このコミットが含まれているのは:
@@ -212,6 +212,15 @@ const LEGACY_GEKANATOR_BACKGROUND_MOTION_STORAGE_KEY =
|
|||||||
const LEGACY_MIGRATED_THEME_ID = 'custom:legacy-migrated'
|
const LEGACY_MIGRATED_THEME_ID = 'custom:legacy-migrated'
|
||||||
|
|
||||||
|
|
||||||
|
const createCustomThemeId = (): `custom:${ string }` => {
|
||||||
|
const randomPart =
|
||||||
|
globalThis.crypto?.randomUUID?.()
|
||||||
|
?? `${ Date.now ().toString (36) }-${ Math.random ().toString (36).slice (2) }`
|
||||||
|
|
||||||
|
return `custom:${ randomPart }`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const fetchUserSettings = async (): Promise<UserSettings> => {
|
export const fetchUserSettings = async (): Promise<UserSettings> => {
|
||||||
const raw = await apiGet<{
|
const raw = await apiGet<{
|
||||||
theme: UserSettings['theme']
|
theme: UserSettings['theme']
|
||||||
@@ -567,7 +576,7 @@ export const createCustomThemeFromBase = (
|
|||||||
baseTheme: BuiltinThemeId,
|
baseTheme: BuiltinThemeId,
|
||||||
tokens?: ThemeTokens,
|
tokens?: ThemeTokens,
|
||||||
): CustomClientTheme => {
|
): CustomClientTheme => {
|
||||||
const id = `custom:${ crypto.randomUUID () }` as ThemeId
|
const id = createCustomThemeId ()
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name: themeCopyName (baseTheme),
|
name: themeCopyName (baseTheme),
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ type SharedSectionProps = {
|
|||||||
selectedTheme: ClientTheme
|
selectedTheme: ClientTheme
|
||||||
draftTagColours: ThemeTagColours
|
draftTagColours: ThemeTagColours
|
||||||
onThemeChange: (themeId: ActiveThemeId) => void
|
onThemeChange: (themeId: ActiveThemeId) => void
|
||||||
|
onEnsureEditableTheme: () => void
|
||||||
onTagColourChange: (category: Category, colour: string) => void
|
onTagColourChange: (category: Category, colour: string) => void
|
||||||
onResetAllTagColours: () => void
|
onResetAllTagColours: () => void
|
||||||
onResetTagColour: (category: Category) => void
|
onResetTagColour: (category: Category) => void
|
||||||
@@ -252,6 +253,7 @@ const ThemeSection: FC<SharedSectionProps> = ({
|
|||||||
draftCustomThemes,
|
draftCustomThemes,
|
||||||
selectedTheme,
|
selectedTheme,
|
||||||
draftTagColours,
|
draftTagColours,
|
||||||
|
onEnsureEditableTheme,
|
||||||
onResetAllTagColours,
|
onResetAllTagColours,
|
||||||
onResetTagColour,
|
onResetTagColour,
|
||||||
onTagColourChange,
|
onTagColourChange,
|
||||||
@@ -331,6 +333,8 @@ const ThemeSection: FC<SharedSectionProps> = ({
|
|||||||
<input
|
<input
|
||||||
type="color"
|
type="color"
|
||||||
value={draftTagColours[category]}
|
value={draftTagColours[category]}
|
||||||
|
onPointerDown={onEnsureEditableTheme}
|
||||||
|
onFocus={onEnsureEditableTheme}
|
||||||
onChange={ev => onTagColourChange (category, ev.target.value)}
|
onChange={ev => onTagColourChange (category, ev.target.value)}
|
||||||
className="h-10 w-16 cursor-pointer rounded border border-border
|
className="h-10 w-16 cursor-pointer rounded border border-border
|
||||||
bg-transparent p-1"/>
|
bg-transparent p-1"/>
|
||||||
@@ -514,6 +518,21 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleEnsureEditableTheme = (): {
|
||||||
|
activeThemeId: ActiveThemeId
|
||||||
|
customThemes: Record<string, CustomClientTheme>
|
||||||
|
} => {
|
||||||
|
const editable = ensureEditableCustomTheme ()
|
||||||
|
|
||||||
|
if (editable.activeThemeId !== draftActiveThemeId
|
||||||
|
|| editable.customThemes !== draftCustomThemes)
|
||||||
|
{
|
||||||
|
applyDraftThemeSelection (editable.activeThemeId, editable.customThemes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return editable
|
||||||
|
}
|
||||||
|
|
||||||
const handleTabKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {
|
const handleTabKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {
|
||||||
const currentIndex = tabs.findIndex (tab => tab.id === activeTab)
|
const currentIndex = tabs.findIndex (tab => tab.id === activeTab)
|
||||||
|
|
||||||
@@ -677,8 +696,11 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
|||||||
onThemeChange: themeId => {
|
onThemeChange: themeId => {
|
||||||
applyDraftThemeSelection (themeId, draftCustomThemes)
|
applyDraftThemeSelection (themeId, draftCustomThemes)
|
||||||
},
|
},
|
||||||
|
onEnsureEditableTheme: () => {
|
||||||
|
handleEnsureEditableTheme ()
|
||||||
|
},
|
||||||
onTagColourChange: (category, colour) => {
|
onTagColourChange: (category, colour) => {
|
||||||
const editable = ensureEditableCustomTheme ()
|
const editable = handleEnsureEditableTheme ()
|
||||||
const editableTheme = editable.customThemes[editable.activeThemeId]
|
const editableTheme = editable.customThemes[editable.activeThemeId]
|
||||||
const nextCustomThemes = {
|
const nextCustomThemes = {
|
||||||
...editable.customThemes,
|
...editable.customThemes,
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする