Phase 1: - 프로젝트 초기화 (TypeScript strict, electron-vite, ESLint, Prettier) - shared 타입 (ipc-channels 113채널, types, errors, constants) - 메인 프로세스 뼈대 (bootstrap, lifecycle, 단일 인스턴스) - LoggerService, ConfigService (electron-store ESM dynamic import) - React 19 + MUI 7 Dashboard, 시스템 트레이 Phase 2: - AudioCaptureService (node-record-lpcm16, PCM16 16kHz mono) - HotkeyService (uiohook-napi, 더블프레스, holdMode/toggleMode) - LocalSTTService (faster-whisper Python sidecar, 이중 조건 플러시) - VoiceModeService 오케스트레이터 (이중 상태머신, Action Queue) - Python sidecar (FastAPI: health/load/transcribe/shutdown) - IPC 핸들러 (voice, stt, hotkey) + Preload API 확장
148 lines
3.2 KiB
TypeScript
148 lines
3.2 KiB
TypeScript
// src/renderer/theme.ts — MUI 7 테마 정의 (설계서 03 기반)
|
|
|
|
import { createTheme, type ThemeOptions } from '@mui/material/styles'
|
|
|
|
const commonOptions: ThemeOptions = {
|
|
typography: {
|
|
fontFamily: [
|
|
'-apple-system',
|
|
'BlinkMacSystemFont',
|
|
'"Segoe UI"',
|
|
'Roboto',
|
|
'"Helvetica Neue"',
|
|
'Arial',
|
|
'sans-serif'
|
|
].join(','),
|
|
h4: { fontWeight: 600, fontSize: '1.5rem' },
|
|
h5: { fontWeight: 600, fontSize: '1.25rem' },
|
|
h6: { fontWeight: 600, fontSize: '1rem' },
|
|
subtitle1: { fontWeight: 500 },
|
|
body1: { fontSize: '0.9375rem' },
|
|
body2: { fontSize: '0.8125rem' },
|
|
button: { textTransform: 'none' as const, fontWeight: 500 }
|
|
},
|
|
shape: {
|
|
borderRadius: 12
|
|
},
|
|
components: {
|
|
MuiButton: {
|
|
defaultProps: {
|
|
disableElevation: true
|
|
},
|
|
styleOverrides: {
|
|
root: {
|
|
textTransform: 'none',
|
|
fontWeight: 500,
|
|
borderRadius: 8,
|
|
padding: '8px 16px'
|
|
}
|
|
}
|
|
},
|
|
MuiCard: {
|
|
defaultProps: {
|
|
elevation: 0
|
|
},
|
|
styleOverrides: {
|
|
root: {
|
|
borderRadius: 12,
|
|
border: '1px solid'
|
|
}
|
|
}
|
|
},
|
|
MuiDrawer: {
|
|
styleOverrides: {
|
|
paper: {
|
|
width: 240,
|
|
borderRight: 'none'
|
|
}
|
|
}
|
|
},
|
|
MuiListItemButton: {
|
|
styleOverrides: {
|
|
root: {
|
|
borderRadius: 8,
|
|
marginLeft: 8,
|
|
marginRight: 8
|
|
}
|
|
}
|
|
},
|
|
MuiTextField: {
|
|
defaultProps: {
|
|
size: 'small',
|
|
variant: 'outlined'
|
|
}
|
|
},
|
|
MuiChip: {
|
|
styleOverrides: {
|
|
root: {
|
|
borderRadius: 6,
|
|
fontWeight: 500
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const lightTheme = createTheme({
|
|
...commonOptions,
|
|
palette: {
|
|
mode: 'light',
|
|
primary: {
|
|
main: 'rgb(31, 93, 242)',
|
|
light: 'rgb(71, 133, 255)',
|
|
dark: 'rgb(20, 65, 180)',
|
|
contrastText: '#FFFFFF'
|
|
},
|
|
secondary: {
|
|
main: 'rgb(108, 117, 125)',
|
|
light: 'rgb(173, 181, 189)',
|
|
dark: 'rgb(73, 80, 87)'
|
|
},
|
|
background: {
|
|
default: '#F9F9F9',
|
|
paper: '#FFFFFF'
|
|
},
|
|
text: {
|
|
primary: 'rgba(0, 0, 0, 0.87)',
|
|
secondary: 'rgba(0, 0, 0, 0.6)'
|
|
},
|
|
divider: 'rgba(0, 0, 0, 0.08)',
|
|
error: { main: '#D32F2F' },
|
|
success: { main: '#2E7D32' },
|
|
warning: { main: '#ED6C02' }
|
|
}
|
|
})
|
|
|
|
export const darkTheme = createTheme({
|
|
...commonOptions,
|
|
palette: {
|
|
mode: 'dark',
|
|
primary: {
|
|
main: 'rgb(71, 133, 255)',
|
|
light: 'rgb(120, 170, 255)',
|
|
dark: 'rgb(31, 93, 242)',
|
|
contrastText: '#FFFFFF'
|
|
},
|
|
secondary: {
|
|
main: 'rgb(173, 181, 189)',
|
|
light: 'rgb(206, 212, 218)',
|
|
dark: 'rgb(108, 117, 125)'
|
|
},
|
|
background: {
|
|
default: '#121212',
|
|
paper: '#1E1E1E'
|
|
},
|
|
text: {
|
|
primary: 'rgba(255, 255, 255, 0.87)',
|
|
secondary: 'rgba(255, 255, 255, 0.6)'
|
|
},
|
|
divider: 'rgba(255, 255, 255, 0.08)',
|
|
error: { main: '#EF5350' },
|
|
success: { main: '#4CAF50' },
|
|
warning: { main: '#FFA726' }
|
|
}
|
|
})
|
|
|
|
export function getTheme(mode: 'light' | 'dark') {
|
|
return mode === 'dark' ? darkTheme : lightTheme
|
|
}
|