mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
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:
@@ -174,10 +174,10 @@ export class AIChatContent extends SignalWatcher(
|
||||
accessor isHistoryLoading = false;
|
||||
|
||||
@state()
|
||||
accessor showPreviewPanel = false;
|
||||
private accessor showPreviewPanel = false;
|
||||
|
||||
@state()
|
||||
accessor previewPanelContent: TemplateResult<1> | null = null;
|
||||
private accessor previewPanelContent: TemplateResult<1> | null = null;
|
||||
|
||||
private readonly chatMessagesRef: Ref<AIChatMessages> =
|
||||
createRef<AIChatMessages>();
|
||||
@@ -338,8 +338,23 @@ export class AIChatContent extends SignalWatcher(
|
||||
|
||||
public reset() {
|
||||
this.updateContext(DEFAULT_CHAT_CONTEXT_VALUE);
|
||||
this.closePreviewPanel(true);
|
||||
}
|
||||
|
||||
public openPreviewPanel(content?: TemplateResult<1>) {
|
||||
this.showPreviewPanel = true;
|
||||
if (content) this.previewPanelContent = content;
|
||||
AIProvider.slots.previewPanelOpenChange.next(true);
|
||||
}
|
||||
|
||||
public closePreviewPanel(destroyContent: boolean = false) {
|
||||
this.showPreviewPanel = false;
|
||||
this.previewPanelContent = null;
|
||||
if (destroyContent) this.previewPanelContent = null;
|
||||
AIProvider.slots.previewPanelOpenChange.next(false);
|
||||
}
|
||||
|
||||
public get isPreviewPanelOpen() {
|
||||
return this.showPreviewPanel;
|
||||
}
|
||||
|
||||
override connectedCallback() {
|
||||
|
||||
@@ -13,7 +13,7 @@ function getChatPanel(target: HTMLElement) {
|
||||
|
||||
export const isPreviewPanelOpen = (target: HTMLElement) => {
|
||||
const chatPanel = getChatPanel(target);
|
||||
return chatPanel?.showPreviewPanel ?? false;
|
||||
return chatPanel?.isPreviewPanelOpen ?? false;
|
||||
};
|
||||
|
||||
export const renderPreviewPanel = (
|
||||
@@ -28,13 +28,11 @@ export const renderPreviewPanel = (
|
||||
return;
|
||||
}
|
||||
|
||||
chatPanel.showPreviewPanel = true;
|
||||
|
||||
const preview = html`<artifact-preview-panel
|
||||
.content=${content}
|
||||
.controls=${controls ?? nothing}
|
||||
></artifact-preview-panel>`;
|
||||
chatPanel.previewPanelContent = preview;
|
||||
chatPanel.openPreviewPanel(preview);
|
||||
};
|
||||
|
||||
export const closePreviewPanel = (target: HTMLElement) => {
|
||||
@@ -45,7 +43,7 @@ export const closePreviewPanel = (target: HTMLElement) => {
|
||||
return;
|
||||
}
|
||||
|
||||
chatPanel.showPreviewPanel = false;
|
||||
chatPanel.closePreviewPanel();
|
||||
};
|
||||
|
||||
export class ArtifactPreviewPanel extends WithDisposable(ShadowlessElement) {
|
||||
|
||||
@@ -149,6 +149,7 @@ export class AIProvider {
|
||||
}>(),
|
||||
// downstream can emit this slot to notify ai presets that user info has been updated
|
||||
userInfo: new Subject<AIUserInfo | null>(),
|
||||
previewPanelOpenChange: new Subject<boolean>(),
|
||||
/* eslint-enable rxjs/finnish */
|
||||
};
|
||||
|
||||
|
||||
@@ -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} />;
|
||||
});
|
||||
|
||||
@@ -117,6 +117,7 @@ const WorkbenchSidebar = () => {
|
||||
const [resizing, setResizing] = useState(false);
|
||||
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const sidebarWidth = useLiveData(workbench.sidebarWidth$);
|
||||
const [width, setWidth] = useState(workbench.sidebarWidth$.value ?? 0);
|
||||
|
||||
const views = useLiveData(workbench.views$);
|
||||
@@ -152,6 +153,11 @@ const WorkbenchSidebar = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (resizing) return;
|
||||
setWidth(sidebarWidth ?? 0);
|
||||
}, [resizing, sidebarWidth]);
|
||||
|
||||
return (
|
||||
<ResizePanel
|
||||
floating={floating}
|
||||
|
||||
Reference in New Issue
Block a user