feat(core): auto expand workbench sidebar when opening ai preview panel (#13058)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added the ability to programmatically open and close the AI chat
preview panel, with improved control over its visibility and content.
* Introduced event notifications for preview panel open/close actions,
enabling responsive UI updates.

* **Enhancements**
* Automatically adjusts the sidebar width to a minimum value when the
preview panel is opened for optimal viewing.
* Improved synchronization between sidebar width and external changes,
ensuring a consistent user experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Cats Juice
2025-07-07 14:35:54 +08:00
committed by GitHub
parent 6175bde86e
commit 563a14d0b3
5 changed files with 52 additions and 11 deletions
@@ -1,4 +1,4 @@
import { ChatPanel } from '@affine/core/blocksuite/ai';
import { AIProvider, ChatPanel } from '@affine/core/blocksuite/ai';
import type { AffineEditorContainer } from '@affine/core/blocksuite/block-suite-editor';
import { useAIChatConfig } from '@affine/core/components/hooks/affine/use-ai-chat-config';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
@@ -8,8 +8,8 @@ import { ViewExtensionManagerIdentifier } from '@blocksuite/affine/ext-loader';
import { RefNodeSlotsProvider } from '@blocksuite/affine/inlines/reference';
import { DocModeProvider } from '@blocksuite/affine/shared/services';
import { createSignalFromObservable } from '@blocksuite/affine/shared/utils';
import { useFramework } from '@toeverything/infra';
import { forwardRef, useEffect, useRef } from 'react';
import { useFramework, useService } from '@toeverything/infra';
import { forwardRef, useEffect, useRef, useState } from 'react';
import * as styles from './chat.css';
@@ -25,6 +25,7 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel(
) {
const chatPanelRef = useRef<ChatPanel | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null);
const workbench = useService(WorkbenchService).workbench;
const framework = useFramework();
useEffect(() => {
@@ -118,5 +119,25 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel(
playgroundConfig,
]);
const [autoResized, setAutoResized] = useState(false);
useEffect(() => {
// after auto expanded first time, do not auto expand again(even if user manually resized)
if (autoResized) return;
const subscription = AIProvider.slots.previewPanelOpenChange.subscribe(
open => {
if (!open) return;
const sidebarWidth = workbench.sidebarWidth$.value;
const MIN_SIDEBAR_WIDTH = 1080;
if (!sidebarWidth || sidebarWidth < MIN_SIDEBAR_WIDTH) {
workbench.setSidebarWidth(MIN_SIDEBAR_WIDTH);
setAutoResized(true);
}
}
);
return () => {
subscription.unsubscribe();
};
}, [autoResized, workbench]);
return <div className={styles.root} ref={containerRef} />;
});