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
89
apps/desktop/src/renderer/components/meeting/DocumentTab.tsx
Normal file
89
apps/desktop/src/renderer/components/meeting/DocumentTab.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// src/renderer/components/meeting/DocumentTab.tsx
|
||||
// Phase 14.5: 문서 탭 — MarkdownEditor + 자동저장 + 내보내기
|
||||
|
||||
import { useCallback, useRef } from 'react'
|
||||
import { Box } from '@mui/material'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import { MarkdownEditor } from './MarkdownEditor'
|
||||
import { ExportMenu } from './ExportMenu'
|
||||
import { PhysicalButton } from '../ds/PhysicalButton'
|
||||
import { d3roPalette, d3roTypo } from '../../theme'
|
||||
import { useI18n } from '../../i18n'
|
||||
import type { MeetingExportFormat } from '@shared/types'
|
||||
|
||||
interface DocumentTabDoc {
|
||||
id: string
|
||||
title: string
|
||||
content: string
|
||||
templateType: string
|
||||
}
|
||||
|
||||
interface DocumentTabProps {
|
||||
document: DocumentTabDoc
|
||||
onContentChange: (content: string) => void
|
||||
onExport: (format: MeetingExportFormat) => void
|
||||
onDelete: () => void
|
||||
}
|
||||
|
||||
const AUTOSAVE_DELAY = 500
|
||||
|
||||
export function DocumentTab({
|
||||
document: doc,
|
||||
onContentChange,
|
||||
onExport,
|
||||
onDelete,
|
||||
}: DocumentTabProps): React.ReactElement {
|
||||
const { t } = useI18n()
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
|
||||
const handleChange = useCallback(
|
||||
(content: string) => {
|
||||
if (timerRef.current) clearTimeout(timerRef.current)
|
||||
timerRef.current = setTimeout(() => {
|
||||
onContentChange(content)
|
||||
}, AUTOSAVE_DELAY)
|
||||
},
|
||||
[onContentChange],
|
||||
)
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
{/* 콘텐츠 편집기 */}
|
||||
<Box sx={{ flex: 1, overflow: 'hidden', minHeight: 0 }}>
|
||||
<MarkdownEditor
|
||||
content={doc.content}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* 하단 액션 바 */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
mt: 1.5,
|
||||
pt: 1.5,
|
||||
borderTop: `1px solid ${d3roPalette.border.subtle}`,
|
||||
}}
|
||||
>
|
||||
<ExportMenu onExport={onExport} />
|
||||
<PhysicalButton
|
||||
size="small"
|
||||
color="error"
|
||||
onClick={onDelete}
|
||||
sx={{ height: 32, fontSize: d3roTypo.engrave.size }}
|
||||
>
|
||||
<DeleteIcon sx={{ fontSize: 14, mr: 0.5 }} />
|
||||
{t('common.delete')}
|
||||
</PhysicalButton>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue