This repository has been archived on 2025-03-19. You can view files and clone it, but cannot push or open issues or pull requests.
feishin/src/renderer/features/settings/components/general/control-settings.tsx
2024-08-22 21:57:58 -07:00

473 lines
17 KiB
TypeScript

import { Group } from '@mantine/core';
import { t } from 'i18next';
import isElectron from 'is-electron';
import { Select, Tooltip, NumberInput, Switch, Slider } from '/@/renderer/components';
import { SettingsSection } from '/@/renderer/features/settings/components/settings-section';
import {
GenreTarget,
SideQueueType,
useGeneralSettings,
useSettingsStoreActions,
} from '/@/renderer/store/settings.store';
import { Play } from '/@/renderer/types';
import { useTranslation } from 'react-i18next';
const localSettings = isElectron() ? window.electron.localSettings : null;
const SIDE_QUEUE_OPTIONS = [
{
label: t('setting.sidePlayQueueStyle', {
context: 'optionAttached',
postProcess: 'sentenceCase',
}),
value: 'sideQueue',
},
{
label: t('setting.sidePlayQueueStyle', {
context: 'optionDetached',
postProcess: 'sentenceCase',
}),
value: 'sideDrawerQueue',
},
];
export const ControlSettings = () => {
const { t } = useTranslation();
const settings = useGeneralSettings();
const { setSettings } = useSettingsStoreActions();
const controlOptions = [
{
control: (
<NumberInput
defaultValue={settings.buttonSize}
max={30}
min={15}
rightSection="px"
width={75}
onBlur={(e) => {
if (!e) return;
const newVal = e.currentTarget.value
? Math.min(Math.max(Number(e.currentTarget.value), 15), 30)
: settings.buttonSize;
setSettings({
general: {
...settings,
buttonSize: newVal,
},
});
}}
/>
),
description: t('setting.buttonSize', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.buttonSize', { postProcess: 'sentenceCase' }),
},
{
control: (
<NumberInput
defaultValue={settings.albumArtRes || undefined}
max={2500}
placeholder="0"
rightSection="px"
value={settings.albumArtRes ?? 0}
width={75}
onBlur={(e) => {
const newVal =
e.currentTarget.value !== '0'
? Math.min(Math.max(Number(e.currentTarget.value), 175), 2500)
: null;
setSettings({ general: { ...settings, albumArtRes: newVal } });
}}
/>
),
description: t('setting.playerAlbumArtResolution', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.playerAlbumArtResolution', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label="Toggle using native aspect ratio"
defaultChecked={settings.nativeAspectRatio}
onChange={(e) =>
setSettings({
general: {
...settings,
nativeAspectRatio: e.currentTarget.checked,
},
})
}
/>
),
description: t('setting.imageAspectRatio', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.imageAspectRatio', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label="Toggle skip buttons"
defaultChecked={settings.skipButtons?.enabled}
onChange={(e) =>
setSettings({
general: {
...settings,
skipButtons: {
...settings.skipButtons,
enabled: e.currentTarget.checked,
},
},
})
}
/>
),
description: t('setting.showSkipButtons', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.showSkipButtons', { postProcess: 'sentenceCase' }),
},
{
control: (
<Group>
<Tooltip label={t('common.backward', { postProcess: 'titleCase' })}>
<NumberInput
defaultValue={settings.skipButtons.skipBackwardSeconds}
min={0}
width={75}
onBlur={(e) =>
setSettings({
general: {
...settings,
skipButtons: {
...settings.skipButtons,
skipBackwardSeconds: e.currentTarget.value
? Number(e.currentTarget.value)
: 0,
},
},
})
}
/>
</Tooltip>
<Tooltip label={t('common.forward', { postProcess: 'titleCase' })}>
<NumberInput
defaultValue={settings.skipButtons.skipForwardSeconds}
min={0}
width={75}
onBlur={(e) =>
setSettings({
general: {
...settings,
skipButtons: {
...settings.skipButtons,
skipForwardSeconds: e.currentTarget.value
? Number(e.currentTarget.value)
: 0,
},
},
})
}
/>
</Tooltip>
</Group>
),
description: t('setting.skipDuration', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.skipDuration', { postProcess: 'sentenceCase' }),
},
{
control: (
<Select
data={[
{
label: t('setting.playButtonBehavior', {
context: 'optionPlay',
postProcess: 'titleCase',
}),
value: Play.NOW,
},
{
label: t('setting.playButtonBehavior', {
context: 'optionAddNext',
postProcess: 'titleCase',
}),
value: Play.NEXT,
},
{
label: t('setting.playButtonBehavior', {
context: 'optionAddLast',
postProcess: 'titleCase',
}),
value: Play.LAST,
},
]}
defaultValue={settings.playButtonBehavior}
onChange={(e) =>
setSettings({
general: {
...settings,
playButtonBehavior: e as Play,
},
})
}
/>
),
description: t('setting.playButtonBehavior', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.playButtonBehavior', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label="Whether double clicking a track should queue all matching songs"
defaultChecked={settings.doubleClickQueueAll}
onChange={(e) =>
setSettings({
general: {
...settings,
doubleClickQueueAll: e.currentTarget.checked,
},
})
}
/>
),
description: t('setting.doubleClickBehavior', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.doubleClickBehavior', { postProcess: 'sentenceCase' }),
},
{
control: (
<Select
data={SIDE_QUEUE_OPTIONS}
defaultValue={settings.sideQueueType}
onChange={(e) => {
setSettings({
general: {
...settings,
sideQueueType: e as SideQueueType,
},
});
}}
/>
),
description: t('setting.sidePlayQueueStyle', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.sidePlayQueueStyle', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
defaultChecked={settings.showQueueDrawerButton}
onChange={(e) => {
setSettings({
general: {
...settings,
showQueueDrawerButton: e.currentTarget.checked,
},
});
}}
/>
),
description: t('setting.sidePlayQueueStyle', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.floatingQueueArea', { postProcess: 'sentenceCase' }),
},
{
control: (
<Slider
defaultValue={settings.volumeWheelStep}
max={20}
min={1}
w={100}
onChangeEnd={(e) => {
setSettings({
general: {
...settings,
volumeWheelStep: e,
},
});
}}
/>
),
description: t('setting.volumeWheelStep', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.volumeWheelStep', { postProcess: 'sentenceCase' }),
},
{
control: (
<NumberInput
defaultValue={settings.volumeWidth}
max={180}
min={30}
placeholder="0"
rightSection="px"
width={75}
onBlur={(e) => {
setSettings({
general: { ...settings, volumeWidth: Number(e.currentTarget.value) },
});
}}
/>
),
description: t('setting.volumeWidth', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.volumeWidth', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
defaultChecked={settings.resume}
onChange={(e) => {
localSettings?.set('resume', e.target.checked);
setSettings({
general: {
...settings,
resume: e.currentTarget.checked,
},
});
}}
/>
),
description: t('setting.savePlayQueue', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: !isElectron(),
title: t('setting.savePlayQueue', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label="Go to playlist songs page by default"
defaultChecked={settings.defaultFullPlaylist}
onChange={(e) =>
setSettings({
general: {
...settings,
defaultFullPlaylist: e.currentTarget.checked,
},
})
}
/>
),
description: t('setting.skipPlaylistPage', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.skipPlaylistPage', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
defaultChecked={settings.externalLinks}
onChange={(e) => {
setSettings({
general: {
...settings,
externalLinks: e.currentTarget.checked,
},
});
}}
/>
),
description: t('setting.externalLinks', {
context: 'description',
postProcess: 'sentenceCase',
}),
title: t('setting.externalLinks', { postProcess: 'sentenceCase' }),
},
{
control: (
<Select
data={[
{
label: t('entity.album_other', {
postProcess: 'titleCase',
}),
value: GenreTarget.ALBUM,
},
{
label: t('entity.track_other', {
postProcess: 'titleCase',
}),
value: GenreTarget.TRACK,
},
]}
defaultValue={settings.genreTarget}
onChange={(e) =>
setSettings({
general: {
...settings,
genreTarget: e as GenreTarget,
},
})
}
/>
),
description: t('setting.genreBehavior', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.genreBehavior', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label={t('setting.homeFeature', { postProcess: 'sentenceCase' })}
defaultChecked={settings.homeFeature}
onChange={(e) =>
setSettings({
general: {
...settings,
homeFeature: e.currentTarget.checked,
},
})
}
/>
),
description: t('setting.homeFeature', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: false,
title: t('setting.homeFeature', { postProcess: 'sentenceCase' }),
},
];
return <SettingsSection options={controlOptions} />;
};