feat(desktop): information architecture overhaul — home, records, meetings first
Wave 2 of the 2026-09-28 design overhaul ("records are the main
character, a quiet instrument"). Decisions: design.md.
- Shell: sidebar with primary Home / Records / Meetings (Ctrl+1..3) and a
secondary "Tools" group; every item is a button with aria-current.
The status bar is removed — its "100% LOCAL PRIVACY · ZERO CLOUD SYNC"
claim contradicted device sync; the sidebar shows only queried state.
- Navigation context (routes, params, back, useRouteRequest) so Home can
open a specific meeting or record.
- Home replaces the dashboard: dictation key, start actions, only real
problems, one-line summary, recent records and meetings, file
transcription, free-tier limits.
- Settings become a full-screen route with vertical tabs (tabs no longer
clip) and a shared row grammar; long-standing bugs fixed: team and
enterprise tiers crashed the license tab (currentTier undefined),
first-run onboarding could not be left, Pro+ saw "upgrade to Pro+".
- Records: date-grouped single list with in-place expansion, search and
tags together, mode/favorite filters, load more past 50, undoable
delete. Meetings: list with search/rename/delete, summary-first detail
(summary | transcript | documents | my notes), notes persisted locally
instead of being lost. Tools pages cleaned up; stale-closure example
chips and a 1550x mouse-distance bug fixed.
- Shared pieces: PageHeader, EmptyStateCard, SearchInput ("/" works),
ConfirmDialog, notify with undo; display-labels maps domain values to
typed i18n keys so missing keys fail to compile.
- Mono font stack falls back to Pretendard for Hangul (Korean labels no
longer render spaced out).
- i18n: new ko/en keys via scripts/i18n-add-keys.mjs (one read-merge-
write so parallel editors cannot clobber locale files).
Some renderer files also carried pre-existing in-flight changes (error
recovery deep links, meeting document hooks); they are included as-is.
This commit is contained in:
parent
ba9ef9741e
commit
f064c93197
96 changed files with 12886 additions and 8924 deletions
41
scripts/i18n-add-keys.mjs
Normal file
41
scripts/i18n-add-keys.mjs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env node
|
||||
// scripts/i18n-add-keys.mjs
|
||||
// 번역 키를 ko/en(필요하면 다른 로케일) JSON 에 한 번에 병합한다. 파일 전체를 읽고-합치고-쓰는 동작이 한 프로세스 안에서
|
||||
// 끝나므로, 여러 작업자가 같은 로케일 파일을 손으로 Edit 하다 서로 덮어쓰는 일을 막는다.
|
||||
//
|
||||
// 사용: node scripts/i18n-add-keys.mjs <keys.json>
|
||||
// keys.json 형식: { "ko": { "home.title": "오늘" }, "en": { "home.title": "Today" } }
|
||||
// 이미 있는 키는 값을 바꾼다(--no-overwrite 면 건너뛴다). 새 키는 파일 끝에 붙는다.
|
||||
|
||||
import { readFileSync, writeFileSync, renameSync } from 'node:fs'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url))
|
||||
const localesDir = join(here, '..', 'packages', 'i18n', 'src', 'locales')
|
||||
|
||||
const [input, flag] = process.argv.slice(2)
|
||||
if (!input) {
|
||||
process.stderr.write('usage: node scripts/i18n-add-keys.mjs <keys.json> [--no-overwrite]\n')
|
||||
process.exit(2)
|
||||
}
|
||||
const overwrite = flag !== '--no-overwrite'
|
||||
const patch = JSON.parse(readFileSync(input, 'utf8'))
|
||||
|
||||
let changed = 0
|
||||
for (const [locale, entries] of Object.entries(patch)) {
|
||||
const file = join(localesDir, `${locale}.json`)
|
||||
const current = JSON.parse(readFileSync(file, 'utf8'))
|
||||
for (const [key, value] of Object.entries(entries)) {
|
||||
if (typeof value !== 'string') throw new Error(`${locale}.${key}: value must be a string`)
|
||||
if (key in current && !overwrite) continue
|
||||
if (current[key] !== value) {
|
||||
current[key] = value
|
||||
changed++
|
||||
}
|
||||
}
|
||||
const tmp = `${file}.tmp-${process.pid}`
|
||||
writeFileSync(tmp, `${JSON.stringify(current, null, 2)}\n`, 'utf8')
|
||||
renameSync(tmp, file)
|
||||
}
|
||||
process.stdout.write(`i18n: ${changed} key(s) written\n`)
|
||||
Loading…
Add table
Add a link
Reference in a new issue