L-Sun
2025-01-19 08:35:02 +00:00
parent 9d61b41c05
commit 6ba802fb17
13 changed files with 224 additions and 8 deletions

View File

@@ -47,6 +47,7 @@
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.6",
"@vanilla-extract/css": "^1.17.0",
"date-fns": "^4.0.0",
"dompurify": "^3.1.6",
"fflate": "^0.8.2",

View File

@@ -30,16 +30,18 @@ import {
} from '@blocksuite/affine-model';
import {
FeatureFlagService,
NotificationProvider,
SidebarExtensionIdentifier,
ThemeProvider,
} from '@blocksuite/affine-shared/services';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import {
assertExists,
Bound,
countBy,
maxBy,
WithDisposable,
} from '@blocksuite/global/utils';
import { LinkedPageIcon } from '@blocksuite/icons/lit';
import { html, LitElement, nothing, type TemplateResult } from 'lit';
import { property, query } from 'lit/decorators.js';
import { join } from 'lit/directives/join.js';
@@ -52,6 +54,7 @@ import {
} from '../../edgeless/components/panel/line-styles-panel.js';
import { getTooltipWithShortcut } from '../../edgeless/components/utils.js';
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
import * as styles from './styles.css';
const SIZE_LIST = [
{ name: 'None', value: 0 },
@@ -141,15 +144,17 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
.getFlag('enable_advanced_block_visibility');
}
private get _pageBlockHeaderEnabled() {
return this.doc.get(FeatureFlagService).getFlag('enable_page_block_header');
}
private get doc() {
return this.edgeless.doc;
}
private get _enableAutoHeight() {
return !(
this.edgeless.doc
.get(FeatureFlagService)
.getFlag('enable_page_block_header') &&
this._pageBlockHeaderEnabled &&
this.notes.length === 1 &&
this.notes[0].parent?.children.find(child =>
matchFlavours(child, ['affine:note'])
@@ -195,13 +200,16 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
return;
}
this.doc.captureSync();
this.crud.updateElement(note.id, { displayMode: newMode });
const noteParent = this.doc.getParent(note);
assertExists(noteParent);
if (!noteParent) return;
const noteParentChildNotes = noteParent.children.filter(block =>
matchFlavours(block, ['affine:note'])
) as NoteBlockModel[];
);
const noteParentLastNote =
noteParentChildNotes[noteParentChildNotes.length - 1];
@@ -218,6 +226,61 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
if (newMode === NoteDisplayMode.DocOnly) {
this.edgeless.service.selection.clear();
}
const abortController = new AbortController();
const clear = () => {
this.doc.history.off('stack-item-added', addHandler);
this.doc.history.off('stack-item-popped', popHandler);
disposable.dispose();
};
const closeNotify = () => {
abortController.abort();
clear();
};
const addHandler = this.doc.history.on('stack-item-added', closeNotify);
const popHandler = this.doc.history.on('stack-item-popped', closeNotify);
const disposable = this.edgeless.std.host.slots.unmounted.on(closeNotify);
const undo = () => {
this.doc.undo();
closeNotify();
};
const viewInToc = () => {
const sidebar = this.edgeless.std.getOptional(SidebarExtensionIdentifier);
sidebar?.open('outline');
closeNotify();
};
const notification = this.edgeless.std.getOptional(NotificationProvider);
notification?.notify({
title: 'Note displayed in Page Mode',
message:
'Content added to your page. Find it in the TOC for quick navigation.',
accent: 'success',
duration: 1000 * 1000,
footer: html`<div class=${styles.viewInPageNotifyFooter}>
<button
class=${styles.viewInPageNotifyFooterButton}
@click=${undo}
data-testid="undo-display-in-page"
>
Undo
</button>
<button
class=${styles.viewInPageNotifyFooterButton}
@click=${viewInToc}
data-testid="view-in-toc"
>
View in Toc
</button>
</div>`,
abort: abortController.signal,
onClose: () => {
clear();
},
});
}
private _setShadowType(shadowType: string) {
@@ -286,6 +349,11 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
const currentMode = DisplayModeMap[displayMode];
const onlyOne = len === 1;
const isDocOnly = displayMode === NoteDisplayMode.DocOnly;
const isFirstNote =
onlyOne &&
note.parent?.children.find(child =>
matchFlavours(child, ['affine:note'])
) === note;
const theme = this.edgeless.std.get(ThemeProvider).theme;
const buttons = [
onlyOne && this._advancedVisibilityEnabled
@@ -315,6 +383,32 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
`
: nothing,
onlyOne &&
!isFirstNote &&
this._pageBlockHeaderEnabled &&
!this._advancedVisibilityEnabled
? html`<editor-icon-button
aria-label="Display In Page"
.showTooltip=${displayMode === NoteDisplayMode.DocAndEdgeless}
.tooltip=${'This note is part of Page Mode. Click to remove it from the page.'}
data-testid="display-in-page"
@click=${() =>
this._setDisplayMode(
note,
displayMode === NoteDisplayMode.EdgelessOnly
? NoteDisplayMode.DocAndEdgeless
: NoteDisplayMode.EdgelessOnly
)}
>
${LinkedPageIcon({ width: '20px', height: '20px' })}
<span class="label"
>${displayMode === NoteDisplayMode.EdgelessOnly
? 'Display In Page'
: 'Displayed In Page'}</span
>
</editor-icon-button>`
: nothing,
isDocOnly
? nothing
: when(

View File

@@ -0,0 +1,24 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const viewInPageNotifyFooter = style({
display: 'flex',
justifyContent: 'flex-end',
gap: '12px',
});
export const viewInPageNotifyFooterButton = style({
padding: '0px 6px',
borderRadius: '4px',
color: cssVarV2('text/primary'),
fontSize: cssVar('fontSm'),
lineHeight: '22px',
fontWeight: '500',
textAlign: 'center',
':hover': {
background: cssVarV2('layer/background/hoverOverlay'),
},
});