1
1
import prompt from 'custom-electron-prompt' ;
2
2
3
+ import { DataConnection } from 'peerjs' ;
4
+
3
5
import { t } from '@/i18n' ;
4
6
import { createPlugin } from '@/utils' ;
5
7
import promptOptions from '@/providers/prompt-options' ;
@@ -17,7 +19,6 @@ import style from './style.css?inline';
17
19
import type { YoutubePlayer } from '@/types/youtube-player' ;
18
20
import type { RendererContext } from '@/types/contexts' ;
19
21
import type { VideoDataChanged } from '@/types/video-data-changed' ;
20
- import { DataConnection } from 'peerjs' ;
21
22
22
23
type RawAccountData = {
23
24
accountName : {
@@ -34,7 +35,44 @@ type RawAccountData = {
34
35
} ;
35
36
} ;
36
37
37
- export default createPlugin ( {
38
+ export default createPlugin <
39
+ unknown ,
40
+ unknown ,
41
+ {
42
+ connection ?: Connection ;
43
+ ipc ?: RendererContext < never > [ 'ipc' ] ;
44
+ api : HTMLElement & AppAPI | null ;
45
+ queue ?: Queue ;
46
+ playerApi ?: YoutubePlayer ;
47
+ showPrompt : ( title : string , label : string ) => Promise < string > ;
48
+ popups : {
49
+ host : ReturnType < typeof createHostPopup > ;
50
+ guest : ReturnType < typeof createGuestPopup > ;
51
+ setting : ReturnType < typeof createSettingPopup > ;
52
+ } ;
53
+ elements : {
54
+ setting : HTMLElement ;
55
+ icon : SVGElement ;
56
+ spinner : HTMLElement ;
57
+ } ;
58
+ stateInterval ?: number ;
59
+ updateNext : boolean ;
60
+ ignoreChange : boolean ;
61
+ rollbackInjector ?: ( ( ) => void ) ;
62
+ me ?: Omit < Profile , 'id' > ;
63
+ profiles : Record < string , Profile > ;
64
+ permission : Permission ;
65
+ videoChangeListener : ( event : CustomEvent < VideoDataChanged > ) => void ;
66
+ videoStateChangeListener : ( ) => void ;
67
+ onHost : ( ) => Promise < boolean > ;
68
+ onJoin : ( ) => Promise < boolean > ;
69
+ onStop : ( ) => void ;
70
+ putProfile : ( id : string , profile ?: Profile ) => void ;
71
+ showSpinner : ( ) => void ;
72
+ hideSpinner : ( ) => void ;
73
+ initMyProfile : ( ) => void ;
74
+ }
75
+ > ( {
38
76
name : ( ) => t ( 'plugins.music-together.name' ) ,
39
77
description : ( ) => t ( 'plugins.music-together.description' ) ,
40
78
restartNeeded : false ,
@@ -43,50 +81,38 @@ export default createPlugin({
43
81
enabled : false
44
82
} ,
45
83
stylesheets : [ style ] ,
46
- backend : {
47
- async start ( { ipc } ) {
48
- ipc . handle ( 'music-together:prompt' , async ( title : string , label : string ) => prompt ( {
49
- title,
50
- label,
51
- type : 'input' ,
52
- ...promptOptions ( )
53
- } ) ) ;
54
- }
84
+ backend ( { ipc } ) {
85
+ ipc . handle ( 'music-together:prompt' , async ( title : string , label : string ) => prompt ( {
86
+ title,
87
+ label,
88
+ type : 'input' ,
89
+ ...promptOptions ( )
90
+ } ) ) ;
55
91
} ,
56
92
renderer : {
57
- connection : null as Connection | null ,
58
- ipc : null as RendererContext < never > [ 'ipc' ] | null ,
59
-
60
- api : null as ( HTMLElement & AppAPI ) | null ,
61
- queue : null as Queue | null ,
62
- playerApi : null as YoutubePlayer | null ,
63
- showPrompt : ( async ( ) => null ) as ( ( title : string , label : string ) => Promise < string | null > ) ,
64
-
65
- elements : { } as {
66
- setting : HTMLElement ;
67
- icon : SVGElement ;
68
- spinner : HTMLElement ;
69
- } ,
93
+ updateNext : false ,
94
+ ignoreChange : false ,
95
+ permission : 'playlist' ,
70
96
popups : { } as {
71
97
host : ReturnType < typeof createHostPopup > ;
72
98
guest : ReturnType < typeof createGuestPopup > ;
73
99
setting : ReturnType < typeof createSettingPopup > ;
74
100
} ,
75
- stateInterval : null as number | null ,
76
- updateNext : false ,
77
- ignoreChange : false ,
78
- rollbackInjector : null as ( ( ) => void ) | null ,
79
-
80
- me : null as Omit < Profile , 'id' > | null ,
81
- profiles : { } as Record < string , Profile > ,
82
- permission : 'playlist' as Permission ,
101
+ elements : { } as {
102
+ setting : HTMLElement ;
103
+ icon : SVGElement ;
104
+ spinner : HTMLElement ;
105
+ } ,
106
+ profiles : { } ,
107
+ showPrompt : ( ) => Promise . resolve ( '' ) ,
108
+ api : null ,
83
109
84
110
/* events */
85
111
videoChangeListener ( event : CustomEvent < VideoDataChanged > ) {
86
112
if ( event . detail . name === 'dataloaded' || this . updateNext ) {
87
113
if ( this . connection ?. mode === 'host' ) {
88
- const videoList : VideoData [ ] = this . queue ?. flatItems . map ( ( it : any ) => ( {
89
- videoId : it . videoId ,
114
+ const videoList : VideoData [ ] = this . queue ?. flatItems . map ( ( it ) => ( {
115
+ videoId : it ! . videoId ,
90
116
ownerId : this . connection ! . id
91
117
} satisfies VideoData ) ) ?? [ ] ;
92
118
@@ -123,8 +149,8 @@ export default createPlugin({
123
149
if ( ! wait ) return false ;
124
150
125
151
if ( ! this . me ) this . me = getDefaultProfile ( this . connection . id ) ;
126
- const rawItems = this . queue ?. flatItems ?. map ( ( it : any ) => ( {
127
- videoId : it . videoId ,
152
+ const rawItems = this . queue ?. flatItems ?. map ( ( it ) => ( {
153
+ videoId : it ! . videoId ,
128
154
ownerId : this . connection ! . id
129
155
} satisfies VideoData ) ) ?? [ ] ;
130
156
this . queue ?. setOwner ( {
@@ -170,7 +196,7 @@ export default createPlugin({
170
196
case 'REMOVE_SONG' : {
171
197
if ( conn && this . permission === 'host-only' ) return ;
172
198
173
- await this . queue ?. removeVideo ( event . payload . index ) ;
199
+ this . queue ?. removeVideo ( event . payload . index ) ;
174
200
await this . connection ?. broadcast ( 'REMOVE_SONG' , event . payload ) ;
175
201
break ;
176
202
}
@@ -295,11 +321,11 @@ export default createPlugin({
295
321
break ;
296
322
}
297
323
case 'REMOVE_SONG' : {
298
- await this . queue ?. removeVideo ( event . payload . index ) ;
324
+ this . queue ?. removeVideo ( event . payload . index ) ;
299
325
break ;
300
326
}
301
327
case 'MOVE_SONG' : {
302
- await this . queue ?. moveItem ( event . payload . fromIndex , event . payload . toIndex ) ;
328
+ this . queue ?. moveItem ( event . payload . fromIndex , event . payload . toIndex ) ;
303
329
break ;
304
330
}
305
331
case 'IDENTIFY' : {
@@ -461,7 +487,7 @@ export default createPlugin({
461
487
this . queue ?. removeQueueOwner ( ) ;
462
488
if ( this . rollbackInjector ) {
463
489
this . rollbackInjector ( ) ;
464
- this . rollbackInjector = null ;
490
+ this . rollbackInjector = undefined ;
465
491
}
466
492
467
493
this . profiles = { } ;
@@ -530,7 +556,7 @@ export default createPlugin({
530
556
531
557
start ( { ipc } ) {
532
558
this . ipc = ipc ;
533
- this . showPrompt = async ( title : string , label : string ) => ipc . invoke ( 'music-together:prompt' , title , label ) ;
559
+ this . showPrompt = async ( title : string , label : string ) => ipc . invoke ( 'music-together:prompt' , title , label ) as Promise < string > ;
534
560
this . api = document . querySelector < HTMLElement & AppAPI > ( 'ytmusic-app' ) ;
535
561
536
562
/* setup */
@@ -571,10 +597,15 @@ export default createPlugin({
571
597
}
572
598
573
599
if ( id === 'music-together-copy-id' ) {
574
- navigator . clipboard . writeText ( this . connection ?. id ?? '' ) ;
575
-
576
- this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copied' ) ) ;
577
- hostPopup . dismiss ( ) ;
600
+ navigator . clipboard . writeText ( this . connection ?. id ?? '' )
601
+ . then ( ( ) => {
602
+ this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copied' ) ) ;
603
+ hostPopup . dismiss ( ) ;
604
+ } )
605
+ . catch ( ( ) => {
606
+ this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copy-failed' ) ) ;
607
+ hostPopup . dismiss ( ) ;
608
+ } ) ;
578
609
}
579
610
580
611
if ( id === 'music-together-permission' ) {
@@ -614,9 +645,14 @@ export default createPlugin({
614
645
this . hideSpinner ( ) ;
615
646
616
647
if ( result ) {
617
- navigator . clipboard . writeText ( this . connection ?. id ?? '' ) ;
618
- this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copied' ) ) ;
619
- hostPopup . showAtAnchor ( setting ) ;
648
+ navigator . clipboard . writeText ( this . connection ?. id ?? '' )
649
+ . then ( ( ) => {
650
+ this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copied' ) ) ;
651
+ hostPopup . showAtAnchor ( setting ) ;
652
+ } ) . catch ( ( ) => {
653
+ this . api ?. openToast ( t ( 'plugins.music-together.toast.id-copy-failed' ) ) ;
654
+ hostPopup . showAtAnchor ( setting ) ;
655
+ } ) ;
620
656
} else {
621
657
this . api ?. openToast ( t ( 'plugins.music-together.toast.host-failed' ) ) ;
622
658
}
@@ -642,7 +678,7 @@ export default createPlugin({
642
678
guest : guestPopup ,
643
679
setting : settingPopup
644
680
} ;
645
- setting . addEventListener ( 'click' , async ( ) => {
681
+ setting . addEventListener ( 'click' , ( ) => {
646
682
let popup = settingPopup ;
647
683
if ( this . connection ?. mode === 'host' ) popup = hostPopup ;
648
684
if ( this . connection ?. mode === 'guest' ) popup = guestPopup ;
0 commit comments