feat(V2-1a): Monorepo 구조 전환 — apps/desktop으로 V1 이동
- npm workspaces 루트 (apps/*, packages/*) 세팅 - V1 전체를 apps/desktop/으로 git mv (src, resources, tests, sidecar, scripts, electron.vite.config.ts, electron-builder.yml, vitest.config.ts, tsconfig.node.json, tsconfig.web.json) - apps/desktop/package.json 신규 (name=@d3ro/desktop) - productName: 'd3ro-voice' 명시 — app.getName()을 고정하여 userData 경로 %APPDATA%\d3ro-voice\ 그대로 유지 (기존 DB/설정 연속성 보장) - 루트 package.json을 workspace 루트로 재구성, 공통 devDep만 유지 (typescript, eslint, prettier) - turbo.json, tsconfig.base.json 추가 (Turborepo 자체 설치는 별도 sub-phase) - memory/project_status.md 생성 (규칙 13) 검증: - npm run typecheck 통과 - npm run build 통과 (electron-vite main+preload+renderer) - npm run dev 실제 실행 → DB/핫키/Ollama 자동 실행 모두 정상
This commit is contained in:
parent
3a160b9032
commit
45a580878a
178 changed files with 214 additions and 0 deletions
|
|
@ -1,131 +0,0 @@
|
|||
// src/main/services/ConfigService.ts
|
||||
// electron-store 기반 설정 관리. 설계서 02의 AppConfig 타입 사용.
|
||||
|
||||
import { EventEmitter } from 'events'
|
||||
import type { AppConfig, ConfigChangedEvent } from '@shared/types'
|
||||
import { getLogger } from './LoggerService'
|
||||
|
||||
const logger = getLogger('ConfigService')
|
||||
|
||||
// electron-store v10은 ESM 전용이므로 동적 import 필요
|
||||
interface ElectronStore<T extends Record<string, unknown>> {
|
||||
get<K extends keyof T>(key: K): T[K]
|
||||
set<K extends keyof T>(key: K, value: T[K]): void
|
||||
store: T
|
||||
}
|
||||
|
||||
const CONFIG_DEFAULTS: AppConfig = {
|
||||
theme: 'auto',
|
||||
language: 'ko',
|
||||
closeToTray: true,
|
||||
autoLaunch: false,
|
||||
soundEnabled: true,
|
||||
selectedDeviceId: null,
|
||||
sttModelId: 'base',
|
||||
sttLanguage: 'auto',
|
||||
ttsVoiceId: null,
|
||||
ttsSpeed: 1.0,
|
||||
ollamaServerUrl: 'http://localhost:11434',
|
||||
llmModelId: null,
|
||||
defaultLLMAction: 'refine',
|
||||
dictationShortcut: {
|
||||
keyCode: 0xa5, // Right Alt
|
||||
ctrl: false,
|
||||
alt: false,
|
||||
shift: false,
|
||||
meta: false,
|
||||
displayLabel: 'Right Alt'
|
||||
},
|
||||
handsFreeShortcut: {
|
||||
keyCode: 0xa5,
|
||||
ctrl: false,
|
||||
alt: false,
|
||||
shift: false,
|
||||
meta: false,
|
||||
displayLabel: 'Right Alt (double)'
|
||||
},
|
||||
commandShortcut: {
|
||||
keyCode: 0xa5,
|
||||
ctrl: true,
|
||||
alt: false,
|
||||
shift: false,
|
||||
meta: false,
|
||||
displayLabel: 'Ctrl + Right Alt'
|
||||
},
|
||||
captionShortcut: {
|
||||
keyCode: 0xa5,
|
||||
ctrl: true,
|
||||
alt: false,
|
||||
shift: true,
|
||||
meta: false,
|
||||
displayLabel: 'Ctrl + Shift + Right Alt'
|
||||
},
|
||||
hotkeyEnabled: true,
|
||||
insertMethod: 'clipboard',
|
||||
autoInsert: true,
|
||||
maxHistoryEntries: 1000,
|
||||
dictationEnabled: true,
|
||||
agentModeEnabled: false,
|
||||
handsFreeEnabled: false,
|
||||
screenContextEnabled: false,
|
||||
}
|
||||
|
||||
let store: ElectronStore<AppConfig> | null = null
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
export async function initConfigService(): Promise<void> {
|
||||
const { default: Store } = await import('electron-store')
|
||||
store = new Store<AppConfig>({
|
||||
name: 'd3ro-voice-config',
|
||||
defaults: CONFIG_DEFAULTS
|
||||
})
|
||||
logger.info('ConfigService initialized')
|
||||
}
|
||||
|
||||
export function getConfigService(): ElectronStore<AppConfig> | null {
|
||||
return store
|
||||
}
|
||||
|
||||
export function configGet<K extends keyof AppConfig>(key: K): AppConfig[K] {
|
||||
if (!store) {
|
||||
logger.warn(`ConfigService not initialized, returning default for "${key}"`)
|
||||
return CONFIG_DEFAULTS[key]
|
||||
}
|
||||
return store.get(key)
|
||||
}
|
||||
|
||||
export function configSet<K extends keyof AppConfig>(key: K, value: AppConfig[K]): void {
|
||||
if (!store) {
|
||||
logger.warn(`ConfigService not initialized, cannot set "${key}"`)
|
||||
return
|
||||
}
|
||||
const previousValue = store.get(key)
|
||||
store.set(key, value)
|
||||
|
||||
const event: ConfigChangedEvent = {
|
||||
key,
|
||||
value,
|
||||
previousValue
|
||||
}
|
||||
emitter.emit('config-changed', event)
|
||||
logger.debug(`Config changed: ${key}`)
|
||||
}
|
||||
|
||||
export function configGetAll(): AppConfig {
|
||||
if (!store) return { ...CONFIG_DEFAULTS }
|
||||
return store.store
|
||||
}
|
||||
|
||||
export function configReset(key?: keyof AppConfig): void {
|
||||
if (!store) return
|
||||
if (key) {
|
||||
store.set(key, CONFIG_DEFAULTS[key])
|
||||
} else {
|
||||
store.store = { ...CONFIG_DEFAULTS }
|
||||
}
|
||||
}
|
||||
|
||||
export function onConfigChanged(callback: (event: ConfigChangedEvent) => void): () => void {
|
||||
emitter.on('config-changed', callback)
|
||||
return () => emitter.off('config-changed', callback)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue