feat: 完善图像工作区与创作工具体验
This commit is contained in:
@@ -21,15 +21,16 @@ type TitleBarProps = {
|
||||
integrated?: boolean;
|
||||
workspaceLayout?: boolean;
|
||||
overlay?: boolean;
|
||||
pageTitle?: string;
|
||||
sidebarPeekOpen?: boolean;
|
||||
onSidebarPeekChange?: SidebarPeekChange;
|
||||
};
|
||||
|
||||
export function TitleBar({ integrated = false, workspaceLayout = false, overlay = false, sidebarPeekOpen = false, onSidebarPeekChange }: TitleBarProps) {
|
||||
export function TitleBar({ integrated = false, workspaceLayout = false, overlay = false, pageTitle, sidebarPeekOpen = false, onSidebarPeekChange }: TitleBarProps) {
|
||||
const platform = window.electron?.platform;
|
||||
|
||||
if (platform === 'darwin') {
|
||||
return <ProductTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} nativeTrafficLights sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange} />;
|
||||
return <ProductTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} pageTitle={pageTitle} nativeTrafficLights sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange} />;
|
||||
}
|
||||
|
||||
// Linux keeps the native frame/title bar for better IME compatibility.
|
||||
@@ -37,13 +38,14 @@ export function TitleBar({ integrated = false, workspaceLayout = false, overlay
|
||||
return null;
|
||||
}
|
||||
|
||||
return <WindowsTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange} />;
|
||||
return <WindowsTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} pageTitle={pageTitle} sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange} />;
|
||||
}
|
||||
|
||||
function ProductTitleBar({
|
||||
integrated,
|
||||
workspaceLayout = false,
|
||||
overlay = false,
|
||||
pageTitle,
|
||||
children,
|
||||
nativeTrafficLights = false,
|
||||
sidebarPeekOpen = false,
|
||||
@@ -52,15 +54,16 @@ function ProductTitleBar({
|
||||
integrated: boolean;
|
||||
workspaceLayout?: boolean;
|
||||
overlay?: boolean;
|
||||
pageTitle?: string;
|
||||
children?: React.ReactNode;
|
||||
nativeTrafficLights?: boolean;
|
||||
sidebarPeekOpen?: boolean;
|
||||
onSidebarPeekChange?: SidebarPeekChange;
|
||||
}) {
|
||||
const sidebarCollapsed = useSettingsStore((state) => state.sidebarCollapsed);
|
||||
const setSidebarCollapsed = useSettingsStore((state) => state.setSidebarCollapsed);
|
||||
const activeProject = useOpencodeStore((state) => state.activeProject);
|
||||
const toolbarButtonClass = 'no-drag motion-press flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-surface-subtle hover:text-foreground';
|
||||
const setSidebarCollapsed = useSettingsStore((state) => state.setSidebarCollapsed);
|
||||
const toggleSidebar = () => setSidebarCollapsed(!sidebarCollapsed);
|
||||
const handleSidebarPeekEnter = (source: SidebarPeekSource) => {
|
||||
if (sidebarCollapsed) onSidebarPeekChange?.(true, source);
|
||||
@@ -134,8 +137,9 @@ function ProductTitleBar({
|
||||
<div
|
||||
data-testid="product-titlebar"
|
||||
className={cn(
|
||||
'relative z-30 flex h-10 shrink-0 text-foreground',
|
||||
overlay && 'pointer-events-none absolute inset-x-0 top-0 z-[300] bg-transparent',
|
||||
overlay ? 'absolute' : 'relative',
|
||||
'z-30 flex h-10 shrink-0 text-foreground',
|
||||
overlay && 'pointer-events-none inset-x-0 top-0 z-[300] bg-transparent',
|
||||
(!nativeTrafficLights || !integrated) && 'drag-region',
|
||||
!workspaceLayout && !overlay && 'glass-surface',
|
||||
integrated && !overlay && (workspaceLayout ? 'bg-transparent' : sidebarTitlebarHidden ? 'bg-background' : 'bg-background/70'),
|
||||
@@ -155,13 +159,14 @@ function ProductTitleBar({
|
||||
: workspaceLayout
|
||||
? 'w-[256px] min-w-[256px] basis-[256px]'
|
||||
: 'w-64',
|
||||
sidebarTitlebarHidden
|
||||
? 'border-r-0 bg-background'
|
||||
: cn(
|
||||
sidebarPreviewTitlebarVisible ? 'sidebar-peek-surface' : 'sidebar-glass-surface',
|
||||
'border-r border-border/80',
|
||||
),
|
||||
overlay && 'pointer-events-none border-r-0 bg-transparent',
|
||||
overlay
|
||||
? 'pointer-events-none border-r-0 bg-transparent'
|
||||
: sidebarTitlebarHidden
|
||||
? 'border-r-0 bg-background'
|
||||
: cn(
|
||||
sidebarPreviewTitlebarVisible ? 'sidebar-peek-surface' : 'sidebar-glass-surface',
|
||||
'border-r border-border/80',
|
||||
),
|
||||
nativeTrafficLights && 'pl-[88px]',
|
||||
)}
|
||||
onPointerEnter={sidebarPreviewTitlebarVisible ? () => handleSidebarPeekEnter('titlebar') : undefined}
|
||||
@@ -191,7 +196,14 @@ function ProductTitleBar({
|
||||
style={{ left: conversationSurfaceOffset }}
|
||||
/>
|
||||
) : null}
|
||||
{!workspaceLayout && !overlay ? (
|
||||
{pageTitle ? (
|
||||
<h1
|
||||
data-testid="titlebar-page-title"
|
||||
className="flex min-w-0 flex-1 items-center truncate px-3 text-sm font-semibold tracking-[-0.02em]"
|
||||
>
|
||||
{pageTitle}
|
||||
</h1>
|
||||
) : !workspaceLayout && !overlay ? (
|
||||
<div
|
||||
data-testid="titlebar-project-context"
|
||||
className={cn(
|
||||
@@ -220,7 +232,7 @@ function ProductTitleBar({
|
||||
);
|
||||
}
|
||||
|
||||
function WindowsTitleBar({ integrated, workspaceLayout, overlay, sidebarPeekOpen, onSidebarPeekChange }: Omit<TitleBarProps, 'integrated'> & { integrated: boolean }) {
|
||||
function WindowsTitleBar({ integrated, workspaceLayout, overlay, pageTitle, sidebarPeekOpen, onSidebarPeekChange }: Omit<TitleBarProps, 'integrated'> & { integrated: boolean }) {
|
||||
const [maximized, setMaximized] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -247,7 +259,7 @@ function WindowsTitleBar({ integrated, workspaceLayout, overlay, sidebarPeekOpen
|
||||
};
|
||||
|
||||
return (
|
||||
<ProductTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange}>
|
||||
<ProductTitleBar integrated={integrated} workspaceLayout={workspaceLayout} overlay={overlay} pageTitle={pageTitle} sidebarPeekOpen={sidebarPeekOpen} onSidebarPeekChange={onSidebarPeekChange}>
|
||||
<div className="no-drag pointer-events-auto flex h-full">
|
||||
<button
|
||||
onClick={handleMinimize}
|
||||
|
||||
Reference in New Issue
Block a user