import isElectron from 'is-electron'; import { useTranslation } from 'react-i18next'; import { languages } from '/@/i18n/i18n'; import { SettingOption, SettingsSection, } from '/@/renderer/features/settings/components/settings-section'; import { useLyricsDisplaySettings, useLyricsSettings, useSettingsStore, useSettingsStoreActions, } from '/@/renderer/store'; import { Fieldset } from '/@/shared/components/fieldset/fieldset'; import { MultiSelect } from '/@/shared/components/multi-select/multi-select'; import { NumberInput } from '/@/shared/components/number-input/number-input'; import { SegmentedControl } from '/@/shared/components/segmented-control/segmented-control'; import { Select } from '/@/shared/components/select/select'; import { Slider } from '/@/shared/components/slider/slider'; import { Stack } from '/@/shared/components/stack/stack'; import { Switch } from '/@/shared/components/switch/switch'; import { TextInput } from '/@/shared/components/text-input/text-input'; import { Text } from '/@/shared/components/text/text'; import { LyricSource } from '/@/shared/types/domain-types'; const localSettings = isElectron() ? window.api.localSettings : null; interface LyricsSettingsFormProps { settingsKey: string; } export const LyricsSettingsForm = ({ settingsKey }: LyricsSettingsFormProps) => { const { t } = useTranslation(); const lyricsSettings = useLyricsSettings(); const displaySettings = useLyricsDisplaySettings(settingsKey); const allLyricsDisplay = useSettingsStore((state) => state.lyricsDisplay); const { setSettings } = useSettingsStoreActions(); const updateLyricsSetting = (updates: Partial) => { setSettings({ lyrics: { ...lyricsSettings, ...updates, }, }); }; const updateDisplaySetting = (updates: Partial) => { setSettings({ lyricsDisplay: { ...allLyricsDisplay, [settingsKey]: { ...displaySettings, ...updates, }, }, }); }; const displayOptions: SettingOption[] = [ { control: ( { const value = Number(e.currentTarget.value); updateDisplaySetting({ fontSize: value }); }} rightSection={ px } step={1} value={displaySettings.fontSize} width={100} /> ), description: '', title: t( `${t('page.fullscreenPlayer.config.lyricSize')} (${t('page.fullscreenPlayer.config.synchronized')})`, { postProcess: 'sentenceCase' }, ), }, { control: ( { const value = Number(e.currentTarget.value); updateDisplaySetting({ fontSizeUnsync: value }); }} rightSection={ px } step={1} value={displaySettings.fontSizeUnsync} width={100} /> ), description: '', title: t( `${t('page.fullscreenPlayer.config.lyricSize')} (${t('page.fullscreenPlayer.config.unsynchronized')})`, { postProcess: 'sentenceCase' }, ), }, { control: ( { const value = Number(e.currentTarget.value); updateDisplaySetting({ gap: value }); }} rightSection={ px } step={1} value={displaySettings.gap} width={100} /> ), description: '', title: t( `${t('page.fullscreenPlayer.config.lyricGap')} (${t('page.fullscreenPlayer.config.synchronized')})`, { postProcess: 'sentenceCase' }, ), }, { control: ( { const value = Number(e.currentTarget.value); updateDisplaySetting({ gapUnsync: value }); }} rightSection={ px } step={1} value={displaySettings.gapUnsync} width={100} /> ), description: '', title: t( `${t('page.fullscreenPlayer.config.lyricGap')} (${t('page.fullscreenPlayer.config.unsynchronized')})`, { postProcess: 'sentenceCase' }, ), }, { control: ( updateLyricsSetting({ alignment: value as 'center' | 'left' | 'right' }) } value={lyricsSettings.alignment} /> ), description: '', title: t('page.fullscreenPlayer.config.lyricAlignment', { postProcess: 'sentenceCase', }), }, { control: ( updateLyricsSetting({ follow: e.currentTarget.checked })} /> ), description: '', title: t('page.fullscreenPlayer.config.followCurrentLyric', { postProcess: 'sentenceCase', }), }, { control: ( (e * 100).toFixed(0) + '%'} max={1.0} min={0.0} onChangeEnd={(e) => { updateDisplaySetting({ opacityNonActive: e, }); }} step={0.01} w={100} /> ), description: '', title: t(`${t('page.fullscreenPlayer.config.lyricOpacityNonActive')}`, { postProcess: 'sentenceCase', }), }, { control: ( (e * 100).toFixed(0) + '%'} max={1.0} min={0.5} onChangeEnd={(e) => { updateDisplaySetting({ scaleNonActive: e, }); }} step={0.01} w={100} /> ), description: '', title: t(`${t('page.fullscreenPlayer.config.lyricScaleNonActive')}`, { postProcess: 'sentenceCase', }), }, { control: ( updateLyricsSetting({ showMatch: e.currentTarget.checked })} /> ), description: '', title: t('page.fullscreenPlayer.config.showLyricMatch', { postProcess: 'sentenceCase', }), }, { control: ( updateLyricsSetting({ showProvider: e.currentTarget.checked })} /> ), description: '', title: t('page.fullscreenPlayer.config.showLyricProvider', { postProcess: 'sentenceCase', }), }, ]; const lyricOptions: SettingOption[] = [ { control: ( updateLyricsSetting({ preferLocalLyrics: e.currentTarget.checked }) } /> ), description: t('setting.preferLocalLyrics', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.preferLocalLyrics', { postProcess: 'sentenceCase' }), }, { control: ( updateLyricsSetting({ fetch: e.currentTarget.checked })} /> ), description: t('setting.lyricFetch', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.lyricFetch', { postProcess: 'sentenceCase' }), }, { control: ( { localSettings?.set('lyrics', e); updateLyricsSetting({ sources: e.map((source) => source as LyricSource) }); }} width={300} /> ), description: t('setting.lyricFetchProvider', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.lyricFetchProvider', { postProcess: 'sentenceCase' }), }, { control: ( { const isChecked = e.currentTarget.checked; updateLyricsSetting({ enableNeteaseTranslation: isChecked }); localSettings?.set('enableNeteaseTranslation', isChecked); }} /> ), description: t('setting.neteaseTranslation', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.neteaseTranslation', { postProcess: 'sentenceCase' }), }, { control: ( { const value = Number(e.currentTarget.value); updateLyricsSetting({ delayMs: value }); }} step={10} width={100} /> ), description: t('setting.lyricOffset', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.lyricOffset', { postProcess: 'sentenceCase' }), }, { control: ( { updateLyricsSetting({ translationApiProvider: value }); }} value={lyricsSettings.translationApiProvider} /> ), description: t('setting.translationApiProvider', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.translationApiProvider', { postProcess: 'sentenceCase' }), }, { control: ( { updateLyricsSetting({ translationApiKey: e.currentTarget.value }); }} value={lyricsSettings.translationApiKey} /> ), description: t('setting.translationApiKey', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.translationApiKey', { postProcess: 'sentenceCase' }), }, { control: ( updateLyricsSetting({ enableAutoTranslation: e.currentTarget.checked }) } /> ), description: t('setting.enableAutoTranslation', { context: 'description', postProcess: 'sentenceCase', }), isHidden: !isElectron(), title: t('setting.enableAutoTranslation', { postProcess: 'sentenceCase' }), }, ]; return (
); };