1
- import { useCallback , useContext , useMemo , ChangeEvent } from 'react' ;
1
+ import { useCallback , useContext , useMemo , useState , ChangeEvent , useRef , useEffect } from 'react' ;
2
2
import { Slider } from '@material-ui/core' ;
3
3
import { createMuiTheme } from '@material-ui/core' ;
4
4
import { ThemeProvider } from '@material-ui/styles' ;
5
+ import ShareIcon from '@material-ui/icons/Share' ;
6
+ import CloseIcon from '@material-ui/icons/Close' ;
7
+ import Button from '@material-ui/core/Button' ;
8
+ import Dialog from '@material-ui/core/Dialog' ;
9
+ import DialogActions from '@material-ui/core/DialogActions' ;
10
+ import DialogContent from '@material-ui/core/DialogContent' ;
11
+ import Checkbox from '@material-ui/core/Checkbox' ;
12
+ import Input from '@material-ui/core/Input' ;
13
+ import FormControlLabel from '@material-ui/core/FormControlLabel' ;
14
+ import tap from 'lodash/tap' ;
5
15
6
16
import { default as Styles } from 'components/Player/Player.module.css' ;
7
17
import { PlayerContext } from 'components/PlayerContext/PlayerContext' ;
18
+ import { useQueryParam } from 'hocs/useQueryParam' ;
8
19
9
20
export function Player ( ) {
10
21
const {
@@ -16,11 +27,54 @@ export function Player() {
16
27
currentEndTime,
17
28
increasePlaybackRate,
18
29
changeCurrentTime,
30
+ closeTrack,
31
+ tracks
19
32
} = useContext ( PlayerContext ) ;
33
+ const [ locationTrack , setLocationTrack ] = useQueryParam ( 'track' ) ;
34
+ const shareInputRef = useRef < HTMLInputElement > ( null )
35
+ const [ shareUrl , changeShareUrl ] = useState < string > ( ( ) => {
36
+ return tap ( new URL ( window . location . toString ( ) ) , url => {
37
+ url . searchParams . set ( 'track' , tracks . findIndex ( track => track . order === currentTrack ?. order ) . toString ( ) ) ;
38
+ url . searchParams . set ( 'currentTime' , '' ) ;
39
+ } ) . toString ( ) ;
40
+ } ) ;
41
+ const [ isShareWithTime , setIsShareWithTime ] = useState ( false ) ;
42
+ const [ isShareDialogOpen , setIsShareDialogOpen ] = useState ( false ) ;
20
43
const onClickControl = useCallback ( ( ) => {
21
44
toggle ( ) ;
22
45
} , [ toggle , isPlayed ] ) ;
23
46
47
+ const toggleShareDialog = useCallback ( ( ) => {
48
+ setIsShareDialogOpen ( state => ! state ) ;
49
+ } , [ ] ) ;
50
+
51
+ const toggleShareWithTime = useCallback ( ( ) => {
52
+ setIsShareWithTime ( state => ! state ) ;
53
+ } , [ isShareWithTime ] ) ;
54
+
55
+ useEffect ( ( ) => {
56
+ changeShareUrl (
57
+ tap ( new URL ( window . location . toString ( ) ) , url => {
58
+ url . searchParams . set ( 'track' , tracks . findIndex ( track => track . order === currentTrack ?. order ) . toString ( ) ) ;
59
+ url . searchParams . set ( 'currentTime' , '' ) ;
60
+ } ) . toString ( )
61
+ ) ;
62
+ } , [ currentTrack ] ) ;
63
+
64
+ useEffect ( ( ) => {
65
+ const url = new URL ( window . location . toString ( ) ) ;
66
+ if ( isShareWithTime ) {
67
+ url . searchParams . set ( 'track' , tracks . findIndex ( track => track . order === currentTrack ?. order ) . toString ( ) ) ;
68
+ url . searchParams . set ( 'currentTime' , currentTime . toString ( ) ) ;
69
+ } else {
70
+ url . searchParams . set ( 'track' , tracks . findIndex ( track => track . order === currentTrack ?. order ) . toString ( ) ) ;
71
+ url . searchParams . set ( 'currentTime' , '' ) ;
72
+ }
73
+
74
+ changeShareUrl ( url . toString ( ) ) ;
75
+
76
+ } , [ isShareWithTime ] )
77
+
24
78
const muiTheme = useMemo ( ( ) => createMuiTheme ( {
25
79
overrides : {
26
80
MuiSlider : {
@@ -39,24 +93,84 @@ export function Player() {
39
93
changeCurrentTime ( newTime ) ;
40
94
} , [ ] ) ;
41
95
96
+ const onCopy = useCallback ( ( ) => {
97
+ if ( ! shareInputRef . current ) {
98
+ return ;
99
+ }
100
+
101
+ shareInputRef . current . focus ( ) ;
102
+ shareInputRef . current . setSelectionRange ( 0 , shareInputRef . current . value . length ) ;
103
+ document . execCommand ( 'copy' ) ;
104
+ setTimeout ( ( ) => toggleShareDialog ( ) , 0 ) ;
105
+ } , [ ] )
106
+
107
+ const onShareFocus = useCallback ( ( ) => {
108
+ if ( ! shareInputRef . current ) {
109
+ return ;
110
+ }
111
+
112
+ shareInputRef . current . setSelectionRange ( 0 , shareInputRef . current . value . length ) ;
113
+ } , [ ] ) ;
114
+
115
+ const onClickTitle = useCallback ( ( ) => {
116
+ setLocationTrack ( tracks . findIndex ( track => track . order === currentTrack ?. order ) . toString ( ) ) ;
117
+ } , [ ] ) ;
118
+
42
119
if ( ! currentTrack ) {
43
120
return null ;
44
121
}
45
122
46
- const { backgroundColor, playColor, length } = currentTrack ;
123
+ const { backgroundColor, playColor } = currentTrack ;
47
124
48
125
49
126
return (
50
- < div className = { Styles . Player } style = { { backgroundColor, color : playColor } } >
51
- < div
52
- className = { [ Styles . Player__Control , isPlayed && Styles . Player__Control_Pause ] . join ( ' ' ) }
53
- style = { { borderColor : `transparent transparent transparent ${ playColor } ` } }
54
- onClick = { onClickControl }
55
- />
56
- < ThemeProvider theme = { muiTheme } >
57
- < Slider className = { Styles . Player__Slider } min = { 0 } max = { currentEndTime } onChange = { onChange } value = { currentTime } />
58
- </ ThemeProvider >
59
- < div className = { Styles . Player__Rate } onClick = { increasePlaybackRate } > x{ playbackRate } </ div >
60
- </ div >
127
+ < >
128
+ < div className = { Styles . PlayerWrapper } >
129
+ < div className = { Styles . Player } style = { { backgroundColor, color : playColor } } >
130
+ < div className = { Styles . Player__Title } >
131
+ < span className = { Styles . Player__TrackTitle } onClick = { onClickTitle } >
132
+ { currentTrack . order } { currentTrack . greeting }
133
+ </ span >
134
+ < div >
135
+ < span className = { Styles . Player__Icon } onClick = { toggleShareDialog } > < ShareIcon /> </ span >
136
+ < span className = { Styles . Player__Icon } onClick = { closeTrack } > < CloseIcon /> </ span >
137
+ </ div >
138
+ </ div >
139
+ < div className = { Styles . Player__Controls } >
140
+ < div
141
+ className = { [ Styles . Player__Control , isPlayed && Styles . Player__Control_Pause ] . join ( ' ' ) }
142
+ style = { { borderColor : `transparent transparent transparent ${ playColor } ` } }
143
+ onClick = { onClickControl }
144
+ />
145
+ < ThemeProvider theme = { muiTheme } >
146
+ < Slider className = { Styles . Player__Slider } min = { 0 } max = { currentEndTime } onChange = { onChange } value = { currentTime } />
147
+ </ ThemeProvider >
148
+ < div className = { Styles . Player__Rate } onClick = { increasePlaybackRate } > x{ playbackRate } </ div >
149
+ </ div >
150
+ </ div >
151
+ </ div >
152
+ < Dialog
153
+ open = { isShareDialogOpen }
154
+ onClose = { toggleShareDialog }
155
+ aria-labelledby = "alert-dialog-title"
156
+ aria-describedby = "alert-dialog-description"
157
+ >
158
+ < DialogContent >
159
+ < Input value = { shareUrl } fullWidth onClick = { onShareFocus } inputRef = { shareInputRef } />
160
+ < FormControlLabel
161
+ control = { < Checkbox checked = { isShareWithTime } onChange = { toggleShareWithTime } /> }
162
+ label = "С текущего момента"
163
+ />
164
+ </ DialogContent >
165
+ < DialogActions >
166
+ < Button onClick = { toggleShareDialog } color = 'secondary' >
167
+ Закрыть
168
+ </ Button >
169
+ < Button onClick = { onCopy } color = 'primary' autoFocus >
170
+ Копировать
171
+ </ Button >
172
+ </ DialogActions >
173
+ </ Dialog >
174
+ </ >
61
175
) ;
62
176
}
0 commit comments