Skip to content

Commit 895386f

Browse files
committed
fix(music-together): typing
1 parent 3810955 commit 895386f

File tree

11 files changed

+232
-127
lines changed

11 files changed

+232
-127
lines changed

src/i18n/resources/en.json

+1
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@
472472
"disconnected": "Music Together disconnected",
473473
"host-failed": "Failed to host Music Together",
474474
"id-copied": "Host ID copied to clipboard",
475+
"id-copy-failed": "Failed to copy Host ID to clipboard",
475476
"join-failed": "Failed to join Music Together",
476477
"joined": "Joined Music Together",
477478
"permission-changed": "Music Together permission changed to \"{{permission}}\"",

src/plugins/music-together/index.ts

+85-49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import prompt from 'custom-electron-prompt';
22

3+
import { DataConnection } from 'peerjs';
4+
35
import { t } from '@/i18n';
46
import { createPlugin } from '@/utils';
57
import promptOptions from '@/providers/prompt-options';
@@ -17,7 +19,6 @@ import style from './style.css?inline';
1719
import type { YoutubePlayer } from '@/types/youtube-player';
1820
import type { RendererContext } from '@/types/contexts';
1921
import type { VideoDataChanged } from '@/types/video-data-changed';
20-
import { DataConnection } from 'peerjs';
2122

2223
type RawAccountData = {
2324
accountName: {
@@ -34,7 +35,44 @@ type RawAccountData = {
3435
};
3536
};
3637

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+
>({
3876
name: () => t('plugins.music-together.name'),
3977
description: () => t('plugins.music-together.description'),
4078
restartNeeded: false,
@@ -43,50 +81,38 @@ export default createPlugin({
4381
enabled: false
4482
},
4583
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+
}));
5591
},
5692
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',
7096
popups: {} as {
7197
host: ReturnType<typeof createHostPopup>;
7298
guest: ReturnType<typeof createGuestPopup>;
7399
setting: ReturnType<typeof createSettingPopup>;
74100
},
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,
83109

84110
/* events */
85111
videoChangeListener(event: CustomEvent<VideoDataChanged>) {
86112
if (event.detail.name === 'dataloaded' || this.updateNext) {
87113
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,
90116
ownerId: this.connection!.id
91117
} satisfies VideoData)) ?? [];
92118

@@ -123,8 +149,8 @@ export default createPlugin({
123149
if (!wait) return false;
124150

125151
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,
128154
ownerId: this.connection!.id
129155
} satisfies VideoData)) ?? [];
130156
this.queue?.setOwner({
@@ -170,7 +196,7 @@ export default createPlugin({
170196
case 'REMOVE_SONG': {
171197
if (conn && this.permission === 'host-only') return;
172198

173-
await this.queue?.removeVideo(event.payload.index);
199+
this.queue?.removeVideo(event.payload.index);
174200
await this.connection?.broadcast('REMOVE_SONG', event.payload);
175201
break;
176202
}
@@ -295,11 +321,11 @@ export default createPlugin({
295321
break;
296322
}
297323
case 'REMOVE_SONG': {
298-
await this.queue?.removeVideo(event.payload.index);
324+
this.queue?.removeVideo(event.payload.index);
299325
break;
300326
}
301327
case 'MOVE_SONG': {
302-
await this.queue?.moveItem(event.payload.fromIndex, event.payload.toIndex);
328+
this.queue?.moveItem(event.payload.fromIndex, event.payload.toIndex);
303329
break;
304330
}
305331
case 'IDENTIFY': {
@@ -461,7 +487,7 @@ export default createPlugin({
461487
this.queue?.removeQueueOwner();
462488
if (this.rollbackInjector) {
463489
this.rollbackInjector();
464-
this.rollbackInjector = null;
490+
this.rollbackInjector = undefined;
465491
}
466492

467493
this.profiles = {};
@@ -530,7 +556,7 @@ export default createPlugin({
530556

531557
start({ ipc }) {
532558
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>;
534560
this.api = document.querySelector<HTMLElement & AppAPI>('ytmusic-app');
535561

536562
/* setup */
@@ -571,10 +597,15 @@ export default createPlugin({
571597
}
572598

573599
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+
});
578609
}
579610

580611
if (id === 'music-together-permission') {
@@ -614,9 +645,14 @@ export default createPlugin({
614645
this.hideSpinner();
615646

616647
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+
});
620656
} else {
621657
this.api?.openToast(t('plugins.music-together.toast.host-failed'));
622658
}
@@ -642,7 +678,7 @@ export default createPlugin({
642678
guest: guestPopup,
643679
setting: settingPopup
644680
};
645-
setting.addEventListener('click', async () => {
681+
setting.addEventListener('click', () => {
646682
let popup = settingPopup;
647683
if (this.connection?.mode === 'host') popup = hostPopup;
648684
if (this.connection?.mode === 'guest') popup = guestPopup;

0 commit comments

Comments
 (0)