perf: optimize app startup and background lifecycles

This commit is contained in:
inman committed 2026-08-19 00:56:15 +08:00
1 parent 31332f6d76
commit 927e13349b
121 files changed
+4359 -1400

No files matched your search

+12 -12
View File
@@ -42,8 +42,8 @@ type ProjectDialogState =
const VISIBLE_CONVERSATION_LIMIT = 5;
const CONVERSATION_PREVIEW_LIMIT = 28;
const PROJECT_ACTION_BUTTON_CLASS = 'flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground pointer-events-none opacity-0 transition-[opacity,background-color,color,transform] group-hover/project:pointer-events-auto group-hover/project:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100';
const IMAGE_SIDEBAR_ACTION_CLASS = 'motion-press flex min-h-9 w-full items-center justify-start gap-2 rounded-lg border-0 bg-transparent px-2 py-1.5 text-left text-sm font-medium text-foreground shadow-none transition-[background-color,color,transform] hover:bg-surface-subtle hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/35 focus-visible:ring-offset-1 active:scale-[0.985]';
const PROJECT_ACTION_BUTTON_CLASS = 'relative z-10 flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground pointer-events-none opacity-0 transition-colors duration-100 group-hover/project:pointer-events-auto group-hover/project:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100';
const IMAGE_SIDEBAR_ACTION_CLASS = 'motion-press flex min-h-9 w-full items-center justify-start gap-2 rounded-lg border-0 bg-transparent px-2 py-1.5 text-left text-sm font-medium text-foreground shadow-none transition-colors duration-100 hover:bg-surface-subtle hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/35 focus-visible:ring-offset-1';
function conversationTimestamp(conversation: DesignConversationSummary): number {
const timestamp = Date.parse(conversation.updatedAt);
@@ -364,7 +364,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
aria-current={selected ? 'page' : undefined}
title={`${conversation.title}:${fullPreview}`}
className={cn(
'group/image-conversation flex w-full min-w-0 items-center gap-1.5 rounded-lg px-1.5 py-1.5 text-left transition-[background-color,color,transform] active:scale-[0.985]',
'group/image-conversation flex w-full min-w-0 items-center gap-1.5 rounded-lg px-1.5 py-1.5 text-left transition-colors duration-100',
selected
? 'bg-background text-foreground shadow-soft'
: 'text-muted-foreground hover:bg-background/70 hover:text-foreground',
@@ -386,7 +386,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
key={project.workspaceId}
data-testid={`sidebar-image-project-${project.workspaceId}`}
className={cn(
'motion-press group/project relative overflow-hidden rounded-lg border px-2 py-1.5 text-left transition-[background-color,border-color,color]',
'motion-press group/project relative overflow-hidden rounded-lg border px-2 py-1.5 text-left transition-colors duration-100',
active
? 'border-brand/35 bg-brand-soft shadow-soft before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-brand'
: 'border-transparent bg-transparent hover:border-border/70 hover:bg-surface-subtle',
@@ -399,7 +399,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
<button
type="button"
aria-current={active ? 'page' : undefined}
className="flex min-w-0 flex-1 items-center gap-2 text-left"
className="flex min-w-0 flex-1 items-center gap-2 pr-28 text-left"
onClick={() => handleSelectProject(project.workspaceId)}
>
<span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-surface-input text-foreground">
@@ -407,24 +407,24 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
</span>
<span className="min-w-0 flex-1 truncate text-sm font-semibold">{project.title}</span>
</button>
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center gap-1">
<div className="pointer-events-none absolute inset-y-0 right-0 z-10 flex items-center gap-1">
<button
type="button"
aria-label={projectExpanded ? `收起 ${project.title} 的会话` : `展开 ${project.title} 的会话`}
title={projectExpanded ? `收起 ${project.title} 的会话` : `展开 ${project.title} 的会话`}
aria-expanded={active ? projectExpanded : undefined}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-foreground active:scale-[0.96]')}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-foreground')}
onClick={() => handleToggleProject(project.workspaceId)}
>
<ChevronDown
data-testid={`sidebar-image-project-toggle-icon-${project.workspaceId}`}
className={cn('h-3.5 w-3.5 transition-transform duration-200 ease-out', projectExpanded && 'rotate-180')}
className={cn('h-3.5 w-3.5', projectExpanded && 'rotate-180')}
/>
</button>
<button
type="button"
aria-label={`重命名 ${project.title}`}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-foreground active:scale-[0.96]')}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-foreground')}
onClick={() => openRenameDialog(project)}
>
<Pencil className="h-3.5 w-3.5" />
@@ -434,7 +434,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
aria-label="新建设计会话"
title="新建设计会话"
aria-busy={creatingConversation}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-brand active:scale-[0.96]')}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-background hover:text-brand')}
disabled={creatingConversation || !workspace || workspace.workspaceId !== project.workspaceId}
onClick={() => void handleCreateConversation()}
>
@@ -447,7 +447,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
data-testid={`sidebar-delete-image-project-${project.workspaceId}`}
aria-label={`删除 ${project.title}`}
title={`删除 ${project.title}`}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-destructive/10 hover:text-destructive active:scale-[0.96]')}
className={cn(PROJECT_ACTION_BUTTON_CLASS, 'hover:bg-destructive/10 hover:text-destructive')}
onClick={() => openDeleteDialog(project)}
>
<Trash2 className="h-3.5 w-3.5" />
@@ -489,7 +489,7 @@ export function ImageWorkspaceSidebar({ sidebarCollapsed }: ImageWorkspaceSideba
}))}
>
<span>更多会话({hiddenConversations.length})</span>
<ChevronRight className={cn('h-3.5 w-3.5 transition-transform duration-200 ease-out', moreConversationsOpen && 'rotate-90')} />
<ChevronRight className={cn('h-3.5 w-3.5', moreConversationsOpen && 'rotate-90')} />
</button>
<DisclosureContent
open={moreConversationsOpen}