fix(core): hide the footer that blocks the toolbar in shared page (#8091)

close PD-1405 CLOUD-64

https://github.com/user-attachments/assets/f6ed2dfc-d238-41d8-abaf-684193a080ff
This commit is contained in:
JimmFly
2024-09-05 07:14:23 +00:00
parent 03c2051926
commit f452414952
11 changed files with 279 additions and 404 deletions
@@ -1,4 +1,4 @@
import type { DocMode } from '@blocksuite/blocks';
import type { DocMode, EdgelessRootService } from '@blocksuite/blocks';
import type { InlineEditor } from '@blocksuite/inline/inline-editor';
import type { AffineEditorContainer, DocTitle } from '@blocksuite/presets';
import type { DocService, WorkspaceService } from '@toeverything/infra';
@@ -23,6 +23,20 @@ export class Editor extends Entity {
readonly editorContainer$ = new LiveData<AffineEditorContainer | null>(null);
isPresenting$ = new LiveData<boolean>(false);
togglePresentation() {
const edgelessRootService =
this.editorContainer$.value?.host?.std.getService(
'affine:page'
) as EdgelessRootService;
if (!edgelessRootService) return;
edgelessRootService.tool.setEdgelessTool({
type: !this.isPresenting$.value ? 'frameNavigator' : 'default',
});
}
setSelector(selector: EditorSelector | undefined) {
this.selector$.next(selector);
}
@@ -145,8 +159,10 @@ export class Editor extends Entity {
bindEditorContainer(
editorContainer: AffineEditorContainer,
docTitle: DocTitle
docTitle: DocTitle | null
) {
const unsubs: (() => void)[] = [];
const focusAt$ = LiveData.computed(get => {
const selector = get(this.selector$);
const id =
@@ -159,26 +175,49 @@ export class Editor extends Entity {
return null;
}
});
if (focusAt$.value === null) {
if (focusAt$.value === null && docTitle) {
const title = docTitle.querySelector<
HTMLElement & { inlineEditor: InlineEditor }
>('rich-text');
title?.inlineEditor.focusEnd();
}
const unsubscribe = focusAt$
.distinctUntilChanged(
(a, b) => a?.id === b?.id && a?.refreshKey === b?.refreshKey
)
.subscribe(params => {
if (params?.id) {
const std = editorContainer.host?.std;
if (std) {
scrollAnchoring(std, this.mode$.value, params.id);
unsubs.push(
focusAt$
.distinctUntilChanged(
(a, b) => a?.id === b?.id && a?.refreshKey === b?.refreshKey
)
.subscribe(params => {
if (params?.id) {
const std = editorContainer.host?.std;
if (std) {
scrollAnchoring(std, this.mode$.value, params.id);
}
}
}
});
}).unsubscribe
);
const edgelessPage = editorContainer.host?.querySelector(
'affine-edgeless-root'
);
if (!edgelessPage) {
this.isPresenting$.next(false);
} else {
this.isPresenting$.next(
edgelessPage.edgelessTool.type === 'frameNavigator'
);
unsubs.push(
edgelessPage.slots.edgelessToolUpdated.on(() => {
this.isPresenting$.next(
edgelessPage.edgelessTool.type === 'frameNavigator'
);
}).dispose
);
}
return () => {
unsubscribe.unsubscribe();
for (const unsub of unsubs) {
unsub();
}
};
}
@@ -4,7 +4,6 @@ import { AIProvider } from '@affine/core/blocksuite/presets/ai';
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
import { BlockSuiteEditor } from '@affine/core/components/blocksuite/block-suite-editor';
import { EditorOutlineViewer } from '@affine/core/components/blocksuite/outline-viewer';
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import { EditorService } from '@affine/core/modules/editor';
import { PageNotFound } from '@affine/core/pages/404';
import { DebugLogger } from '@affine/debug';
@@ -18,7 +17,7 @@ import {
useServices,
} from '@toeverything/infra';
import clsx from 'clsx';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect } from 'react';
import { WorkbenchService } from '../../../workbench';
import { PeekViewService } from '../../services/peek-view';
@@ -75,26 +74,48 @@ function DocPeekPreviewEditor({
const doc = editor.doc;
const workspace = editor.doc.workspace;
const mode = useLiveData(editor.mode$);
const { jumpToTag } = useNavigateHelper();
const workbench = useService(WorkbenchService).workbench;
const peekView = useService(PeekViewService).peekView;
const [editorElement, setEditorElement] =
useState<AffineEditorContainer | null>(null);
const editorElement = useLiveData(editor.editorContainer$);
const onRef = (editor: AffineEditorContainer) => {
setEditorElement(editor);
};
const handleOnEditorReady = useCallback(
(editorContainer: AffineEditorContainer) => {
if (!editorContainer.host) {
return;
}
const disposableGroup = new DisposableGroup();
const rootService = editorContainer.host.std.getService('affine:page');
// doc change event inside peek view should be handled by peek view
disposableGroup.add(
rootService.slots.docLinkClicked.on(options => {
peekView
.open({
type: 'doc',
docId: options.pageId,
...options.params,
})
.catch(console.error);
})
);
useEffect(() => {
editorElement?.updateComplete
.then(() => {
if (mode === 'edgeless') {
fitViewport(editorElement, xywh);
}
})
.catch(console.error);
return;
}, [editorElement, mode, xywh]);
editor.setEditorContainer(editorContainer);
const unbind = editor.bindEditorContainer(
editorContainer,
(editorContainer as any).title
);
if (mode === 'edgeless') {
fitViewport(editorContainer, xywh);
}
return () => {
unbind();
editor.setEditorContainer(null);
disposableGroup.dispose();
};
},
[editor, mode, peekView, xywh]
);
useEffect(() => {
const disposable = AIProvider.slots.requestOpenWithChat.on(() => {
@@ -110,43 +131,6 @@ function DocPeekPreviewEditor({
};
}, [doc, peekView, workbench, workspace.id]);
useEffect(() => {
const disposableGroup = new DisposableGroup();
if (editorElement) {
editorElement.updateComplete
.then(() => {
if (!editorElement.host) {
return;
}
const rootService = editorElement.host.std.getService('affine:page');
// doc change event inside peek view should be handled by peek view
disposableGroup.add(
rootService.slots.docLinkClicked.on(options => {
peekView
.open({
type: 'doc',
docId: options.pageId,
...options.params,
})
.catch(console.error);
})
);
// TODO(@Peng): no tag peek view yet
disposableGroup.add(
rootService.slots.tagClicked.on(({ tagId }) => {
jumpToTag(workspace.id, tagId);
peekView.close();
})
);
})
.catch(console.error);
}
return () => {
disposableGroup.dispose();
};
}, [editorElement, jumpToTag, peekView, workspace.id]);
const openOutlinePanel = useCallback(() => {
workbench.openDoc(doc.id);
workbench.openSidebar();
@@ -161,10 +145,10 @@ function DocPeekPreviewEditor({
className={clsx('affine-page-viewport', styles.affineDocViewport)}
>
<BlockSuiteEditor
ref={onRef}
className={styles.editor}
mode={mode}
page={doc.blockSuiteDoc}
onEditorReady={handleOnEditorReady}
/>
<EditorOutlineViewer
editor={editorElement}