weishu
d52a5a0e69
feat(sessions): one-line row meta — project · worktree · machine, no raw paths
...
Rows carried a machine-only line plus the full absolute path (prefix
noise, tail-truncated exactly where the information lives, machine
repeated under the filter chips). Replace both with a single meta line:
the last two segments of the worktree base path (session path fallback
— the web sidebar's group-name rule), the worktree name when present,
and the machine label only while several machines are known with no
machine filter active. The subtitle now carries the AI summary or
nothing; full paths stay in the session detail. Typical rows shrink
from three or four lines to two.
2026-08-18 22:09:33 +08:00
weishu
6066f20c20
feat(ios): zh-CN localization + catalog dedupe (A-M5)
...
Part 1 — Simplified Chinese localization of the iOS app layer:
- ios/Hapi/Resources/Localizable.xcstrings: hand-authored String Catalog
(395 keys, zh-Hans; en implicit as source). Terminology mined from
web/src/lib/locales/zh-CN.ts (会话/新建会话/权限模式/允许/拒绝/工作树/
机器/语音输入/用量/草稿夹 …).
- Mechanical edits only: merged multi-part string concatenations into
single LocalizedStringKey literals, converted ternary/plain-String user
copy to String(localized:), switched helper params (detailRow,
DashboardCard, optionPicker, notice) to LocalizedStringKey.
- LocalizedNoticeMapper (app layer): display-point translation of the 27
known HapiKit-emitted strings (ChatInteractor notices, dictation errors,
window-sync warnings, files fallbacks, worktree-name validation) with
verbatim passthrough for server-originated text; package stays
language-free.
- Deliberately untranslated (web parity / non-copy): event rows
(EventPresentation — web renders presentation.ts verbatim), catalog
option labels (Default/Auto/Sonnet/permission modes — web shows them
verbatim), tool names, code-like titles (grep(pattern:), MCP:, Skill,
Task), unit suffixes (B/KB/MB, m/h/d/w), decorative separators.
- Language row wired: AppLanguage gains .system (follow system, new
default); explicit picks write the AppleLanguages override, Follow
system removes it; footer notes a relaunch applies it (no supported
in-place SwiftUI locale swap).
- project.pbxproj: zh-Hans added to knownRegions.
Part 2 — #39 catalog dedupe (HapiProtocol):
- NewSessionCatalogs.claudeModels/claudeEfforts now derive from
ClaudeModels/ClaudeEfforts (single source shared with ModelCatalog);
codexReasoningEfforts stays own data (web CODEX_REASONING_EFFORT_OPTIONS
minus max); effortLabel delegates to ModelCatalog.capitalizedFirst.
- New CatalogTests lock test for the derived option lists.
Gate: bash ios/scripts/linux-test.sh — 459 tests green.
2026-08-18 16:04:03 +08:00
weishu
67b7fe7304
feat(ios): session list store + UI (A-M2a)
...
HapiProtocol (pure, mirroring the Android reference port):
- SummaryPatching: sessionSummary.ts derivations (pending requests
cap-5/oldest-first/id-tiebreak, kinds, todo progress), toSessionSummary
projection with the per-flavor agentSessionId resolution (legacy chain
omits piSessionId, replicated), applySessionSummaryPatch with the
deliberate >= version gates (vs the detail path's strict >), the
keep-alive render-irrelevance filter (pendingRequests compare ignores
'since'; metadata compare ignores hapiMcpUrl), max-monotonic updatedAt,
post-patch updatedAt as fallback 'since', and the deprecated legacy
detail-required gate kept for rule pinning.
- SessionSorting: exact list comparator (globalPinned > pinned > active >
pendingRequestsCount desc among active > updatedAt desc; stable).
- SessionMetadata: per-flavor session-id fields (claude/codex/gemini/
opencode/grok/agy/cursor/kimi/copilot/pi).
HapiClient stores (@MainActor @Observable, per hub):
- DiskCache: 500 ms debounced atomic JSON snapshots + SnapshotLocations.
- SessionListStore: sorted summaries + detail cache; full-session upsert
preserving hub-computed scheduled fields; strict-> detail vs >= summary
patch paths; keep-alive identity preservation (listRevision); empty-{}
and unparseable payloads take the REST fallback; 16 ms coalesced
refresh; optimistic pin (roll-forward) and archive (restore).
- MachineStore: the exact machine-updated decision tree.
- LastSeenStore: monotonic unread watermarks + per-scope baseline.
- SyncEventRouter: SyncEvent fan-out to the stores, global-scope message
events refresh the list, gap handshake triggers the full resync.
App:
- HubSession owns the stores + router (replaces the TODO(M2) routing);
background flushes snapshots.
- Features/Sessions: SessionListView + SessionListModel (status dot with
thinking pulse, title cascade, flavor·machine·worktree meta, relative
age on a minute timeline, pending/todo badges, unread dots, pinned
section, machine filter chips >= 2, pull-to-refresh, empty/loading/
offline states, long-press pin/archive context menu) + an M2f chat
placeholder pushed on row tap.
- HomePlaceholderView -> HomeView hosting the list (hub switcher +
connection dot kept in the toolbar).
Tests transcribe the Android suites: SummaryPatchingTest (18),
SessionSortingTest (6), SessionStoreTest, MachineStoreTest,
LastSeenStoreTest, JsonSnapshotStoreTest, StoreSyncTargetsTest — using
the existing HTTPPerforming recording stub plus a path-routing performer
for concurrent refetches.
2026-08-17 20:17:02 +08:00