trans3 / ui /lib /stores /preferencesStore.ts
Mayo
feat: Codex integration
dab69e9 unverified
Raw
History Blame Contribute Delete
4.2 kB
'use client'
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { getPlatform } from '@/lib/shortcutUtils'
type PreferencesState = {
brushConfig: {
size: number
color: string
}
setBrushConfig: (config: Partial<PreferencesState['brushConfig']>) => void
defaultFont?: string
setDefaultFont: (font?: string) => void
customSystemPrompt?: string
setCustomSystemPrompt: (prompt?: string) => void
codexImagePrompt?: string
setCodexImagePrompt: (prompt?: string) => void
codexImageModel?: string
setCodexImageModel: (model?: string) => void
shortcuts: {
select: string
block: string
brush: string
eraser: string
repairBrush: string
increaseBrushSize: string
decreaseBrushSize: string
undo: string
redo: string
}
setShortcuts: (shortcuts: Partial<PreferencesState['shortcuts']>) => void
resetShortcuts: () => void
resetPreferences: () => void
}
const initialPreferences = {
brushConfig: {
size: 36,
color: '#ffffff',
},
shortcuts: {
select: 'V',
block: 'M',
brush: 'B',
eraser: 'E',
repairBrush: 'R',
increaseBrushSize: ']',
decreaseBrushSize: '[',
undo: getPlatform() === 'mac' ? 'Cmd+Z' : 'Ctrl+Z',
redo: getPlatform() === 'mac' ? 'Cmd+Shift+Z' : 'Ctrl+Shift+Z',
},
codexImagePrompt:
'Translate all visible text to natural English, remove the original lettering, and redraw the page as a clean manga image while preserving the artwork, panel layout, speech bubbles, tone, and composition.',
codexImageModel: 'gpt-5.5',
}
export const usePreferencesStore = create<PreferencesState>()(
persist(
(set) => ({
...initialPreferences,
setBrushConfig: (config) =>
set((state) => ({
brushConfig: {
...state.brushConfig,
...config,
},
})),
setDefaultFont: (font) => set({ defaultFont: font }),
setCustomSystemPrompt: (prompt) => set({ customSystemPrompt: prompt }),
setCodexImagePrompt: (prompt) => set({ codexImagePrompt: prompt }),
setCodexImageModel: (model) => set({ codexImageModel: model }),
setShortcuts: (shortcuts) =>
set((state) => ({
shortcuts: {
...state.shortcuts,
...shortcuts,
},
})),
resetShortcuts: () =>
set(() => ({
shortcuts: {
...initialPreferences.shortcuts,
},
})),
resetPreferences: () => set({ ...initialPreferences }),
}),
{
name: 'koharu-config',
version: 6,
migrate: (persisted: any, version: number) => {
if (version < 2 && persisted) {
delete persisted.localLlm
delete persisted.openAiCompatibleConfigVersion
}
if (version < 3 && persisted) {
delete persisted.apiKeys
delete persisted.providerBaseUrls
delete persisted.providerModelNames
}
if (version < 4 && persisted?.shortcuts) {
for (const key in persisted.shortcuts) {
const val = persisted.shortcuts[key]
if (typeof val === 'string' && val.length === 1) {
persisted.shortcuts[key] = val.toUpperCase()
}
}
}
if (version < 5 && persisted?.shortcuts) {
const isMac = getPlatform() === 'mac'
if (!persisted.shortcuts.undo) {
persisted.shortcuts.undo = isMac ? 'Cmd+Z' : 'Ctrl+Z'
}
if (!persisted.shortcuts.redo) {
persisted.shortcuts.redo = isMac ? 'Cmd+Shift+Z' : 'Ctrl+Shift+Z'
}
}
if (version < 6 && persisted) {
persisted.codexImagePrompt ??= initialPreferences.codexImagePrompt
persisted.codexImageModel ??= initialPreferences.codexImageModel
}
return persisted
},
partialize: (state) => ({
brushConfig: state.brushConfig,
defaultFont: state.defaultFont,
customSystemPrompt: state.customSystemPrompt,
codexImagePrompt: state.codexImagePrompt,
codexImageModel: state.codexImageModel,
shortcuts: state.shortcuts,
}),
},
),
)