6
6
*
7
7
* Copyright (C) 2021 hello-slide
8
8
**********************************************************/
9
- import { useToast , Box , Flex } from '@chakra-ui/react' ;
9
+ import { Box , Flex } from '@chakra-ui/react' ;
10
10
import React from 'react' ;
11
11
import { useSetRecoilState } from 'recoil' ;
12
12
import Page from '../../@types/page' ;
13
- import SlidePageData from '../../@types/pageItem ' ;
13
+ import { PageDetails } from '../../@types/slideshow ' ;
14
14
import useShowClose from '../../hooks/useShowClose' ;
15
- import GetPage from '../../utils/api/getPage' ;
16
- import ListPages from '../../utils/api/listPage' ;
15
+ import useShowControl from '../../hooks/useShowControl' ;
17
16
import { SlideshowDataState } from '../../utils/state/atom' ;
18
17
import Load from '../common/Load' ;
19
18
import ChangeContents from './ChangeContetns' ;
20
19
21
20
const ShowController : React . FC < { id : string } > = ( { id} ) => {
22
- const toast = useToast ( ) ;
23
21
const setSlideshowData = useSetRecoilState ( SlideshowDataState ) ;
24
22
const [ index , setIndex ] = React . useState ( 0 ) ;
25
- const [ pageList , setPageList ] = React . useState < Page [ ] > ( [ ] ) ;
26
- const [ load , setIsLoad ] = React . useState ( false ) ;
27
23
const closeShow = useShowClose ( ) ;
28
- let maxPage = 3 ; // header page * 2 and end page.
24
+ const [ isLoad , setIsLoad ] = React . useState ( false ) ;
25
+ const [ maxIndex , setMaxIndex ] = React . useState ( 0 ) ;
26
+ const [ isEndGetPage , setIsEndGetPage ] = React . useState ( false ) ;
27
+ const [ slideData , pageData , load , pageList , setSlideId , getPage ] =
28
+ useShowControl ( ) ;
29
+
30
+ const numberOfPageRef = React . useRef < number > ( ) ;
31
+ const pageRef = React . useRef < AsyncGenerator < PageDetails > > ( ) ;
32
+ const pageDataRef = React . useRef < Page [ ] > ( ) ;
33
+ const pageLockRef = React . useRef < boolean > ( ) ;
29
34
30
35
const keyboardEvent = React . useCallback ( ( event : KeyboardEvent ) => {
31
36
if ( event . code === 'ArrowRight' ) {
32
- nextPage ( false ) ;
37
+ nextPage ( ) ;
33
38
} else if ( event . code === 'ArrowLeft' ) {
34
39
backPage ( ) ;
35
40
}
36
41
} , [ ] ) ;
37
42
38
- const nextPage = ( useJsx : boolean ) => {
39
- setIndex ( value => {
40
- if ( ! useJsx && value >= maxPage ) {
41
- return value ;
42
- } else if ( useJsx && value >= pageList . length + 3 ) {
43
- return value ;
44
- }
45
- return ( value += 1 ) ;
46
- } ) ;
47
- } ;
43
+ const nextPage = ( ) => {
44
+ // The move is locked until the next page is loaded.
45
+ if ( ! pageLockRef . current ) {
46
+ setIndex ( value => {
47
+ if ( numberOfPageRef . current && value >= numberOfPageRef . current ) {
48
+ return value ;
49
+ }
48
50
49
- const backPage = ( ) => {
50
- setIndex ( value => {
51
- if ( value > 0 ) {
52
- return ( value -= 1 ) ;
53
- }
54
- return value ;
55
- } ) ;
51
+ return ( value += 1 ) ;
52
+ } ) ;
53
+ }
56
54
} ;
57
55
58
- const getPage = async (
59
- getPage : GetPage ,
60
- pageId : string
61
- ) : Promise < SlidePageData > => {
62
- return await getPage . run ( id , pageId ) ;
56
+ const backPage = ( ) => {
57
+ // The move is locked until the next page is loaded.
58
+ if ( ! pageLockRef . current ) {
59
+ setIndex ( value => {
60
+ if ( value > 0 ) {
61
+ return ( value -= 1 ) ;
62
+ }
63
+ return value ;
64
+ } ) ;
65
+ }
63
66
} ;
64
67
65
68
React . useEffect ( ( ) => {
66
- if ( index >= pageList . length + 3 ) {
69
+ // The slide show ends when you move to the next page on the last page.
70
+ if ( numberOfPageRef . current && index >= numberOfPageRef . current ) {
67
71
closeShow ( ) ;
68
72
}
73
+
74
+ if ( index >= 2 && maxIndex < index && ! isEndGetPage ) {
75
+ switch ( pageData [ index - 2 ] ?. type ) {
76
+ case 'quiz2' :
77
+ case 'question' :
78
+ pageLockRef . current = true ;
79
+ pageRef . current . next ( ) . then ( value => {
80
+ if ( value . done ) {
81
+ setIsEndGetPage ( true ) ;
82
+ pageLockRef . current = false ;
83
+ return ;
84
+ }
85
+ // Get page data async.
86
+ const result = value . value as PageDetails ;
87
+ setSlideshowData ( value => {
88
+ return [ result , ...value ] ;
89
+ } ) ;
90
+
91
+ pageLockRef . current = false ;
92
+ } ) ;
93
+ break ;
94
+ default :
95
+ break ;
96
+ }
97
+ setMaxIndex ( index ) ;
98
+ }
69
99
} , [ index ] ) ;
70
100
71
101
React . useEffect ( ( ) => {
72
- // reset state
73
102
setSlideshowData ( undefined ) ;
74
103
setIsLoad ( true ) ;
75
104
76
- const listPagesAPI = new ListPages ( ) ;
105
+ if ( id . length !== 0 ) {
106
+ setSlideId ( id ) ;
107
+ }
77
108
78
- const getPageAPI = new GetPage ( ) ;
109
+ return ( ) => {
110
+ document . removeEventListener ( 'keydown' , keyboardEvent , false ) ;
111
+ } ;
112
+ } , [ ] ) ;
79
113
80
- const api = async ( ) => {
81
- try {
82
- const value = await listPagesAPI . run ( id ) ;
114
+ React . useEffect ( ( ) => {
115
+ if ( typeof pageList !== 'undefined' && typeof pageData !== 'undefined' ) {
116
+ numberOfPageRef . current = pageData . length + 3 ;
83
117
84
- const pageLists = [ ] ;
85
- const data : { key : string ; value : SlidePageData } [ ] = [ ] ;
86
- for ( const element of value . pages ) {
87
- if ( element . type === 'quiz' ) {
88
- pageLists . push ( { id : element . page_id , type : 'quiz1' } ) ;
89
- pageLists . push ( { id : element . page_id , type : 'quiz2' } ) ;
90
- } else if ( element . type === 'question' ) {
91
- pageLists . push ( { id : element . page_id , type : 'question' } ) ;
92
- }
118
+ const getter = getPage ( ) ;
119
+ // Load only the first page.
120
+ getter . next ( ) . then ( value => {
121
+ const result = value . value as PageDetails ;
122
+ setSlideshowData ( [ result ] ) ;
123
+ } ) ;
93
124
94
- try {
95
- data . push ( {
96
- key : element . page_id ,
97
- value : await getPage ( getPageAPI , element . page_id ) ,
98
- } ) ;
99
- } catch ( error ) {
100
- toast ( {
101
- title : 'ページを読み込めませんでした。' ,
102
- description : `${ error } ` ,
103
- status : 'error' ,
104
- } ) ;
105
- }
106
- }
107
- setPageList ( pageLists ) ;
108
-
109
- setSlideshowData ( {
110
- title : value . title ,
111
- id : value . id ,
112
- createDate : value . createDate ,
113
- lastChange : value . lastChange ,
114
- data : data ,
115
- } ) ;
116
-
117
- maxPage += pageLists . length ;
118
- document . addEventListener ( 'keydown' , keyboardEvent , false ) ;
119
- } catch ( error ) {
120
- toast ( {
121
- title : 'スライドを読み込めませんでした' ,
122
- description : `${ error } ` ,
123
- status : 'error' ,
124
- } ) ;
125
- }
125
+ pageRef . current = getter ;
126
+ pageDataRef . current = pageData ;
126
127
128
+ document . addEventListener ( 'keydown' , keyboardEvent , false ) ;
127
129
setIsLoad ( false ) ;
128
- } ;
129
- api ( ) ;
130
-
131
- return ( ) => {
132
- document . removeEventListener ( 'keydown' , keyboardEvent , false ) ;
133
- } ;
134
- } , [ ] ) ;
130
+ }
131
+ } , [ pageList , pageData ] ) ;
135
132
136
133
return (
137
134
< >
138
- < Load isLoad = { load } />
135
+ < Load isLoad = { load || isLoad } />
139
136
< Flex
140
137
position = "absolute"
141
138
zIndex = "1000"
@@ -145,9 +142,9 @@ const ShowController: React.FC<{id: string}> = ({id}) => {
145
142
height = "100%"
146
143
>
147
144
< Box width = "50%" height = "100%" onClick = { backPage } />
148
- < Box width = "50%" height = "100%" onClick = { ( ) => nextPage ( true ) } />
145
+ < Box width = "50%" height = "100%" onClick = { ( ) => nextPage ( ) } />
149
146
</ Flex >
150
- < ChangeContents index = { index } pageList = { pageList } />
147
+ < ChangeContents index = { index } pageList = { pageData } slideData = { slideData } />
151
148
</ >
152
149
) ;
153
150
} ;
0 commit comments