| '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, |
| }), |
| }, |
| ), |
| ) |
|
|