fix(editor): adjust highlght style of comment and comment editor flickering (#13040)
### Before https://github.com/user-attachments/assets/6b98946b-d53c-42fb-b341-e09ba5204523 ### After https://github.com/user-attachments/assets/274341de-33c4-4fd3-b01b-a8f7c25bf2fe #### PR Dependency Tree * **PR #13040** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved comment highlighting: Clicking now cycles through and highlights individual comments one at a time instead of highlighting all at once. * Highlighting behavior is now more flexible, allowing highlighting to be toggled on or off in certain scenarios. * **Bug Fixes** * Prevented flickering in the comment editor when focusing on comments. * **Refactor** * Enhanced selection and anchoring logic to support the new highlight flag and updated types for improved clarity and control. <!-- end of auto-generated comment: release notes by coderabbit.ai --> #### PR Dependency Tree * **PR #13040** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal)
This commit is contained in:
@@ -41,6 +41,8 @@ export class InlineComment extends WithDisposable(ShadowlessElement) {
|
|||||||
})
|
})
|
||||||
accessor commentIds!: string[];
|
accessor commentIds!: string[];
|
||||||
|
|
||||||
|
private _index: number = 0;
|
||||||
|
|
||||||
@consume({ context: stdContext })
|
@consume({ context: stdContext })
|
||||||
private accessor _std!: BlockStdScope;
|
private accessor _std!: BlockStdScope;
|
||||||
|
|
||||||
@@ -52,8 +54,8 @@ export class InlineComment extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly _handleClick = () => {
|
private readonly _handleClick = () => {
|
||||||
const provider = this._provider;
|
this._provider?.highlightComment(this.commentIds[this._index]);
|
||||||
provider && this.commentIds.forEach(id => provider.highlightComment(id));
|
this._index = (this._index + 1) % this.commentIds.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly _handleHighlight = (id: CommentId | null) => {
|
private readonly _handleHighlight = (id: CommentId | null) => {
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import {
|
import { ReferenceParamsSchema } from '@blocksuite/affine-model';
|
||||||
type ReferenceParams,
|
|
||||||
ReferenceParamsSchema,
|
|
||||||
} from '@blocksuite/affine-model';
|
|
||||||
import { BaseSelection, SelectionExtension } from '@blocksuite/store';
|
import { BaseSelection, SelectionExtension } from '@blocksuite/store';
|
||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
const HighlightSelectionParamsSchema = ReferenceParamsSchema.extend({
|
||||||
|
highlight: z.boolean().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
type HighlightSelectionParams = z.infer<typeof HighlightSelectionParamsSchema>;
|
||||||
|
|
||||||
export class HighlightSelection extends BaseSelection {
|
export class HighlightSelection extends BaseSelection {
|
||||||
static override group = 'scene';
|
static override group = 'scene';
|
||||||
@@ -15,16 +19,24 @@ export class HighlightSelection extends BaseSelection {
|
|||||||
|
|
||||||
readonly mode: 'page' | 'edgeless' = 'page';
|
readonly mode: 'page' | 'edgeless' = 'page';
|
||||||
|
|
||||||
constructor({ mode, blockIds, elementIds }: ReferenceParams) {
|
readonly highlight: boolean = true;
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
mode,
|
||||||
|
blockIds,
|
||||||
|
elementIds,
|
||||||
|
highlight = true,
|
||||||
|
}: HighlightSelectionParams) {
|
||||||
super({ blockId: '[scene-highlight]' });
|
super({ blockId: '[scene-highlight]' });
|
||||||
|
|
||||||
this.mode = mode ?? 'page';
|
this.mode = mode ?? 'page';
|
||||||
this.blockIds = blockIds ?? [];
|
this.blockIds = blockIds ?? [];
|
||||||
this.elementIds = elementIds ?? [];
|
this.elementIds = elementIds ?? [];
|
||||||
|
this.highlight = highlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static override fromJSON(json: Record<string, unknown>): HighlightSelection {
|
static override fromJSON(json: Record<string, unknown>): HighlightSelection {
|
||||||
const result = ReferenceParamsSchema.parse(json);
|
const result = HighlightSelectionParamsSchema.parse(json);
|
||||||
return new HighlightSelection(result);
|
return new HighlightSelection(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|||||||
type Anchor = {
|
type Anchor = {
|
||||||
id: string;
|
id: string;
|
||||||
mode: DocMode;
|
mode: DocMode;
|
||||||
|
highlight: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AFFINE_SCROLL_ANCHORING_WIDGET = 'affine-scroll-anchoring-widget';
|
export const AFFINE_SCROLL_ANCHORING_WIDGET = 'affine-scroll-anchoring-widget';
|
||||||
@@ -221,6 +222,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent {
|
|||||||
mode,
|
mode,
|
||||||
blockIds: [bid],
|
blockIds: [bid],
|
||||||
elementIds: [eid],
|
elementIds: [eid],
|
||||||
|
highlight,
|
||||||
} = highlighted;
|
} = highlighted;
|
||||||
const id = mode === 'page' ? bid : eid || bid;
|
const id = mode === 'page' ? bid : eid || bid;
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
@@ -228,7 +230,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent {
|
|||||||
// Consumes highlight selection
|
// Consumes highlight selection
|
||||||
this.std.selection.clear(['highlight']);
|
this.std.selection.clear(['highlight']);
|
||||||
|
|
||||||
this.anchor$.value = { mode, id };
|
this.anchor$.value = { mode, id, highlight };
|
||||||
this.#listened = true;
|
this.#listened = true;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -241,7 +243,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent {
|
|||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
const anchor = this.anchor$.value;
|
const anchor = this.anchor$.value;
|
||||||
if (!anchor) return nothing;
|
if (!anchor || !anchor.highlight) return nothing;
|
||||||
|
|
||||||
const { mode, id } = anchor;
|
const { mode, id } = anchor;
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export class Editor extends Entity {
|
|||||||
const mode = get(this.mode$);
|
const mode = get(this.mode$);
|
||||||
let id = selector?.blockIds?.[0];
|
let id = selector?.blockIds?.[0];
|
||||||
let commentId = selector?.commentId;
|
let commentId = selector?.commentId;
|
||||||
let key = 'blockIds';
|
let key: 'blockIds' | 'elementIds' = 'blockIds';
|
||||||
|
|
||||||
if (mode === 'edgeless') {
|
if (mode === 'edgeless') {
|
||||||
const elementId = selector?.elementIds?.[0];
|
const elementId = selector?.elementIds?.[0];
|
||||||
@@ -195,7 +195,7 @@ export class Editor extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFocusAt(focusAt: {
|
handleFocusAt(focusAt: {
|
||||||
key: string;
|
key: 'blockIds' | 'elementIds';
|
||||||
mode: DocMode;
|
mode: DocMode;
|
||||||
id?: string;
|
id?: string;
|
||||||
commentId?: string;
|
commentId?: string;
|
||||||
@@ -208,6 +208,7 @@ export class Editor extends Entity {
|
|||||||
|
|
||||||
let finalId = id;
|
let finalId = id;
|
||||||
let finalKey = key;
|
let finalKey = key;
|
||||||
|
let highlight = true;
|
||||||
|
|
||||||
// If we have commentId but no blockId, find the block from the comment
|
// If we have commentId but no blockId, find the block from the comment
|
||||||
if (commentId && !id && editorContainer.host?.std) {
|
if (commentId && !id && editorContainer.host?.std) {
|
||||||
@@ -230,6 +231,9 @@ export class Editor extends Entity {
|
|||||||
finalKey = 'blockIds';
|
finalKey = 'blockIds';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Workaround: clear selection to avoid comment editor flickering
|
||||||
|
selection?.clear();
|
||||||
|
highlight = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === this.mode$.value && finalId) {
|
if (mode === this.mode$.value && finalId) {
|
||||||
@@ -237,7 +241,8 @@ export class Editor extends Entity {
|
|||||||
selection?.create(HighlightSelection, {
|
selection?.create(HighlightSelection, {
|
||||||
mode,
|
mode,
|
||||||
[finalKey]: [finalId],
|
[finalKey]: [finalId],
|
||||||
}),
|
highlight,
|
||||||
|
} as const),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user