1
1
import React , { useState , useEffect } from 'react' ;
2
2
import { connect } from 'react-redux' ;
3
- import { Container } from 'react-bootstrap' ;
3
+ import { Container , Form } from 'react-bootstrap' ;
4
4
import { useWaterPumpAPI } from '../contexts/WaterPumpAPIContext' ;
5
5
import { startPump , stopPump } from '../store/slices/SystemStatus.js' ;
6
6
7
- export function HoldToPourComponent ( { startPump, stopPump } ) {
8
- const pouringTime = 1500 ;
9
- const api = useWaterPumpAPI ( ) . API ;
7
+ export function HoldToPourComponent ( { startPump, stopPump, interval } ) {
10
8
const [ isPouring , setIsPouring ] = useState ( false ) ;
9
+ const [ clickToPour , setClickToPour ] = useState ( false ) ;
10
+ // continuously pour water while the button is pressed
11
+ const lastPouringTime = React . useRef ( 0 ) ;
12
+ const onTick = React . useCallback (
13
+ async ( ) => {
14
+ if ( Date . now ( ) < lastPouringTime . current ) return ;
15
+ try {
16
+ lastPouringTime . current = Number . MAX_SAFE_INTEGER ; // prevent concurrent calls
17
+ await startPump ( ) ;
18
+ lastPouringTime . current = Date . now ( ) + interval ;
19
+ } catch ( e ) {
20
+ lastPouringTime . current = 0 ; // run again on next tick
21
+ }
22
+ } ,
23
+ [ startPump , interval ]
24
+ ) ;
11
25
12
26
useEffect ( ( ) => {
13
- if ( ! isPouring ) return ;
14
-
15
- const tid = setInterval ( ( ) => {
16
- startPump ( { api, pouringTime } ) ;
17
- } , pouringTime - 500 ) ;
18
-
19
- return ( ) => {
20
- clearInterval ( tid ) ;
21
- stopPump ( { api } ) ;
22
- } ;
23
- } , [ isPouring , api , startPump , stopPump ] ) ;
27
+ if ( ! isPouring ) {
28
+ lastPouringTime . current = 0 ;
29
+ stopPump ( ) ;
30
+ return ;
31
+ }
32
+ // tick every 100ms
33
+ const tid = setInterval ( onTick , 100 ) ;
34
+ return ( ) => { clearInterval ( tid ) ; }
35
+ } , [ onTick , isPouring , stopPump , lastPouringTime ] ) ;
24
36
25
37
const handlePress = ( ) => { setIsPouring ( true ) ; } ;
26
38
const handleRelease = ( ) => { setIsPouring ( false ) ; } ;
27
-
39
+ const handleCheckboxChange = e => { setClickToPour ( e . target . checked ) ; } ;
40
+ const handleToggle = ( ) => { setIsPouring ( ! isPouring ) ; } ;
41
+ // FIX: onMouseDown/onMouseUp is not working on mobile
28
42
return (
29
- < Container className = "d-flex justify-content -center mt-3" >
43
+ < Container className = "d-flex flex-column align-items -center mt-3" >
30
44
< img src = "valve.png" className = 'hold-to-pour-image' alt = "Hold to pour button"
31
- draggable = "false" onMouseDown = { handlePress } onMouseUp = { handleRelease }
45
+ draggable = "false"
46
+ onMouseDown = { clickToPour ? null : handlePress }
47
+ onMouseUp = { clickToPour ? null : handleRelease }
48
+ onClick = { clickToPour ? handleToggle : null }
49
+ />
50
+
51
+ < Form . Check
52
+ type = "checkbox"
53
+ checked = { clickToPour } onChange = { handleCheckboxChange }
54
+ label = {
55
+ < span style = { { color : 'red' , fontSize : '1.5rem' } } >
56
+ Click to pour (< b > dangerous</ b > )
57
+ </ span >
58
+ }
32
59
/>
33
60
</ Container >
34
61
) ;
35
62
}
36
63
64
+ // Helper wrapper to simplify the code in the component
65
+ function HoldToPourComponent_withExtras ( { pouringTime, startPump, stopPump } ) {
66
+ const api = useWaterPumpAPI ( ) . API ;
67
+
68
+ const _startPump = React . useCallback (
69
+ async ( ) => { await startPump ( { api, pouringTime } ) ; } ,
70
+ [ api , startPump , pouringTime ]
71
+ ) ;
72
+ const _stopPump = React . useCallback (
73
+ async ( ) => { await stopPump ( { api } ) ; } ,
74
+ [ api , stopPump ]
75
+ ) ;
76
+ // a bit smaller than the actual pouring time, to prevent the pump from stopping
77
+ // which could damage the pump
78
+ const interval = Math . max ( Math . round ( pouringTime - 500 ) , 100 ) ;
79
+ return (
80
+ < HoldToPourComponent
81
+ startPump = { _startPump } stopPump = { _stopPump }
82
+ interval = { interval }
83
+ />
84
+ ) ;
85
+ } ;
86
+
37
87
export default connect (
38
- state => ( { } ) ,
88
+ state => ( { pouringTime : state . UI . pouringTime } ) ,
39
89
{ startPump, stopPump }
40
- ) ( HoldToPourComponent ) ;
90
+ ) ( HoldToPourComponent_withExtras ) ;
0 commit comments