|
|
|
@@ -1,5 +1,3 @@
|
|
|
|
|
import type { CSSProperties, Dispatch, FC, KeyboardEvent, SetStateAction } from 'react'
|
|
|
|
|
|
|
|
|
|
import { useEffect, useMemo, useState } from 'react'
|
|
|
|
|
import { Helmet } from 'react-helmet-async'
|
|
|
|
|
import { useLocation, useNavigate } from 'react-router-dom'
|
|
|
|
@@ -18,38 +16,35 @@ import { Button } from '@/components/ui/button'
|
|
|
|
|
import { toast } from '@/components/ui/use-toast'
|
|
|
|
|
import { SITE_TITLE } from '@/config'
|
|
|
|
|
import { apiPut } from '@/lib/api'
|
|
|
|
|
import {
|
|
|
|
|
applyThemeSelection,
|
|
|
|
|
BUILTIN_THEMES,
|
|
|
|
|
createCustomThemeFromBase,
|
|
|
|
|
defaultThemeTagColoursFor,
|
|
|
|
|
DEFAULT_USER_SETTINGS,
|
|
|
|
|
deriveUserThemeModeFromSelection,
|
|
|
|
|
fetchUserSettings,
|
|
|
|
|
hasStoredClientThemeSelection,
|
|
|
|
|
getClientActiveThemeId,
|
|
|
|
|
getClientCustomThemes,
|
|
|
|
|
getResolvedThemeFromSelection,
|
|
|
|
|
setClientAppearanceThemes,
|
|
|
|
|
updateUserSettings,
|
|
|
|
|
} from '@/lib/settings'
|
|
|
|
|
import { applyThemeSelection,
|
|
|
|
|
BUILTIN_THEMES,
|
|
|
|
|
createCustomThemeFromBase,
|
|
|
|
|
defaultThemeTagColoursFor,
|
|
|
|
|
DEFAULT_USER_SETTINGS,
|
|
|
|
|
deriveUserThemeModeFromSelection,
|
|
|
|
|
fetchUserSettings,
|
|
|
|
|
hasStoredClientThemeSelection,
|
|
|
|
|
getClientActiveThemeId,
|
|
|
|
|
getClientCustomThemes,
|
|
|
|
|
getResolvedThemeFromSelection,
|
|
|
|
|
setClientAppearanceThemes,
|
|
|
|
|
updateUserSettings } from '@/lib/settings'
|
|
|
|
|
import { useKeyboardShortcutSettings } from '@/lib/useKeyboardShortcuts'
|
|
|
|
|
import { cn, inputClass } from '@/lib/utils'
|
|
|
|
|
import { useValidationErrors } from '@/lib/useValidationErrors'
|
|
|
|
|
|
|
|
|
|
import type { CSSProperties, Dispatch, FC, KeyboardEvent, SetStateAction } from 'react'
|
|
|
|
|
|
|
|
|
|
import type { Category, Tag, User } from '@/types'
|
|
|
|
|
import type {
|
|
|
|
|
ActiveThemeId,
|
|
|
|
|
ClientTheme,
|
|
|
|
|
CustomClientTheme,
|
|
|
|
|
ThemeTagColours,
|
|
|
|
|
UserSettings,
|
|
|
|
|
} from '@/lib/settings'
|
|
|
|
|
import type { ActiveThemeId,
|
|
|
|
|
ClientTheme,
|
|
|
|
|
CustomClientTheme,
|
|
|
|
|
ThemeTagColours,
|
|
|
|
|
UserSettings } from '@/lib/settings'
|
|
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
user: User | null
|
|
|
|
|
setUser: Dispatch<SetStateAction<User | null>>
|
|
|
|
|
}
|
|
|
|
|
setUser: Dispatch<SetStateAction<User | null>> }
|
|
|
|
|
|
|
|
|
|
type UserFormField = 'name'
|
|
|
|
|
type SettingsFormField = 'theme'
|
|
|
|
@@ -79,14 +74,12 @@ type SharedSectionProps = {
|
|
|
|
|
onResetTagColour: (category: Category) => void
|
|
|
|
|
onThemeSubmit: () => void
|
|
|
|
|
settingsBaseErrors: string[]
|
|
|
|
|
settingsFieldErrors: Partial<Record<SettingsFormField, string[]>>
|
|
|
|
|
}
|
|
|
|
|
settingsFieldErrors: Partial<Record<SettingsFormField, string[]>> }
|
|
|
|
|
|
|
|
|
|
const tabs: TabSpec[] = [
|
|
|
|
|
{ id: 'account', label: 'アカウント' },
|
|
|
|
|
{ id: 'theme', label: 'テーマ' },
|
|
|
|
|
{ id: 'keyboard', label: 'キーボード' },
|
|
|
|
|
]
|
|
|
|
|
{ id: 'keyboard', label: 'キーボード' } ]
|
|
|
|
|
|
|
|
|
|
const sectionClassName =
|
|
|
|
|
'space-y-4 rounded-xl border border-border bg-background/80 p-4'
|
|
|
|
@@ -94,13 +87,12 @@ const sectionClassName =
|
|
|
|
|
const themeLabel: Record<UserSettings['theme'], string> = {
|
|
|
|
|
system: 'システム設定に従う',
|
|
|
|
|
light: 'ライト・モード',
|
|
|
|
|
dark: 'ダーク・モード',
|
|
|
|
|
}
|
|
|
|
|
dark: 'ダーク・モード' }
|
|
|
|
|
|
|
|
|
|
const builtinThemeLabel: Record<'light' | 'dark', string> = {
|
|
|
|
|
light: 'ライト・モード',
|
|
|
|
|
dark: 'ダーク・モード',
|
|
|
|
|
}
|
|
|
|
|
dark: 'ダーク・モード' }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const previewTag = (
|
|
|
|
|
id: number,
|
|
|
|
@@ -122,8 +114,7 @@ const previewTag = (
|
|
|
|
|
hasWiki,
|
|
|
|
|
materialId: null,
|
|
|
|
|
hasDeerjikists: options?.hasDeerjikists ?? false,
|
|
|
|
|
children: [],
|
|
|
|
|
})
|
|
|
|
|
children: [] })
|
|
|
|
|
|
|
|
|
|
const previewTags: Record<Category, Tag> = {
|
|
|
|
|
deerjikist: previewTag (1, 'にじらー', 'deerjikist', 12, true, { hasDeerjikists: true }),
|
|
|
|
@@ -132,15 +123,14 @@ const previewTags: Record<Category, Tag> = {
|
|
|
|
|
general: previewTag (4, '一般', 'general', 78, true),
|
|
|
|
|
material: previewTag (5, '素材', 'material', 90, false),
|
|
|
|
|
meta: previewTag (6, 'メタ', 'meta', 21, true),
|
|
|
|
|
nico: previewTag (7, 'nico:sm9', 'nico', 43, false),
|
|
|
|
|
}
|
|
|
|
|
nico: previewTag (7, 'nico:sm9', 'nico', 43, false) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const parseTab = (search: string): SettingsTab => {
|
|
|
|
|
const tab = new URLSearchParams (search).get ('tab')
|
|
|
|
|
return tabs.some (candidate => candidate.id === tab)
|
|
|
|
|
? tab as SettingsTab
|
|
|
|
|
: 'account'
|
|
|
|
|
return (tabs.some (candidate => candidate.id === tab)
|
|
|
|
|
? (tab as SettingsTab)
|
|
|
|
|
: 'account')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -152,9 +142,7 @@ const themePreviewStyle = (tagColours: ThemeTagColours): CSSProperties =>
|
|
|
|
|
Object.fromEntries (
|
|
|
|
|
CATEGORIES.flatMap (category => [
|
|
|
|
|
[`--tag-colour-${ category }`, tagColours[category]],
|
|
|
|
|
[`--tag-colour-${ category }-hover`, tagColours[category]],
|
|
|
|
|
]),
|
|
|
|
|
) as CSSProperties
|
|
|
|
|
[`--tag-colour-${ category }-hover`, tagColours[category]]])) as CSSProperties
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const themeLabelById = (
|
|
|
|
@@ -169,16 +157,16 @@ const themeLabelById = (
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const AccountSection: FC<SharedSectionProps> = ({
|
|
|
|
|
name,
|
|
|
|
|
onInheritOpen,
|
|
|
|
|
onNameChange,
|
|
|
|
|
onUserCodeOpen,
|
|
|
|
|
onUserSubmit,
|
|
|
|
|
user,
|
|
|
|
|
userBaseErrors,
|
|
|
|
|
userFieldErrors,
|
|
|
|
|
}) => (
|
|
|
|
|
const AccountSection: FC<SharedSectionProps> = (
|
|
|
|
|
{ name,
|
|
|
|
|
onInheritOpen,
|
|
|
|
|
onNameChange,
|
|
|
|
|
onUserCodeOpen,
|
|
|
|
|
onUserSubmit,
|
|
|
|
|
user,
|
|
|
|
|
userBaseErrors,
|
|
|
|
|
userFieldErrors },
|
|
|
|
|
) => (
|
|
|
|
|
<section className={sectionClassName}>
|
|
|
|
|
<h2 className="text-xl font-bold">アカウント</h2>
|
|
|
|
|
<FieldError messages={userBaseErrors}/>
|
|
|
|
@@ -229,20 +217,20 @@ const AccountSection: FC<SharedSectionProps> = ({
|
|
|
|
|
</section>)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ThemeSection: FC<SharedSectionProps> = ({
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
draftCustomThemes,
|
|
|
|
|
selectedTheme,
|
|
|
|
|
draftTagColours,
|
|
|
|
|
onEnsureEditableTheme,
|
|
|
|
|
onResetAllTagColours,
|
|
|
|
|
onResetTagColour,
|
|
|
|
|
onTagColourChange,
|
|
|
|
|
onThemeChange,
|
|
|
|
|
onThemeSubmit,
|
|
|
|
|
settingsBaseErrors,
|
|
|
|
|
settingsFieldErrors,
|
|
|
|
|
}) => (
|
|
|
|
|
const ThemeSection: FC<SharedSectionProps> = (
|
|
|
|
|
{ draftActiveThemeId,
|
|
|
|
|
draftCustomThemes,
|
|
|
|
|
selectedTheme,
|
|
|
|
|
draftTagColours,
|
|
|
|
|
onEnsureEditableTheme,
|
|
|
|
|
onResetAllTagColours,
|
|
|
|
|
onResetTagColour,
|
|
|
|
|
onTagColourChange,
|
|
|
|
|
onThemeChange,
|
|
|
|
|
onThemeSubmit,
|
|
|
|
|
settingsBaseErrors,
|
|
|
|
|
settingsFieldErrors },
|
|
|
|
|
) => (
|
|
|
|
|
<section className={sectionClassName}>
|
|
|
|
|
<h2 className="text-xl font-bold">テーマ</h2>
|
|
|
|
|
<FieldError messages={settingsBaseErrors}/>
|
|
|
|
@@ -389,24 +377,20 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
useState<Record<string, CustomClientTheme>> (getClientCustomThemes ())
|
|
|
|
|
const [userCodeVsbl, setUserCodeVsbl] = useState (false)
|
|
|
|
|
const { conflictActionIds } = useKeyboardShortcutSettings ()
|
|
|
|
|
const {
|
|
|
|
|
baseErrors: userBaseErrors,
|
|
|
|
|
fieldErrors: userFieldErrors,
|
|
|
|
|
clearValidationErrors: clearUserValidationErrors,
|
|
|
|
|
applyValidationError: applyUserValidationError,
|
|
|
|
|
} = useValidationErrors<UserFormField> ()
|
|
|
|
|
const {
|
|
|
|
|
baseErrors: settingsBaseErrors,
|
|
|
|
|
fieldErrors: settingsFieldErrors,
|
|
|
|
|
clearValidationErrors: clearSettingsValidationErrors,
|
|
|
|
|
applyValidationError: applySettingsValidationError,
|
|
|
|
|
} = useValidationErrors<SettingsFormField> ()
|
|
|
|
|
const { baseErrors: userBaseErrors,
|
|
|
|
|
fieldErrors: userFieldErrors,
|
|
|
|
|
clearValidationErrors: clearUserValidationErrors,
|
|
|
|
|
applyValidationError: applyUserValidationError } = useValidationErrors<UserFormField> ()
|
|
|
|
|
const { baseErrors: settingsBaseErrors,
|
|
|
|
|
fieldErrors: settingsFieldErrors,
|
|
|
|
|
clearValidationErrors: clearSettingsValidationErrors,
|
|
|
|
|
applyValidationError: applySettingsValidationError } =
|
|
|
|
|
useValidationErrors<SettingsFormField> ()
|
|
|
|
|
|
|
|
|
|
const activeTab = useMemo<SettingsTab> (() => parseTab (location.search), [location.search])
|
|
|
|
|
const selectedTheme = useMemo<ClientTheme> (
|
|
|
|
|
() => getResolvedThemeFromSelection (draftActiveThemeId, draftCustomThemes),
|
|
|
|
|
[draftActiveThemeId, draftCustomThemes],
|
|
|
|
|
)
|
|
|
|
|
[draftActiveThemeId, draftCustomThemes])
|
|
|
|
|
const draftTagColours = selectedTheme.tokens.tagColours
|
|
|
|
|
|
|
|
|
|
const setActiveTab = (tab: SettingsTab) => {
|
|
|
|
@@ -414,15 +398,15 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
params.set ('tab', tab)
|
|
|
|
|
navigate (
|
|
|
|
|
`${ location.pathname }?${ params.toString () }`,
|
|
|
|
|
{ replace: true },
|
|
|
|
|
)
|
|
|
|
|
{ replace: true })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const settingsTabErrors = useMemo<Record<SettingsTab, boolean>> (() => ({
|
|
|
|
|
account: Boolean (userFieldErrors.name?.length),
|
|
|
|
|
theme: Boolean (settingsFieldErrors.theme?.length),
|
|
|
|
|
keyboard: conflictActionIds.size > 0,
|
|
|
|
|
}), [conflictActionIds.size, settingsFieldErrors.theme, userFieldErrors.name])
|
|
|
|
|
const settingsTabErrors = useMemo<Record<SettingsTab, boolean>> (
|
|
|
|
|
() => (
|
|
|
|
|
{ account: Boolean (userFieldErrors.name?.length),
|
|
|
|
|
theme: Boolean (settingsFieldErrors.theme?.length),
|
|
|
|
|
keyboard: conflictActionIds.size > 0 }),
|
|
|
|
|
[conflictActionIds.size, settingsFieldErrors.theme, userFieldErrors.name])
|
|
|
|
|
|
|
|
|
|
const applyDraftThemeSelection = (
|
|
|
|
|
activeThemeId: ActiveThemeId,
|
|
|
|
@@ -432,52 +416,40 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
setDraftCustomThemes (customThemes)
|
|
|
|
|
setDraftSettings (current => ({
|
|
|
|
|
...current,
|
|
|
|
|
theme: deriveUserThemeModeFromSelection (activeThemeId, customThemes),
|
|
|
|
|
}))
|
|
|
|
|
theme: deriveUserThemeModeFromSelection (activeThemeId, customThemes) }))
|
|
|
|
|
applyThemeSelection (activeThemeId, customThemes)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ensureEditableCustomTheme = (): {
|
|
|
|
|
activeThemeId: ActiveThemeId
|
|
|
|
|
customThemes: Record<string, CustomClientTheme>
|
|
|
|
|
} => {
|
|
|
|
|
customThemes: Record<string, CustomClientTheme> } => {
|
|
|
|
|
if (draftActiveThemeId !== 'system' && draftCustomThemes[draftActiveThemeId] != null)
|
|
|
|
|
{
|
|
|
|
|
return {
|
|
|
|
|
activeThemeId: draftActiveThemeId,
|
|
|
|
|
customThemes: draftCustomThemes,
|
|
|
|
|
}
|
|
|
|
|
return { activeThemeId: draftActiveThemeId,
|
|
|
|
|
customThemes: draftCustomThemes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const customTheme = createCustomThemeFromBase (
|
|
|
|
|
selectedTheme.baseTheme,
|
|
|
|
|
{
|
|
|
|
|
...selectedTheme.tokens,
|
|
|
|
|
tagColours: { ...selectedTheme.tokens.tagColours },
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
{ ...selectedTheme.tokens,
|
|
|
|
|
tagColours: { ...selectedTheme.tokens.tagColours } })
|
|
|
|
|
const nextCustomThemes = {
|
|
|
|
|
...draftCustomThemes,
|
|
|
|
|
[customTheme.id]: customTheme,
|
|
|
|
|
}
|
|
|
|
|
[customTheme.id]: customTheme }
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
activeThemeId: customTheme.id,
|
|
|
|
|
customThemes: nextCustomThemes,
|
|
|
|
|
}
|
|
|
|
|
customThemes: nextCustomThemes }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleEnsureEditableTheme = (): {
|
|
|
|
|
activeThemeId: ActiveThemeId
|
|
|
|
|
customThemes: Record<string, CustomClientTheme>
|
|
|
|
|
} => {
|
|
|
|
|
customThemes: Record<string, CustomClientTheme> } => {
|
|
|
|
|
const editable = ensureEditableCustomTheme ()
|
|
|
|
|
|
|
|
|
|
if (editable.activeThemeId !== draftActiveThemeId
|
|
|
|
|
|| editable.customThemes !== draftCustomThemes)
|
|
|
|
|
{
|
|
|
|
|
applyDraftThemeSelection (editable.activeThemeId, editable.customThemes)
|
|
|
|
|
}
|
|
|
|
|
applyDraftThemeSelection (editable.activeThemeId, editable.customThemes)
|
|
|
|
|
|
|
|
|
|
return editable
|
|
|
|
|
}
|
|
|
|
@@ -580,9 +552,9 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
const customThemes = getClientCustomThemes ()
|
|
|
|
|
const activeThemeId = hasStoredClientThemeSelection ()
|
|
|
|
|
? getClientActiveThemeId ()
|
|
|
|
|
: data.theme
|
|
|
|
|
const activeThemeId = (hasStoredClientThemeSelection ()
|
|
|
|
|
? getClientActiveThemeId ()
|
|
|
|
|
: data.theme)
|
|
|
|
|
const themeMode = deriveUserThemeModeFromSelection (activeThemeId, customThemes)
|
|
|
|
|
|
|
|
|
|
setDraftSettings ({ ...data, theme: themeMode })
|
|
|
|
@@ -629,71 +601,62 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
}
|
|
|
|
|
}, [draftActiveThemeId, draftCustomThemes, savedActiveThemeId, savedCustomThemes])
|
|
|
|
|
|
|
|
|
|
const sectionProps: SharedSectionProps | null = user ? {
|
|
|
|
|
user,
|
|
|
|
|
name,
|
|
|
|
|
onNameChange: setName,
|
|
|
|
|
onInheritOpen: () => setInheritVsbl (true),
|
|
|
|
|
onUserCodeOpen: () => setUserCodeVsbl (true),
|
|
|
|
|
onUserSubmit: handleUserSubmit,
|
|
|
|
|
userBaseErrors,
|
|
|
|
|
userFieldErrors,
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
draftCustomThemes,
|
|
|
|
|
selectedTheme,
|
|
|
|
|
draftTagColours,
|
|
|
|
|
onThemeChange: themeId => {
|
|
|
|
|
applyDraftThemeSelection (themeId, draftCustomThemes)
|
|
|
|
|
},
|
|
|
|
|
onEnsureEditableTheme: () => {
|
|
|
|
|
handleEnsureEditableTheme ()
|
|
|
|
|
},
|
|
|
|
|
onTagColourChange: (category, colour) => {
|
|
|
|
|
const editable = handleEnsureEditableTheme ()
|
|
|
|
|
const editableTheme = editable.customThemes[editable.activeThemeId]
|
|
|
|
|
const nextCustomThemes = {
|
|
|
|
|
...editable.customThemes,
|
|
|
|
|
[editable.activeThemeId]: {
|
|
|
|
|
...editableTheme,
|
|
|
|
|
tokens: {
|
|
|
|
|
...editableTheme.tokens,
|
|
|
|
|
tagColours: {
|
|
|
|
|
...editableTheme.tokens.tagColours,
|
|
|
|
|
[category]: colour,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
applyDraftThemeSelection (editable.activeThemeId, nextCustomThemes)
|
|
|
|
|
},
|
|
|
|
|
onResetAllTagColours: () => {
|
|
|
|
|
if (selectedTheme.builtin || draftActiveThemeId === 'system')
|
|
|
|
|
return
|
|
|
|
|
const sectionProps: SharedSectionProps | null =
|
|
|
|
|
user
|
|
|
|
|
? { user,
|
|
|
|
|
name,
|
|
|
|
|
onNameChange: setName,
|
|
|
|
|
onInheritOpen: () => setInheritVsbl (true),
|
|
|
|
|
onUserCodeOpen: () => setUserCodeVsbl (true),
|
|
|
|
|
onUserSubmit: handleUserSubmit,
|
|
|
|
|
userBaseErrors,
|
|
|
|
|
userFieldErrors,
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
draftCustomThemes,
|
|
|
|
|
selectedTheme,
|
|
|
|
|
draftTagColours,
|
|
|
|
|
onThemeChange: themeId => {
|
|
|
|
|
applyDraftThemeSelection (themeId, draftCustomThemes)
|
|
|
|
|
},
|
|
|
|
|
onEnsureEditableTheme: () => {
|
|
|
|
|
handleEnsureEditableTheme ()
|
|
|
|
|
},
|
|
|
|
|
onTagColourChange: (category, colour) => {
|
|
|
|
|
const editable = handleEnsureEditableTheme ()
|
|
|
|
|
const editableTheme = editable.customThemes[editable.activeThemeId]
|
|
|
|
|
const nextCustomThemes = {
|
|
|
|
|
...editable.customThemes,
|
|
|
|
|
[editable.activeThemeId]: {
|
|
|
|
|
...editableTheme,
|
|
|
|
|
tokens: {
|
|
|
|
|
...editableTheme.tokens,
|
|
|
|
|
tagColours: {
|
|
|
|
|
...editableTheme.tokens.tagColours,
|
|
|
|
|
[category]: colour } } } }
|
|
|
|
|
applyDraftThemeSelection (editable.activeThemeId, nextCustomThemes)
|
|
|
|
|
},
|
|
|
|
|
onResetAllTagColours: () => {
|
|
|
|
|
if (selectedTheme.builtin || draftActiveThemeId === 'system')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
applyDraftThemeSelection (
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
{
|
|
|
|
|
...draftCustomThemes,
|
|
|
|
|
[draftActiveThemeId]: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId],
|
|
|
|
|
tokens: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId].tokens,
|
|
|
|
|
tagColours: {
|
|
|
|
|
...defaultThemeTagColoursFor (selectedTheme.baseTheme),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
onResetTagColour: category => {
|
|
|
|
|
if (selectedTheme.builtin || draftActiveThemeId === 'system')
|
|
|
|
|
return
|
|
|
|
|
applyDraftThemeSelection (
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
{
|
|
|
|
|
...draftCustomThemes,
|
|
|
|
|
[draftActiveThemeId]: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId],
|
|
|
|
|
tokens: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId].tokens,
|
|
|
|
|
tagColours: {
|
|
|
|
|
...defaultThemeTagColoursFor (selectedTheme.baseTheme) } } } })
|
|
|
|
|
},
|
|
|
|
|
onResetTagColour: category => {
|
|
|
|
|
if (selectedTheme.builtin || draftActiveThemeId === 'system')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
applyDraftThemeSelection (
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
{
|
|
|
|
|
...draftCustomThemes,
|
|
|
|
|
applyDraftThemeSelection (
|
|
|
|
|
draftActiveThemeId,
|
|
|
|
|
{ ...draftCustomThemes,
|
|
|
|
|
[draftActiveThemeId]: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId],
|
|
|
|
|
tokens: {
|
|
|
|
@@ -701,17 +664,13 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
tagColours: {
|
|
|
|
|
...draftCustomThemes[draftActiveThemeId].tokens.tagColours,
|
|
|
|
|
[category]:
|
|
|
|
|
defaultThemeTagColoursFor (selectedTheme.baseTheme)[category],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
onThemeSubmit: handleThemeSubmit,
|
|
|
|
|
settingsBaseErrors,
|
|
|
|
|
settingsFieldErrors,
|
|
|
|
|
} : null
|
|
|
|
|
defaultThemeTagColoursFor (
|
|
|
|
|
selectedTheme.baseTheme)[category] } } } })
|
|
|
|
|
},
|
|
|
|
|
onThemeSubmit: handleThemeSubmit,
|
|
|
|
|
settingsBaseErrors,
|
|
|
|
|
settingsFieldErrors }
|
|
|
|
|
: null
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<MainArea>
|
|
|
|
@@ -752,12 +711,11 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
tabIndex={activeTab === tab.id ? 0 : -1}
|
|
|
|
|
className={cn (
|
|
|
|
|
'rounded-xl border px-4 py-3 text-left text-sm font-medium',
|
|
|
|
|
activeTab === tab.id
|
|
|
|
|
? ['border-slate-900 bg-slate-900 text-white',
|
|
|
|
|
'dark:border-slate-100 dark:bg-slate-100 dark:text-slate-900']
|
|
|
|
|
: ['border-slate-300 bg-white text-slate-700',
|
|
|
|
|
'dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100'],
|
|
|
|
|
)}
|
|
|
|
|
(activeTab === tab.id
|
|
|
|
|
? ['border-slate-900 bg-slate-900 text-white',
|
|
|
|
|
'dark:border-slate-100 dark:bg-slate-100 dark:text-slate-900']
|
|
|
|
|
: ['border-slate-300 bg-white text-slate-700',
|
|
|
|
|
'dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100']))}
|
|
|
|
|
onClick={() => setActiveTab (tab.id)}
|
|
|
|
|
onKeyDown={handleTabKeyDown}>
|
|
|
|
|
{tab.label}
|
|
|
|
@@ -778,8 +736,7 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
{activeTab === 'account' && <AccountSection {...sectionProps}/>}
|
|
|
|
|
{activeTab === 'theme' && <ThemeSection {...sectionProps}/>}
|
|
|
|
|
{activeTab === 'keyboard' && (
|
|
|
|
|
<KeyboardSettingsSection sectionClassName={sectionClassName}/>
|
|
|
|
|
)}
|
|
|
|
|
<KeyboardSettingsSection sectionClassName={sectionClassName}/>)}
|
|
|
|
|
</>)}
|
|
|
|
|
</div>)}
|
|
|
|
|
</div>
|
|
|
|
@@ -799,4 +756,5 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|
|
|
|
</MainArea>)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default SettingPage
|
|
|
|
|