From 2c6bfebb5b15b3e5b7b2a49b1b3c2cbd0b698b5b Mon Sep 17 00:00:00 2001 From: th-kim0823 Date: Mon, 11 May 2026 10:47:04 +0900 Subject: [PATCH] =?UTF-8?q?chore(release):=20v0.3.5=20=E2=80=94=20dogfood?= =?UTF-8?q?=20UX=20hotfix=207=EA=B1=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v0.3.4 까지 누적된 dogfood UX 결함 hotfix. 사용자 직접 보고 3건 (inbox 재진입, 회고 탈출, 이동 modal 중복) + 동반 갭 4건 (count stale, 필터 잔류, 초기 로드 불일치, 배너 컨텍스트 누수). 데이터/마이그레이션 변경 없음 (스키마 v8). Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 28 ++++ package-lock.json | 4 +- package.json | 2 +- src/renderer/inbox/App.tsx | 24 +-- .../inbox/components/MoveStatusModal.tsx | 150 ------------------ src/renderer/inbox/components/NoteCard.tsx | 56 ++++--- src/renderer/inbox/components/ReviewView.tsx | 28 +++- src/renderer/inbox/components/statusLabel.ts | 26 +++ src/renderer/inbox/store.ts | 20 ++- tests/unit/MoveStatusModal.test.tsx | 98 ------------ tests/unit/NoteCard.test.tsx | 41 ++++- tests/unit/SettingsPage.test.tsx | 2 + tests/unit/store.showSettings.test.ts | 1 + 13 files changed, 182 insertions(+), 298 deletions(-) delete mode 100644 src/renderer/inbox/components/MoveStatusModal.tsx create mode 100644 src/renderer/inbox/components/statusLabel.ts delete mode 100644 tests/unit/MoveStatusModal.test.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index c1a8933..c43b1ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,34 @@ 본 파일은 Inkling 의 버전별 사용자 영향 변경 사항을 기록한다. 형식은 [Keep a Changelog](https://keepachangelog.com/) 를 느슨하게 따른다. +## [0.3.5] — 2026-05-11 + +v0.3.4 까지 누적된 dogfood UX 결함 7건 hotfix. 사용자가 막혔던 inbox/회고/이동 3건 + 그 부류의 동반 갭 4건. 데이터/마이그레이션 변경 없음 (스키마 v8 그대로). + +### 수정 + +- **Inbox 탭 진입 실패: 다른 보관함에서 inbox 로 못 돌아옴.** `setView('inbox')` 가 reload 를 호출 안 해서 `notes` state 가 이전 view 의 status 로 stale. `loadByView` 시그니처에 `'inbox' → 'active'` 매핑 추가 + setView 의 reload 분기에 inbox 포함. +- **회고 view 탈출 불가.** `ReviewView` 가 App 의 헤더를 우회 (early return) 해서 사용자가 뒤로 갈 길이 없던 문제. `← 돌아가기` 버튼 추가 — 클릭 시 `setView('inbox')`. +- **이동 dropdown 의 modal 중복 질문.** dropdown 에서 "완료로 이동" 선택해도 `MoveStatusModal` 이 떠서 목적지를 재확인. dropdown 클릭 = `inboxApi.setStatus(id, target, null)` 즉시 호출로 단순화. modal path 자체 제거 (`MoveStatusModal.tsx` + 동반 테스트 삭제, `statusLabel` 헬퍼는 별도 `statusLabel.ts` 로 분리). +- **이동 후 헤더 탭 count stale.** `setStatus` IPC 가 `pushNoteUpdated` emit 을 안 해서 `refreshMeta` 가 트리거되지 않던 잠재 버그. dropdown 이동 path 끝에 `refreshMeta()` 명시 호출 추가. +- **View 전환 시 검색/태그 필터 잔류.** `setView` 가 `searchResults`/`searchQuery`/`tagFilter` 를 reset 안 해서 이전 view 의 필터가 완료/보관/휴지통/회고에 잘못 적용. 한 번에 reset. +- **Inbox 첫 로드와 탭 reload 결과 불일치.** `loadInitial` 이 `listNotes()` (= `deleted_at IS NULL` = active+completed+archived 혼재) 사용 → 헤더 inbox count (active 만) 와 list 불일치. `listByStatus('active', limit:50)` 로 통일. +- **AI 배너가 completed/archived 탭에서도 노출.** OllamaBanner/PendingBanner/FailedBanner/ExpiryBanner/RecallBanner/RecoveryToast 가 `!showTrash` 만 체크해서 active 무관 컨텍스트에서도 그림. `view === 'inbox'` 분기로 한정. + +### 갱신 + +- **이동 dropdown UX** — 메뉴 열린 상태에서 외부 클릭 / Escape 로 닫힘 (mousedown + keydown listener, useEffect 로 menuOpen=true 일 때만 활성). + +### 게이트 + +- 단위 738 → **734 PASS** (MoveStatusModal 6 case 삭제 + NoteCard 메뉴 case 1 → 3 (직접 이동/외부 클릭/Escape) 로 재구성) +- typecheck 0 errors (src) +- 신규 npm dependency 0 + +### 업그레이드 + +v0.3.4 인스톨러 위에 v0.3.5 인스톨러를 같은 위치에 실행하면 in-place 업그레이드. 데이터/마이그레이션 변경 없음. + ## [0.3.4] — 2026-05-11 v0.3.0 Cut E (양방향 sync) dogfood 의 결과로, 사용자가 conflict 시나리오에 막힌 순간 도움받을 곳이 부재한 갭을 메운 cut. 3 표면 (in-app modal + ConflictModal inline + README) 통합 도움말. PR #33 머지. diff --git a/package-lock.json b/package-lock.json index 94bab9c..34da9fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "inkling", - "version": "0.3.3", + "version": "0.3.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "inkling", - "version": "0.3.3", + "version": "0.3.5", "dependencies": { "better-sqlite3": "12.9.0", "electron-log": "5.2.0", diff --git a/package.json b/package.json index 3d4e3bc..ba43d33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "inkling", - "version": "0.3.4", + "version": "0.3.5", "private": true, "description": "Inkling — local-first 한 줄 보관 도구", "author": "altair823 ", diff --git a/src/renderer/inbox/App.tsx b/src/renderer/inbox/App.tsx index 09dd46c..154d791 100644 --- a/src/renderer/inbox/App.tsx +++ b/src/renderer/inbox/App.tsx @@ -153,15 +153,21 @@ export function App(): React.ReactElement {
{!showTrash && ( <> - setShowSettings(true)} /> - { markRecoveryDismissed(); setRecoveryDismissed(true); }} - /> - - - - + {/* AI/만료/회상 배너는 active 노트 컨텍스트 — inbox 탭에서만 노출. + completed/archived 에서는 무관 컨텐츠라 숨김. */} + {view === 'inbox' && ( + <> + setShowSettings(true)} /> + { markRecoveryDismissed(); setRecoveryDismissed(true); }} + /> + + + + + + )} {tagFilter !== null && (
void; - onMoved: (status: NoteStatus, reason: string | null) => void; -} - -/** - * v0.2.9 Cut B Task 7 — 메모 이동 Modal. - * - * 사유 입력 + 3 status 버튼 (완료/보관/휴지통) + AI 자동 분류. - */ -export function MoveStatusModal({ - noteId, - onClose, - onMoved -}: Props): React.ReactElement { - const [reason, setReason] = useState(''); - const [recommendation, setRecommendation] = useState<{ - status: NoteStatus; - rationale: string; - } | null>(null); - const [classifying, setClassifying] = useState(false); - - async function move(status: NoteStatus): Promise { - const trimmedReason = reason.trim() === '' ? null : reason.trim(); - await inboxApi.setStatus(noteId, status, trimmedReason); - onMoved(status, trimmedReason); - } - - async function classify(): Promise { - setClassifying(true); - setRecommendation(null); - try { - const r = await inboxApi.classifyStatus(noteId, reason); - setRecommendation({ status: r.recommended, rationale: r.rationale }); - } finally { - setClassifying(false); - } - } - - return ( -
-
-

메모 이동

-