mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 14:33:34 +00:00
Move language settings (#2426)
* added date formatting according to chosen language * deleted spaces * deleted spaces * fixed typos * set date formats after * move * add L LT --------- Co-authored-by: Artsiom Voitas <artsiom.voitas@gmail.com>
This commit is contained in:
parent
dee3ca0524
commit
312524a860
|
@ -77,6 +77,7 @@ export function generateLocaleDateFormats(language: string) {
|
|||
value: 'L',
|
||||
label: dayjs().locale(language).format('L')
|
||||
},
|
||||
{ value: 'L LT', label: dayjs().locale(language).format('L LT') },
|
||||
{
|
||||
value: 'll',
|
||||
label: dayjs().locale(language).format('ll')
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
import { CheckCircle } from '@phosphor-icons/react';
|
||||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Themes,
|
||||
unitFormatStore,
|
||||
useExplorerLayoutStore,
|
||||
useThemeStore,
|
||||
useUnitFormatStore,
|
||||
useZodForm
|
||||
} from '@sd/client';
|
||||
import { Button, Divider, Form, Select, SelectOption, SwitchField, z } from '@sd/ui';
|
||||
import { useState } from 'react';
|
||||
import { Themes, useExplorerLayoutStore, useThemeStore, useUnitFormatStore } from '@sd/client';
|
||||
import { Select, SelectOption } from '@sd/ui';
|
||||
import i18n from '~/app/I18n';
|
||||
import { useLocale } from '~/hooks';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
|
||||
import { generateLocaleDateFormats } from '../../Explorer/util';
|
||||
import HorizontalScroll from '../../overview/Layout/HorizontalScroll';
|
||||
import { Heading } from '../Layout';
|
||||
import Setting from '../Setting';
|
||||
|
@ -28,12 +23,6 @@ type Theme = {
|
|||
|
||||
type ThemeProps = Theme & { isSelected?: boolean; className?: string };
|
||||
|
||||
const schema = z.object({
|
||||
uiAnimations: z.boolean(),
|
||||
syncThemeWithSystem: z.boolean(),
|
||||
blurEffects: z.boolean()
|
||||
});
|
||||
|
||||
const themes: Theme[] = [
|
||||
{
|
||||
insideColor: 'bg-white',
|
||||
|
@ -61,32 +50,42 @@ const themes: Theme[] = [
|
|||
}
|
||||
];
|
||||
|
||||
// Unsorted list of languages available in the app.
|
||||
const LANGUAGE_OPTIONS = [
|
||||
{ value: 'en', label: 'English (US)' },
|
||||
{ value: 'en_gb', label: 'English (UK)' },
|
||||
{ value: 'de', label: 'Deutsch' },
|
||||
{ value: 'es', label: 'Español' },
|
||||
{ value: 'fr', label: 'Français' },
|
||||
{ value: 'tr', label: 'Türkçe' },
|
||||
{ value: 'nl', label: 'Nederlands' },
|
||||
{ value: 'be', label: 'Беларуская' },
|
||||
{ value: 'ru', label: 'Русский' },
|
||||
{ value: 'zh_CN', label: '中文(简体)' },
|
||||
{ value: 'zh_TW', label: '中文(繁體)' },
|
||||
{ value: 'it', label: 'Italiano' },
|
||||
{ value: 'ja', label: '日本語' }
|
||||
];
|
||||
|
||||
// Sort the languages by their label
|
||||
LANGUAGE_OPTIONS.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
export const Component = () => {
|
||||
const { lockAppTheme } = usePlatform();
|
||||
const themeStore = useThemeStore();
|
||||
const formatStore = useUnitFormatStore();
|
||||
const explorerLayout = useExplorerLayoutStore();
|
||||
const { t } = useLocale();
|
||||
|
||||
const [dateFormats, setDateFormats] = useState(
|
||||
generateLocaleDateFormats(i18n.resolvedLanguage || i18n.language || 'en')
|
||||
);
|
||||
|
||||
const { t, dateFormat, setDateFormat } = useLocale();
|
||||
|
||||
const [selectedTheme, setSelectedTheme] = useState<Theme['themeValue']>(
|
||||
themeStore.syncThemeWithSystem === true ? 'system' : themeStore.theme
|
||||
);
|
||||
|
||||
const form = useZodForm({
|
||||
schema
|
||||
});
|
||||
|
||||
const onSubmit = form.handleSubmit(async (data) => {
|
||||
console.log({ data });
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = form.watch(() => onSubmit());
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [form, onSubmit]);
|
||||
|
||||
const themeSelectHandler = (theme: Theme['themeValue']) => {
|
||||
setSelectedTheme(theme);
|
||||
if (theme === 'system') {
|
||||
|
@ -103,68 +102,40 @@ export const Component = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const hueSliderHandler = (hue: number) => {
|
||||
themeStore.hueValue = hue;
|
||||
if (themeStore.theme === 'vanilla') {
|
||||
document.documentElement.style.setProperty('--light-hue', hue.toString());
|
||||
} else if (themeStore.theme === 'dark') {
|
||||
document.documentElement.style.setProperty('--dark-hue', hue.toString());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form className="relative" form={form} onSubmit={onSubmit}>
|
||||
<Heading
|
||||
title={t('appearance')}
|
||||
description={t('appearance_description')}
|
||||
rightArea={
|
||||
<div>
|
||||
<Button
|
||||
disabled={themeStore.hueValue === 235}
|
||||
variant={themeStore.hueValue === 235 ? 'outline' : 'accent'}
|
||||
size="sm"
|
||||
className="flex items-center gap-1"
|
||||
onClick={() => {
|
||||
hueSliderHandler(235);
|
||||
}}
|
||||
<Heading title={t('appearance')} description={t('appearance_description')} />
|
||||
<HorizontalScroll className="!mb-5 mt-4 !pl-0">
|
||||
<div className="flex gap-3 md:w-[300px] lg:w-full">
|
||||
{themes.map((theme, i) => {
|
||||
return (
|
||||
<div
|
||||
onClick={() => themeSelectHandler(theme.themeValue)}
|
||||
className={clsx(
|
||||
'shrink-0',
|
||||
selectedTheme !== theme.themeValue &&
|
||||
'opacity-70 transition-all duration-300 hover:opacity-100'
|
||||
)}
|
||||
key={i}
|
||||
>
|
||||
{t('reset')}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<HorizontalScroll className="!mb-5 mt-4 !pl-0">
|
||||
<div className="flex gap-3 md:w-[300px] lg:w-full">
|
||||
{themes.map((theme, i) => {
|
||||
return (
|
||||
<div
|
||||
onClick={() => themeSelectHandler(theme.themeValue)}
|
||||
className={clsx(
|
||||
'shrink-0',
|
||||
selectedTheme !== theme.themeValue &&
|
||||
'opacity-70 transition-all duration-300 hover:opacity-100'
|
||||
)}
|
||||
key={i}
|
||||
>
|
||||
{theme.themeValue === 'system' ? (
|
||||
<SystemTheme
|
||||
{...theme}
|
||||
isSelected={selectedTheme === 'system'}
|
||||
/>
|
||||
) : (
|
||||
<Theme
|
||||
{...theme}
|
||||
isSelected={selectedTheme === theme.themeValue}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</HorizontalScroll>
|
||||
{theme.themeValue === 'system' ? (
|
||||
<SystemTheme
|
||||
{...theme}
|
||||
isSelected={selectedTheme === 'system'}
|
||||
/>
|
||||
) : (
|
||||
<Theme
|
||||
{...theme}
|
||||
isSelected={selectedTheme === theme.themeValue}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</HorizontalScroll>
|
||||
|
||||
{/* {themeStore.theme === 'dark' && (
|
||||
{/* {themeStore.theme === 'dark' && (
|
||||
<Setting mini title="Theme hue value" description="Change the hue of the theme">
|
||||
<div className="mr-3 w-full max-w-[200px] justify-between gap-5">
|
||||
<div className="w-full">
|
||||
|
@ -184,7 +155,7 @@ export const Component = () => {
|
|||
</Setting>
|
||||
)} */}
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* <div className="flex flex-col gap-4">
|
||||
<Setting
|
||||
mini
|
||||
title={t('ui_animations')}
|
||||
|
@ -210,9 +181,51 @@ export const Component = () => {
|
|||
className="m-2 ml-4"
|
||||
/>
|
||||
</Setting>
|
||||
</div> */}
|
||||
{/* Language Settings */}
|
||||
<Setting mini title={t('language')} description={t('language_description')}>
|
||||
<div className="flex h-[30px] gap-2">
|
||||
<Select
|
||||
value={i18n.resolvedLanguage || i18n.language || 'en'}
|
||||
onChange={(e) => {
|
||||
// add "i18nextLng" key to localStorage and set it to the selected language
|
||||
localStorage.setItem('i18nextLng', e);
|
||||
i18n.changeLanguage(e);
|
||||
|
||||
setDateFormats(generateLocaleDateFormats(e));
|
||||
}}
|
||||
containerClassName="h-[30px] whitespace-nowrap"
|
||||
>
|
||||
{LANGUAGE_OPTIONS.map((lang, key) => (
|
||||
<SelectOption key={key} value={lang.value}>
|
||||
{lang.label}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</Form>
|
||||
<Divider />
|
||||
</Setting>
|
||||
{/* Date Formatting Settings */}
|
||||
<Setting mini title={t('date_format')} description={t('date_format_description')}>
|
||||
<div className="flex h-[30px] gap-2">
|
||||
<Select
|
||||
value={dateFormat}
|
||||
onChange={(e) => {
|
||||
// add "dateFormat" key to localStorage and set it as default date format
|
||||
localStorage.setItem('sd-date-format', e);
|
||||
setDateFormat(e);
|
||||
}}
|
||||
containerClassName="h-[30px] whitespace-nowrap"
|
||||
>
|
||||
{dateFormats.map((format, key) => (
|
||||
<SelectOption key={key} value={format.value}>
|
||||
{format.label}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</Setting>
|
||||
|
||||
{/* <Divider /> */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="mb-3 text-lg font-bold text-ink">{t('default_settings')}</h1>
|
||||
<Setting
|
||||
|
@ -230,10 +243,9 @@ export const Component = () => {
|
|||
</Select>
|
||||
</Setting>
|
||||
</div>
|
||||
<Divider />
|
||||
{/* <Divider />
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="mb-3 text-lg font-bold text-ink">{t('display_formats')}</h1>
|
||||
|
||||
<Setting mini title={t('coordinates')}>
|
||||
<Select
|
||||
onChange={(e) => (unitFormatStore.coordinatesFormat = e)}
|
||||
|
@ -263,7 +275,7 @@ export const Component = () => {
|
|||
<SelectOption value="fahrenheit">{t('fahrenheit')}</SelectOption>
|
||||
</Select>
|
||||
</Setting>
|
||||
</div>
|
||||
</div> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import clsx from 'clsx';
|
||||
import dayjs from 'dayjs';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider } from 'react-hook-form';
|
||||
import {
|
||||
useBridgeMutation,
|
||||
|
@ -11,38 +9,16 @@ import {
|
|||
useZodForm
|
||||
} from '@sd/client';
|
||||
import { Button, Card, Input, Select, SelectOption, Slider, Switch, tw, z } from '@sd/ui';
|
||||
import i18n from '~/app/I18n';
|
||||
import { Icon } from '~/components';
|
||||
import { useDebouncedFormWatch, useLocale } from '~/hooks';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
|
||||
import { generateLocaleDateFormats } from '../../Explorer/util';
|
||||
import { Heading } from '../Layout';
|
||||
import Setting from '../Setting';
|
||||
|
||||
const NodePill = tw.div`px-1.5 py-[2px] rounded text-xs font-medium bg-app-selected`;
|
||||
const NodeSettingLabel = tw.div`mb-1 text-xs font-medium`;
|
||||
|
||||
// Unsorted list of languages available in the app.
|
||||
const LANGUAGE_OPTIONS = [
|
||||
{ value: 'en', label: 'English (US)' },
|
||||
{ value: 'en_gb', label: 'English (UK)' },
|
||||
{ value: 'de', label: 'Deutsch' },
|
||||
{ value: 'es', label: 'Español' },
|
||||
{ value: 'fr', label: 'Français' },
|
||||
{ value: 'tr', label: 'Türkçe' },
|
||||
{ value: 'nl', label: 'Nederlands' },
|
||||
{ value: 'be', label: 'Беларуская' },
|
||||
{ value: 'ru', label: 'Русский' },
|
||||
{ value: 'zh_CN', label: '中文(简体)' },
|
||||
{ value: 'zh_TW', label: '中文(繁體)' },
|
||||
{ value: 'it', label: 'Italiano' },
|
||||
{ value: 'ja', label: '日本語' }
|
||||
];
|
||||
|
||||
// Sort the languages by their label
|
||||
LANGUAGE_OPTIONS.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
const u16 = () => z.number().min(0).max(65535);
|
||||
|
||||
export const Component = () => {
|
||||
|
@ -54,9 +30,7 @@ export const Component = () => {
|
|||
// const image_labeler_versions = useBridgeQuery(['models.image_detection.list']);
|
||||
const updateThumbnailerPreferences = useBridgeMutation('nodes.updateThumbnailerPreferences');
|
||||
|
||||
const [dateFormats, setDateFormats] = useState(
|
||||
generateLocaleDateFormats(i18n.resolvedLanguage || i18n.language || 'en')
|
||||
);
|
||||
const { t } = useLocale();
|
||||
|
||||
const form = useZodForm({
|
||||
schema: z
|
||||
|
@ -132,8 +106,6 @@ export const Component = () => {
|
|||
}
|
||||
});
|
||||
|
||||
const { t, dateFormat, setDateFormat } = useLocale();
|
||||
|
||||
const isP2PWipFeatureEnabled = useFeatureFlag('wipP2P');
|
||||
|
||||
return (
|
||||
|
@ -230,48 +202,6 @@ export const Component = () => {
|
|||
</div> */}
|
||||
</div>
|
||||
</Card>
|
||||
{/* Language Settings */}
|
||||
<Setting mini title={t('language')} description={t('language_description')}>
|
||||
<div className="flex h-[30px] gap-2">
|
||||
<Select
|
||||
value={i18n.resolvedLanguage || i18n.language || 'en'}
|
||||
onChange={(e) => {
|
||||
// add "i18nextLng" key to localStorage and set it to the selected language
|
||||
localStorage.setItem('i18nextLng', e);
|
||||
i18n.changeLanguage(e);
|
||||
|
||||
setDateFormats(generateLocaleDateFormats(e));
|
||||
}}
|
||||
containerClassName="h-[30px] whitespace-nowrap"
|
||||
>
|
||||
{LANGUAGE_OPTIONS.map((lang, key) => (
|
||||
<SelectOption key={key} value={lang.value}>
|
||||
{lang.label}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</Setting>
|
||||
{/* Date Formatting Settings */}
|
||||
<Setting mini title={t('date_format')} description={t('date_format_description')}>
|
||||
<div className="flex h-[30px] gap-2">
|
||||
<Select
|
||||
value={dateFormat}
|
||||
onChange={(e) => {
|
||||
// add "dateFormat" key to localStorage and set it as default date format
|
||||
localStorage.setItem('sd-date-format', e);
|
||||
setDateFormat(e);
|
||||
}}
|
||||
containerClassName="h-[30px] whitespace-nowrap"
|
||||
>
|
||||
{dateFormats.map((format, key) => (
|
||||
<SelectOption key={key} value={format.value}>
|
||||
{format.label}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</Setting>
|
||||
{/* Debug Mode */}
|
||||
<Setting mini title={t('debug_mode')} description={t('debug_mode_description')}>
|
||||
<Switch
|
||||
|
|
Loading…
Reference in a new issue