1
1
import React , { useState , useEffect } from 'react' ;
2
2
import {
3
3
Form ,
4
+ Button ,
4
5
Modal ,
5
6
} from 'antd' ;
6
7
import 'typeface-montserrat' ;
@@ -13,6 +14,7 @@ import MatchNotFoundContent from './modalContent/MatchNotFoundContent';
13
14
import MatchCancelledContent from './modalContent/MatchCancelledContent' ;
14
15
import useMatching from '../services/use-matching' ;
15
16
import { ValidateUser } from '../services/user' ;
17
+ import { useTimer } from 'react-timer-hook' ;
16
18
17
19
interface MatchingModalProps {
18
20
isOpen : boolean ;
@@ -23,12 +25,30 @@ export interface MatchParams {
23
25
topics : string [ ] ,
24
26
difficulties : string [ ] ,
25
27
}
28
+ const MATCH_TIMEOUT = 30 ;
29
+ const JOIN_TIMEOUT = 5 ;
26
30
27
31
const MatchingModal : React . FC < MatchingModalProps > = ( { isOpen, close : _close } ) => {
28
32
const matchingState = useMatching ( ) ;
29
33
const [ closedType , setClosedType ] = useState < "finding" | "cancelled" | "joined" > ( "finding" ) ;
30
- const [ timeoutAfter , setTimeoutAfter ] = useState < number > ( 9999 ) ;
31
34
const isClosable = [ "timeout" , "closed" ] . includes ( matchingState . state ) ;
35
+ const { totalSeconds, pause : pauseTimer , restart : restartTimer } = useTimer ( {
36
+ expiryTimestamp : new Date ( Date . now ( ) + MATCH_TIMEOUT * 1000 ) ,
37
+ autoStart : false ,
38
+ onExpire ( ) {
39
+ if ( matchingState . state === "matching" ) {
40
+ matchingState . timeout ( ) ;
41
+ return ;
42
+ }
43
+ if ( matchingState . state === "found" ) {
44
+ matchingState . ok ( ) ;
45
+ setClosedType ( "joined" ) ;
46
+ return ;
47
+ }
48
+ console . warn ( `matching is in ${ matchingState . state } ` )
49
+ } ,
50
+ } ) ;
51
+ const passed = MATCH_TIMEOUT - totalSeconds ;
32
52
33
53
function close ( ) {
34
54
// clean up matching and closedType State
@@ -49,42 +69,56 @@ const MatchingModal: React.FC<MatchingModalProps> = ({ isOpen, close: _close })
49
69
} ) ;
50
70
} : undefined ;
51
71
72
+ useEffect ( ( ) => {
73
+ if ( matchingState . state === "cancelling" || matchingState . state === "timeout" ) {
74
+ pauseTimer ( ) ;
75
+ return ;
76
+ }
77
+ if ( matchingState . state === "found" ) {
78
+ restartTimer (
79
+ new Date ( Date . now ( ) + JOIN_TIMEOUT * 1000 ) ,
80
+ )
81
+ }
82
+ } , [ matchingState ] )
83
+
52
84
const renderModalContent = ( ) => {
53
85
switch ( matchingState . state ) {
54
86
case 'closed' :
55
87
switch ( closedType ) {
56
88
case "finding" :
57
- return < FindMatchContent beginMatch = { matchingState . start } /> ;
89
+ return < FindMatchContent beginMatch = { params => {
90
+ restartTimer (
91
+ new Date ( Date . now ( ) + MATCH_TIMEOUT * 1000 ) ,
92
+ ) ;
93
+ matchingState . start ( params ) ;
94
+ } } /> ;
58
95
case "cancelled" :
59
96
return < MatchCancelledContent
60
97
reselect = { ( ) => {
61
98
setClosedType ( "finding" ) ;
62
99
} }
63
- canceledIn = { timeoutAfter }
100
+ canceledIn = { passed }
64
101
/> ;
65
102
case "joined" :
66
103
return < JoinedMatchContent
67
- cancel = { ( ) => {
68
- setClosedType ( "cancelled" ) ;
69
- } }
70
- name1 = { matchingState . info ?. myName || "" }
71
- name2 = { matchingState . info ?. partnerName || "" }
104
+ cancel = { ( ) => {
105
+ setClosedType ( "cancelled" ) ;
106
+ } }
107
+ name1 = { matchingState . info ?. myName ?? "" }
108
+ name2 = { matchingState . info ?. partnerName ?? "" }
72
109
/> ;
73
110
}
74
111
case 'matching' :
75
112
return < MatchingInProgressContent
76
- cancelMatch = { ( timeoutAfter : number ) => {
113
+ cancelMatch = { ( ) => {
77
114
setClosedType ( "cancelled" ) ;
78
- setTimeoutAfter ( timeoutAfter ) ;
79
115
matchingState . cancel ( ) ;
116
+ pauseTimer ( ) ;
80
117
} }
81
- timeout = { ( timeoutAfter : number ) => {
82
- matchingState . timeout ( )
83
- setTimeoutAfter ( timeoutAfter ) ;
84
- } }
118
+ timePassed = { passed }
85
119
/> ;
86
120
case 'cancelling' :
87
- return < MatchingInProgressContent cancelMatch = { ( ) => { } } timeout = { ( ) => { } } /> ;
121
+ return < MatchingInProgressContent cancelMatch = { ( ) => { } } timePassed = { passed } /> ;
88
122
case 'starting' :
89
123
return < FindMatchContent beginMatch = { ( ) => { } } />
90
124
case 'found' :
@@ -99,9 +133,10 @@ const MatchingModal: React.FC<MatchingModalProps> = ({ isOpen, close: _close })
99
133
} }
100
134
name1 = { matchingState . info . myName }
101
135
name2 = { matchingState . info . partnerName }
102
- />
136
+ joiningIn = { totalSeconds }
137
+ />
103
138
case 'timeout' :
104
- return < MatchNotFoundContent reselect = { matchingState . ok } timedOutIn = { 10 } /> ;
139
+ return < MatchNotFoundContent reselect = { matchingState . ok } timedOutIn = { passed } /> ;
105
140
default :
106
141
throw new Error ( 'Invalid matching state.' ) ;
107
142
}
0 commit comments