From 992f8dbba48f99a4b85c9dfb60feb253c470f458 Mon Sep 17 00:00:00 2001 From: kris Date: Mon, 6 Apr 2026 16:45:35 +0800 Subject: [PATCH] Compact imported folder conversation previews --- src/lib/boss-projections.ts | 42 +++++++++++++++++++++++---- tests/conversation-home-items.test.ts | 39 +++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/lib/boss-projections.ts b/src/lib/boss-projections.ts index 0d92294..57f1477 100644 --- a/src/lib/boss-projections.ts +++ b/src/lib/boss-projections.ts @@ -488,6 +488,33 @@ function buildFolderSearchAliases(items: ConversationItem[]) { : undefined; } +function compactImportedThreadPreview(preview?: string) { + const value = preview?.trim(); + if (!value) return ""; + if (/^已从设备.+导入线程《.+》[。.]?$/.test(value)) { + return "已导入线程"; + } + return value; +} + +function trimLocalWorkspacePrefix(label?: string) { + const value = label?.trim(); + if (!value) return ""; + const normalized = value.replaceAll("\\", "/"); + const patterns = [ + /^\/Users\/[^/]+\/code\/(.+)$/i, + /^\/home\/[^/]+\/code\/(.+)$/i, + /^[A-Za-z]:\/Users\/[^/]+\/code\/(.+)$/i, + ]; + for (const pattern of patterns) { + const match = normalized.match(pattern); + if (match?.[1]) { + return match[1]; + } + } + return value; +} + export function getConversationItems(state: BossState): ConversationItem[] { const conversations = state.projects.map((project) => buildConversationItem(state, project)); @@ -548,8 +575,12 @@ export function getConversationHomeItems(state: BossState): ConversationItem[] { } return b.latestReplyAt.localeCompare(a.latestReplyAt); })[0]; - const recentThreadLabel = latestItem.threadTitle.trim(); + const recentThreadLabel = trimLocalWorkspacePrefix(latestItem.threadTitle); const searchAliases = buildFolderSearchAliases(items); + const latestPreview = compactImportedThreadPreview(latestItem.preview); + const latestMessagePreview = compactImportedThreadPreview( + latestItem.lastMessagePreview || latestItem.preview, + ); passthrough.push({ conversationId: `folder-${folderKey}`, conversationType: "folder_archive", @@ -571,12 +602,11 @@ export function getConversationHomeItems(state: BossState): ConversationItem[] { searchTargetProjectIds: searchAliases.targetProjectIds, } : {}), - preview: - latestItem.preview || `包含 ${items.length} 个线程,最近活跃:《${latestItem.threadTitle}》`, + preview: latestPreview || `包含 ${items.length} 个线程,最近活跃:《${recentThreadLabel || latestItem.threadTitle}》`, lastMessagePreview: - latestItem.lastMessagePreview || - latestItem.preview || - `包含 ${items.length} 个线程,最近活跃:《${latestItem.threadTitle}》`, + latestMessagePreview || + latestPreview || + `包含 ${items.length} 个线程,最近活跃:《${recentThreadLabel || latestItem.threadTitle}》`, activityIconCount: Math.max(0, Math.min(4, items.reduce((sum, entry) => sum + entry.activityIconCount, 0))), latestReplyAt: latestItem.latestReplyAt, latestReplyLabel: latestItem.latestReplyLabel, diff --git a/tests/conversation-home-items.test.ts b/tests/conversation-home-items.test.ts index e8a4153..b630981 100644 --- a/tests/conversation-home-items.test.ts +++ b/tests/conversation-home-items.test.ts @@ -542,6 +542,45 @@ test("folder archive homepage rows keep the project title, compact subtitle, and assert.equal(presentation.href, "/conversations/folders/mac-studio%3Aboss"); }); +test("conversation home compacts imported previews and trims local workspace prefixes from folder subtitles", async () => { + await setup(); + const state = await readState(); + + state.projects = state.projects.filter((project) => project.id === "master-agent"); + state.projects.push( + { + ...buildImportedThreadProject( + "mac-studio", + "wenshen-thread-1", + "wenshenapp", + "/Users/kris/code/wenshenapp", + "/Users/kris/code/wenshenapp/docs/superpowers/specs/2026-04-06-context-cleanup-design.md", + "thread-1", + "2026-04-06T15:00:00+08:00", + ), + preview: "已从设备 Mac Studio 导入线程《/Users/kris/code/wenshenapp/docs/superpowers/specs/2026-04-06-context-cleanup-design.md》。", + lastMessageAt: "2026-04-06T15:00:00+08:00", + }, + buildImportedThreadProject( + "mac-studio", + "wenshen-thread-2", + "wenshenapp", + "/Users/kris/code/wenshenapp", + "补齐 Android 会话可读性", + "thread-2", + "2026-04-06T14:00:00+08:00", + ), + ); + + const folder = getConversationHomeItems(state).find((item) => item.projectId === "mac-studio:/users/kris/code/wenshenapp"); + + assert.ok(folder, "expected grouped folder archive item"); + assert.equal(folder?.conversationType, "folder_archive"); + assert.equal(folder?.folderLabel, "2 个线程 · 最近:wenshenapp/docs/superpowers/specs/2026-04-06-context-cleanup-design.md"); + assert.equal(folder?.preview, "已导入线程"); + assert.equal(folder?.lastMessagePreview, "已导入线程"); +}); + test("folder archive homepage rows expose pin toggles when the folder is pinned", async () => { await setup(); const state = await readState();