このコミットが含まれているのは:
2026-07-05 11:27:45 +09:00
コミット ca92c62049
11個のファイルの変更1137行の追加92行の削除
+135 -1
ファイルの表示
@@ -51,6 +51,9 @@ export type CustomClientTheme =
export type TheatreLayoutMode = 'threeColumns' | 'tagsBottom' | 'commentsBottom'
export type TheatreTagFlow = 'vertical' | 'horizontal'
export type GekanatorBackgroundMotionMode = 'on' | 'calm' | 'off'
export type ClientAnimationMode = 'normal' | 'reduced' | 'off'
export type ClientEmbedAutoLoadMode = 'auto' | 'manual' | 'off'
export type ClientThumbnailMode = 'normal' | 'light' | 'off'
export type ClientPaneBreakpoint = 'desktop' | 'tablet'
export type ClientListKey = 'postList' | 'postSearch' | 'tagList'
export type ClientListLimit = 20 | 50 | 100
@@ -75,6 +78,12 @@ export type ClientAppearanceSettings = {
theme?: UserSettings['theme']
tagColours?: Partial<ThemeTagColours> }
export type ClientBehaviorSettings = {
animation?: ClientAnimationMode
embedAutoLoad?: ClientEmbedAutoLoadMode
thumbnailMode?: ClientThumbnailMode
}
// DB-backed settings. At present only `theme` is surfaced in `/users/settings`.
// The remaining fields are retained for existing backend work and are not wired
// to the common settings UI yet.
@@ -87,6 +96,7 @@ export const DEFAULT_USER_SETTINGS: UserSettings = {
// Browser-local settings only. These are device or screen specific.
export type ClientSettings = {
appearance?: ClientAppearanceSettings
behavior?: ClientBehaviorSettings
keyboard?: ClientKeyboardSettings
panes?: Record<string, ClientPaneSettings>
lists?: Partial<Record<ClientListKey, ClientListSettings>>
@@ -303,6 +313,25 @@ const validListLimit = (value: unknown): ClientListLimit | null =>
value === 20 || value === 50 || value === 100 ? value : null
const normaliseAnimationMode = (value: unknown): ClientAnimationMode | null => {
if (value === 'normal' || value === 'reduced' || value === 'off')
return value
if (value === 'true')
return 'reduced'
if (value === 'false')
return 'normal'
return null
}
const normaliseEmbedAutoLoadMode = (value: unknown): ClientEmbedAutoLoadMode | null =>
value === 'auto' || value === 'manual' || value === 'off' ? value : null
const normaliseThumbnailMode = (value: unknown): ClientThumbnailMode | null =>
value === 'normal' || value === 'light' || value === 'off' ? value : null
const normaliseKeyboardBindings = (
bindings: unknown,
): Partial<Record<ShortcutActionId, KeyBinding | null>> => {
@@ -341,6 +370,110 @@ export const getClientKeyboardSettings = (): ClientKeyboardSettings => {
}
const legacyAnimationMode = (): ClientAnimationMode | null =>
normaliseAnimationMode (loadClientSettings ().reducedMotion)
const legacyEmbedAutoLoadMode = (): ClientEmbedAutoLoadMode | null =>
normaliseEmbedAutoLoadMode (loadClientSettings ().embedAutoLoad)
const legacyThumbnailMode = (): ClientThumbnailMode | null =>
normaliseThumbnailMode (loadClientSettings ().thumbnailMode)
export const getClientAnimationMode = (): ClientAnimationMode =>
loadClientSettings ().behavior?.animation
?? legacyAnimationMode ()
?? 'normal'
export const applyClientAnimationMode = (mode: ClientAnimationMode): void => {
if (typeof document === 'undefined')
return
if (mode === 'normal')
{
delete document.documentElement.dataset.animation
return
}
document.documentElement.dataset.animation = mode
}
export const setClientAnimationMode = (
animation: ClientAnimationMode,
): ClientBehaviorSettings =>
setClientBehaviorSettings ({
...getClientBehaviorSettings (),
animation,
})
export const getClientEmbedAutoLoadMode = (): ClientEmbedAutoLoadMode =>
loadClientSettings ().behavior?.embedAutoLoad
?? legacyEmbedAutoLoadMode ()
?? 'auto'
export const setClientEmbedAutoLoadMode = (
embedAutoLoad: ClientEmbedAutoLoadMode,
): ClientBehaviorSettings =>
setClientBehaviorSettings ({
...getClientBehaviorSettings (),
embedAutoLoad,
})
export const getClientThumbnailMode = (): ClientThumbnailMode =>
loadClientSettings ().behavior?.thumbnailMode
?? legacyThumbnailMode ()
?? 'normal'
export const setClientThumbnailMode = (
thumbnailMode: ClientThumbnailMode,
): ClientBehaviorSettings =>
setClientBehaviorSettings ({
...getClientBehaviorSettings (),
thumbnailMode,
})
export const getClientBehaviorSettings = (): ClientBehaviorSettings => ({
animation: getClientAnimationMode (),
embedAutoLoad: getClientEmbedAutoLoadMode (),
thumbnailMode: getClientThumbnailMode (),
})
export const setClientBehaviorSettings = (
behavior: ClientBehaviorSettings,
): ClientBehaviorSettings => {
const next: ClientBehaviorSettings = {
animation: (
normaliseAnimationMode (behavior.animation)
?? getClientAnimationMode ()
),
embedAutoLoad: (
normaliseEmbedAutoLoadMode (behavior.embedAutoLoad)
?? getClientEmbedAutoLoadMode ()
),
thumbnailMode: (
normaliseThumbnailMode (behavior.thumbnailMode)
?? getClientThumbnailMode ()
),
}
updateClientSettings (settings => ({
...settings,
behavior: next,
}))
applyClientAnimationMode (next.animation ?? 'normal')
return next
}
export const setClientKeyboardSettings = (
keyboard: ClientKeyboardSettings,
): ClientKeyboardSettings => {
@@ -921,7 +1054,8 @@ export const setClientGekanatorBackgroundMotion = (
): void => {
updateClientSettings (settings => ({
...settings,
gekanator: { ...(settings.gekanator ?? { }), backgroundMotion } }))
gekanator: { ...(settings.gekanator ?? { }), backgroundMotion },
}))
}