feat: migrate from raw HTML to JSX (TSX / SolidJS) (#3583)

Co-authored-by: Su-Yong <simssy2205@gmail.com>
This commit is contained in:
JellyBrick
2025-07-09 23:14:11 +09:00
committed by GitHub
parent 9ccd126eee
commit e114e0ef44
90 changed files with 1723 additions and 1357 deletions

View File

@ -1,11 +1,12 @@
import { dialog } from 'electron';
import QualitySettingsTemplate from './templates/qualitySettingsTemplate.html?raw';
import { render } from 'solid-js/web';
import { createPlugin } from '@/utils';
import { ElementFromHtml } from '@/plugins/utils/renderer';
import { t } from '@/i18n';
import { QualitySettingButton } from './templates/quality-setting-button';
import type { YoutubePlayer } from '@/types/youtube-player';
export default createPlugin({
@ -18,7 +19,7 @@ export default createPlugin({
backend({ ipc, window }) {
ipc.handle(
'qualityChanger',
'ytmd:quality-changer',
async (qualityLabels: string[], currentIndex: number) =>
await dialog.showMessageBox(window, {
type: 'question',
@ -42,40 +43,48 @@ export default createPlugin({
},
renderer: {
qualitySettingsButton: ElementFromHtml(QualitySettingsTemplate),
qualitySettingsButtonContainer: document.createElement('div'),
onPlayerApiReady(api: YoutubePlayer, context) {
const getPlayer = () =>
document.querySelector<HTMLVideoElement>('#player');
const chooseQuality = () => {
setTimeout(() => getPlayer()?.click());
const chooseQuality = async (e: MouseEvent) => {
e.stopPropagation();
const qualityLevels = api.getAvailableQualityLevels();
const currentIndex = qualityLevels.indexOf(api.getPlaybackQuality());
(
context.ipc.invoke(
'qualityChanger',
api.getAvailableQualityLabels(),
currentIndex,
) as Promise<{ response: number }>
).then((promise) => {
if (promise.response === -1) {
return;
}
const quality = (await context.ipc.invoke(
'ytmd:quality-changer',
api.getAvailableQualityLabels(),
currentIndex,
)) as {
response: number;
};
const newQuality = qualityLevels[promise.response];
api.setPlaybackQualityRange(newQuality);
api.setPlaybackQuality(newQuality);
});
if (quality.response === -1) {
return;
}
const newQuality = qualityLevels[quality.response];
api.setPlaybackQualityRange(newQuality);
api.setPlaybackQuality(newQuality);
};
render(
() => (
<QualitySettingButton
label={t(
'plugins.quality-changer.renderer.quality-settings-button.label',
)}
onClick={chooseQuality}
/>
),
this.qualitySettingsButtonContainer,
);
const setup = () => {
document
.querySelector('.top-row-buttons.ytmusic-player')
?.prepend(this.qualitySettingsButton);
this.qualitySettingsButton.addEventListener('click', chooseQuality);
?.prepend(this.qualitySettingsButtonContainer);
};
setup();
@ -83,7 +92,7 @@ export default createPlugin({
stop() {
document
.querySelector('.top-row-buttons.ytmusic-player')
?.removeChild(this.qualitySettingsButton);
?.removeChild(this.qualitySettingsButtonContainer);
},
},
});

View File

@ -0,0 +1,42 @@
export interface QualitySettingButtonProps {
label: string;
onClick: (event: MouseEvent) => void;
}
export const QualitySettingButton = (props: QualitySettingButtonProps) => (
<yt-icon-button
aria-disabled={false}
aria-label={props.label}
class="player-quality-button style-scope ytmusic-player"
icon={'yt-icons:settings'}
role={'button'}
tabindex={0}
title={props.label}
on:click={props.onClick}
>
<span class="yt-icon-shape style-scope yt-icon yt-spec-icon-shape">
<div
style={{
width: '100%',
height: '100%',
display: 'block',
fill: 'currentcolor',
}}
>
<svg
class="style-scope yt-icon"
preserveAspectRatio="xMidYMid meet"
style="pointer-events: none; display: block; width: 100%; height: 100%"
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
class="style-scope yt-icon"
d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.1-1.65c.2-.15.25-.42.13-.64l-2-3.46c-.12-.22-.4-.3-.6-.22l-2.5 1c-.52-.4-1.08-.73-1.7-.98l-.37-2.65c-.06-.24-.27-.42-.5-.42h-4c-.27 0-.48.18-.5.42l-.4 2.65c-.6.25-1.17.6-1.7.98l-2.48-1c-.23-.1-.5 0-.6.22l-2 3.46c-.14.22-.08.5.1.64l2.12 1.65c-.04.32-.07.65-.07.98s.02.66.06.98l-2.1 1.65c-.2.15-.25.42-.13.64l2 3.46c.12.22.4.3.6.22l2.5-1c.52.4 1.08.73 1.7.98l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.6-.25 1.17-.6 1.7-.98l2.48 1c.23.1.5 0 .6-.22l2-3.46c.13-.22.08-.5-.1-.64l-2.12-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"
></path>
</g>
</svg>
</div>
</span>
</yt-icon-button>
);

View File

@ -1,26 +0,0 @@
<tp-yt-paper-icon-button
aria-disabled="false"
aria-label="Open player quality changer"
class="player-quality-button style-scope ytmusic-player"
icon="yt-icons:settings"
role="button"
tabindex="0"
title="Open player quality changer"
>
<tp-yt-iron-icon class="style-scope tp-yt-paper-icon-button" id="icon">
<svg
class="style-scope yt-icon"
focusable="false"
preserveAspectRatio="xMidYMid meet"
style="pointer-events: none; display: block; width: 100%; height: 100%"
viewBox="0 0 24 24"
>
<g class="style-scope yt-icon">
<path
class="style-scope yt-icon"
d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.1-1.65c.2-.15.25-.42.13-.64l-2-3.46c-.12-.22-.4-.3-.6-.22l-2.5 1c-.52-.4-1.08-.73-1.7-.98l-.37-2.65c-.06-.24-.27-.42-.5-.42h-4c-.27 0-.48.18-.5.42l-.4 2.65c-.6.25-1.17.6-1.7.98l-2.48-1c-.23-.1-.5 0-.6.22l-2 3.46c-.14.22-.08.5.1.64l2.12 1.65c-.04.32-.07.65-.07.98s.02.66.06.98l-2.1 1.65c-.2.15-.25.42-.13.64l2 3.46c.12.22.4.3.6.22l2.5-1c.52.4 1.08.73 1.7.98l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.6-.25 1.17-.6 1.7-.98l2.48 1c.23.1.5 0 .6-.22l2-3.46c.13-.22.08-.5-.1-.64l-2.12-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"
></path>
</g>
</svg>
</tp-yt-iron-icon>
</tp-yt-paper-icon-button>