Phase 14 구현: 회의 모드 (Meeting Mode)
실시간 녹음 + 타임스탬프 메모 + STT 전사 + LLM 구조화 회의록 + PDF/MD 내보내기. CaptionService 연동, 동시 사용 충돌 방지, 긴 회의 2-pass 요약 지원. DB 2테이블, IPC 15채널, UI 3뷰(목록/녹음/상세), 12개 locale i18n.
This commit is contained in:
parent
dd68fc9ccd
commit
d0c4f9ee53
38 changed files with 2550 additions and 769 deletions
|
|
@ -9,6 +9,7 @@ import MenuBookIcon from '@mui/icons-material/MenuBook'
|
|||
import ExtensionIcon from '@mui/icons-material/Extension'
|
||||
import RecordVoiceOverIcon from '@mui/icons-material/RecordVoiceOver'
|
||||
import AutoStoriesIcon from '@mui/icons-material/AutoStories'
|
||||
import GroupsIcon from '@mui/icons-material/Groups'
|
||||
import SettingsIcon from '@mui/icons-material/Settings'
|
||||
import { Led } from './ds'
|
||||
import { DashboardPage } from '../pages/DashboardPage'
|
||||
|
|
@ -17,6 +18,7 @@ import { DictionaryPage } from '../pages/DictionaryPage'
|
|||
import { CommandsPage } from '../pages/CommandsPage'
|
||||
import { VoiceConversationPage } from '../pages/VoiceConversationPage'
|
||||
import { KnowledgeBasePage } from '../pages/KnowledgeBasePage'
|
||||
import { MeetingModePage } from '../pages/MeetingModePage'
|
||||
import { SettingsModal } from './SettingsModal'
|
||||
import { LicenseModal } from './LicenseModal'
|
||||
import { OnboardingModal } from './OnboardingModal'
|
||||
|
|
@ -26,7 +28,7 @@ import { useI18n } from '../i18n'
|
|||
import type { TranslationKey } from '../i18n'
|
||||
import type { LicenseTier } from '@shared/types'
|
||||
|
||||
type Route = 'dashboard' | 'history' | 'dictionary' | 'commands' | 'conversation' | 'knowledge'
|
||||
type Route = 'dashboard' | 'history' | 'dictionary' | 'commands' | 'conversation' | 'knowledge' | 'meeting'
|
||||
|
||||
interface NavItem {
|
||||
route: Route
|
||||
|
|
@ -42,6 +44,7 @@ const NAV_ITEMS: NavItem[] = [
|
|||
{ route: 'commands', labelKey: 'nav.commands', abbr: 'CMD', icon: <ExtensionIcon sx={{ fontSize: 20 }} /> },
|
||||
{ route: 'conversation', labelKey: 'nav.conversation', abbr: 'TALK', icon: <RecordVoiceOverIcon sx={{ fontSize: 20 }} /> },
|
||||
{ route: 'knowledge', labelKey: 'nav.knowledge', abbr: 'RAG', icon: <AutoStoriesIcon sx={{ fontSize: 20 }} /> },
|
||||
{ route: 'meeting', labelKey: 'nav.meeting', abbr: 'MTG', icon: <GroupsIcon sx={{ fontSize: 20 }} /> },
|
||||
]
|
||||
|
||||
function tierToLedColor(tier: LicenseTier): 'amber' | 'green' {
|
||||
|
|
@ -225,6 +228,7 @@ export function AppLayout(): React.ReactElement {
|
|||
{currentRoute === 'commands' && <CommandsPage />}
|
||||
{currentRoute === 'conversation' && <VoiceConversationPage />}
|
||||
{currentRoute === 'knowledge' && <KnowledgeBasePage />}
|
||||
{currentRoute === 'meeting' && <MeetingModePage />}
|
||||
</Box>
|
||||
</Box>
|
||||
<StatusBar />
|
||||
|
|
|
|||
|
|
@ -455,10 +455,10 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac
|
|||
<MenuItem value="auto">{t('settings.theme.system')}</MenuItem>
|
||||
<MenuItem value="light">{t('settings.theme.light')}</MenuItem>
|
||||
<MenuItem value="dark">{t('settings.theme.dark')}</MenuItem>
|
||||
<MenuItem value="nord">Nord</MenuItem>
|
||||
<MenuItem value="solarized">Solarized</MenuItem>
|
||||
<MenuItem value="catppuccin">Catppuccin</MenuItem>
|
||||
<MenuItem value="dracula">Dracula</MenuItem>
|
||||
<MenuItem value="nord">{t('settings.theme.nord')}</MenuItem>
|
||||
<MenuItem value="solarized">{t('settings.theme.solarized')}</MenuItem>
|
||||
<MenuItem value="catppuccin">{t('settings.theme.catppuccin')}</MenuItem>
|
||||
<MenuItem value="dracula">{t('settings.theme.dracula')}</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
|
|
@ -627,10 +627,10 @@ export function SettingsModal({ open, onClose }: SettingsModalProps): React.Reac
|
|||
onChange={(e) => updateConfig('sttLanguage', e.target.value)}
|
||||
>
|
||||
<MenuItem value="auto">{t('settings.sttLang.auto')}</MenuItem>
|
||||
<MenuItem value="ko">한국어</MenuItem>
|
||||
<MenuItem value="en">English</MenuItem>
|
||||
<MenuItem value="ja">日本語</MenuItem>
|
||||
<MenuItem value="zh">中文</MenuItem>
|
||||
<MenuItem value="ko">{t('settings.sttLang.ko')}</MenuItem>
|
||||
<MenuItem value="en">{t('settings.sttLang.en')}</MenuItem>
|
||||
<MenuItem value="ja">{t('settings.sttLang.ja')}</MenuItem>
|
||||
<MenuItem value="zh">{t('settings.sttLang.zh')}</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ export function TemplateSection(): React.ReactElement {
|
|||
fullWidth
|
||||
multiline
|
||||
rows={3}
|
||||
helperText="Use {{fieldName}} for placeholders"
|
||||
helperText={t('template.outputHelperText')}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ px: 3, pb: 2 }}>
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ export function MetalDial({
|
|||
background: `
|
||||
repeating-radial-gradient(
|
||||
circle at 50% 50%,
|
||||
#e6e7e9 0px,
|
||||
#e6e7e9 1px,
|
||||
#b0b2b5 1.5px,
|
||||
#b0b2b5 2.5px
|
||||
${d3roPalette.text.disabled} 0px,
|
||||
${d3roPalette.text.disabled} 1px,
|
||||
${d3roPalette.text.label} 1.5px,
|
||||
${d3roPalette.text.label} 2.5px
|
||||
)
|
||||
`,
|
||||
transform: `rotate(${rotation}deg)`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue