mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(editor): improve visibility of hidden content of edgeless note (#12068)
Close [BS-3066](https://linear.app/affine-design/issue/BS-3066/优化长note的展示和折叠) - Enhanced the visibility behavior of hidden content in edgeless notes by: - Showing hidden content when a note is being edited, even when it's outside the viewport - Improving hover behavior with a delay when leaving from the bottom of the note - Adding proper cleanup of hover timeouts when the component is disconnected - Optimizing the viewport element to keep editing blocks or elements visible ## Testing - Added new E2E test cases covering: - Hover behavior on selected notes - Content visibility during editing - Viewport scrolling behavior - Edge cases for content visibility ## Impact This change improves the user experience when working with collapsed notes in edgeless mode by making the content more accessible and preventing accidental content hiding during editing. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved visibility of hidden content in edgeless notes when hovering near the bottom edge or editing the note, especially after resizing or clipping. - **New Features** - Enhanced hover behavior with delayed clearing based on mouse position to improve user experience. - **Tests** - Added new tests verifying hidden content visibility in edgeless notes during hover and editing, simulating diverse user interactions. - **Chores** - Added utilities to get and set viewport center for improved test control. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
||||
} from '../view';
|
||||
import { PropTypes, requiredProperties } from '../view/decorators/required';
|
||||
import { GfxControllerIdentifier } from './identifiers';
|
||||
import type { GfxBlockElementModel } from './model/gfx-block-model';
|
||||
import { GfxBlockElementModel } from './model/gfx-block-model';
|
||||
import { Viewport } from './viewport';
|
||||
|
||||
/**
|
||||
@@ -66,14 +66,17 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) {
|
||||
}
|
||||
`;
|
||||
|
||||
private readonly _hideOutsideBlock = () => {
|
||||
private readonly _hideOutsideNoEditingBlock = () => {
|
||||
if (!this.host) return;
|
||||
|
||||
const gfx = this.host.std.get(GfxControllerIdentifier);
|
||||
const modelsInViewport = this.getModelsInViewport();
|
||||
const nextVisibleModels = new Set([
|
||||
...this.getModelsInViewport(),
|
||||
...this._getEditingModels(),
|
||||
]);
|
||||
|
||||
batch(() => {
|
||||
modelsInViewport.forEach(model => {
|
||||
nextVisibleModels.forEach(model => {
|
||||
const view = gfx.view.get(model);
|
||||
if (isGfxBlockComponent(view)) {
|
||||
view.transformState$.value = 'active';
|
||||
@@ -92,7 +95,7 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) {
|
||||
});
|
||||
});
|
||||
|
||||
this._lastVisibleModels = modelsInViewport;
|
||||
this._lastVisibleModels = nextVisibleModels;
|
||||
};
|
||||
|
||||
private _lastVisibleModels?: Set<GfxBlockElementModel>;
|
||||
@@ -103,7 +106,7 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) {
|
||||
}[] = [];
|
||||
|
||||
private readonly _refreshViewport = requestThrottledConnectedFrame(() => {
|
||||
this._hideOutsideBlock();
|
||||
this._hideOutsideNoEditingBlock();
|
||||
}, this);
|
||||
|
||||
private _updatingChildrenFlag = false;
|
||||
@@ -119,7 +122,7 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) {
|
||||
delete this.scheduleUpdateChildren;
|
||||
}
|
||||
|
||||
this._hideOutsideBlock();
|
||||
this._hideOutsideNoEditingBlock();
|
||||
this.disposables.add(
|
||||
this.viewport.viewportUpdated.subscribe(() => viewportUpdateCallback())
|
||||
);
|
||||
@@ -166,6 +169,18 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) {
|
||||
return promise;
|
||||
};
|
||||
|
||||
private _getEditingModels(): Set<GfxBlockElementModel> {
|
||||
if (!this.host) return new Set();
|
||||
const gfx = this.host.std.get(GfxControllerIdentifier);
|
||||
return new Set(
|
||||
gfx.selection.surfaceSelections
|
||||
.filter(s => s.editing)
|
||||
.flatMap(({ elements }) => elements)
|
||||
.map(id => gfx.getElementById(id))
|
||||
.filter(e => e instanceof GfxBlockElementModel)
|
||||
);
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor getModelsInViewport: () => Set<GfxBlockElementModel> = () =>
|
||||
new Set();
|
||||
|
||||
Reference in New Issue
Block a user