mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-23 05:25:53 +08:00
feat(editor): add more open doc options to editor toolbar (#9588)
fix AF-2036, AF-2092
This commit is contained in:
+43
-35
@@ -13,7 +13,6 @@ import {
|
||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||
import {
|
||||
CaptionIcon,
|
||||
CenterPeekIcon,
|
||||
CopyIcon,
|
||||
EditIcon,
|
||||
ExpandFullSmallIcon,
|
||||
@@ -44,6 +43,8 @@ import {
|
||||
GenerateDocUrlProvider,
|
||||
type GenerateDocUrlService,
|
||||
type LinkEventType,
|
||||
OpenDocExtensionIdentifier,
|
||||
type OpenDocMode,
|
||||
type TelemetryEvent,
|
||||
TelemetryProvider,
|
||||
ThemeProvider,
|
||||
@@ -266,8 +267,8 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
||||
return bound.h / EMBED_CARD_HEIGHT[this.model.style];
|
||||
};
|
||||
|
||||
private readonly _open = () => {
|
||||
this._blockComponent?.open();
|
||||
private readonly _open = ({ openMode }: { openMode?: OpenDocMode } = {}) => {
|
||||
this._blockComponent?.open({ openMode });
|
||||
};
|
||||
|
||||
private readonly _openEditPopup = (e: MouseEvent) => {
|
||||
@@ -493,12 +494,6 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
||||
);
|
||||
}
|
||||
|
||||
get _openButtonDisabled() {
|
||||
return (
|
||||
isEmbedLinkedDocBlock(this.model) && this.model.pageId === this._doc.id
|
||||
);
|
||||
}
|
||||
|
||||
get _originalDocInfo(): AliasInfo | undefined {
|
||||
const model = this.model;
|
||||
const doc = isInternalEmbedModel(model)
|
||||
@@ -543,20 +538,46 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
||||
}
|
||||
|
||||
private _openMenuButton() {
|
||||
const buttons: MenuItem[] = [];
|
||||
const openDocConfig = this.std.get(OpenDocExtensionIdentifier);
|
||||
const buttons: MenuItem[] = openDocConfig.items
|
||||
.map(item => {
|
||||
if (
|
||||
item.type === 'open-in-center-peek' &&
|
||||
this._blockComponent &&
|
||||
!isPeekable(this._blockComponent)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
isEmbedLinkedDocBlock(this.model) ||
|
||||
isEmbedSyncedDocBlock(this.model)
|
||||
) {
|
||||
buttons.push({
|
||||
type: 'open-this-doc',
|
||||
label: 'Open this doc',
|
||||
icon: ExpandFullSmallIcon,
|
||||
action: this._open,
|
||||
disabled: this._openButtonDisabled,
|
||||
});
|
||||
} else if (this._canShowFullScreenButton) {
|
||||
if (
|
||||
!(
|
||||
isEmbedLinkedDocBlock(this.model) ||
|
||||
isEmbedSyncedDocBlock(this.model)
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
label: item.label,
|
||||
type: item.type,
|
||||
icon: item.icon,
|
||||
disabled:
|
||||
this.model.pageId === this._doc.id &&
|
||||
item.type === 'open-in-active-view',
|
||||
action: () => {
|
||||
if (item.type === 'open-in-center-peek') {
|
||||
this._peek();
|
||||
} else {
|
||||
this._open({ openMode: item.type });
|
||||
}
|
||||
},
|
||||
};
|
||||
})
|
||||
.filter(item => item !== null);
|
||||
|
||||
// todo: abstract this?
|
||||
if (this._canShowFullScreenButton) {
|
||||
buttons.push({
|
||||
type: 'open-this-doc',
|
||||
label: 'Open this doc',
|
||||
@@ -565,19 +586,6 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
||||
});
|
||||
}
|
||||
|
||||
// open in new tab
|
||||
|
||||
if (this._blockComponent && isPeekable(this._blockComponent)) {
|
||||
buttons.push({
|
||||
type: 'open-in-center-peek',
|
||||
label: 'Open in center peek',
|
||||
icon: CenterPeekIcon,
|
||||
action: () => this._peek(),
|
||||
});
|
||||
}
|
||||
|
||||
// open in split view
|
||||
|
||||
if (buttons.length === 0) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
OpenDocExtensionIdentifier,
|
||||
TelemetryProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { Bound, getCommonBoundWithRotation } from '@blocksuite/global/utils';
|
||||
import {
|
||||
ArrowDownBigBottomIcon,
|
||||
@@ -23,11 +26,13 @@ import {
|
||||
CopyIcon,
|
||||
DeleteIcon,
|
||||
DuplicateIcon,
|
||||
ExpandFullIcon,
|
||||
FrameIcon,
|
||||
GroupIcon,
|
||||
LinkedPageIcon,
|
||||
OpenInNewIcon,
|
||||
ResetIcon,
|
||||
SplitViewIcon,
|
||||
} from '@blocksuite/icons/lit';
|
||||
|
||||
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
|
||||
@@ -135,11 +140,12 @@ export const reorderGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
||||
};
|
||||
|
||||
// Open Group
|
||||
// TODO: construct this group dynamically
|
||||
export const openGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
||||
type: 'open',
|
||||
items: [
|
||||
{
|
||||
icon: OpenInNewIcon({ width: '20', height: '20' }),
|
||||
icon: ExpandFullIcon({ width: '20', height: '20' }),
|
||||
label: 'Open this doc',
|
||||
type: 'open',
|
||||
generate: ctx => {
|
||||
@@ -163,6 +169,62 @@ export const openGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
||||
disabled,
|
||||
};
|
||||
},
|
||||
when: ctx => {
|
||||
const openDocService = ctx.std.get(OpenDocExtensionIdentifier);
|
||||
return openDocService.isAllowed('open-in-active-view');
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: SplitViewIcon({ width: '20', height: '20' }),
|
||||
label: 'Open in split view',
|
||||
type: 'open-in-split-view',
|
||||
generate: ctx => {
|
||||
const linkedDocBlock = ctx.getLinkedDocBlock();
|
||||
|
||||
if (!linkedDocBlock) return;
|
||||
|
||||
return {
|
||||
action: () => {
|
||||
const blockComponent = ctx.firstBlockComponent;
|
||||
|
||||
if (!blockComponent) return;
|
||||
if (!('open' in blockComponent)) return;
|
||||
if (typeof blockComponent.open !== 'function') return;
|
||||
|
||||
blockComponent.open({ openMode: 'open-in-new-view' });
|
||||
},
|
||||
};
|
||||
},
|
||||
when: ctx => {
|
||||
const openDocService = ctx.std.get(OpenDocExtensionIdentifier);
|
||||
return openDocService.isAllowed('open-in-new-view');
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: OpenInNewIcon({ width: '20', height: '20' }),
|
||||
label: 'Open in new tab',
|
||||
type: 'open-in-new-tab',
|
||||
generate: ctx => {
|
||||
const linkedDocBlock = ctx.getLinkedDocBlock();
|
||||
|
||||
if (!linkedDocBlock) return;
|
||||
|
||||
return {
|
||||
action: () => {
|
||||
const blockComponent = ctx.firstBlockComponent;
|
||||
|
||||
if (!blockComponent) return;
|
||||
if (!('open' in blockComponent)) return;
|
||||
if (typeof blockComponent.open !== 'function') return;
|
||||
|
||||
blockComponent.open({ openMode: 'open-in-new-tab' });
|
||||
},
|
||||
};
|
||||
},
|
||||
when: ctx => {
|
||||
const openDocService = ctx.std.get(OpenDocExtensionIdentifier);
|
||||
return openDocService.isAllowed('open-in-new-tab');
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: CenterPeekIcon({ width: '20', height: '20' }),
|
||||
@@ -184,6 +246,10 @@ export const openGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
||||
},
|
||||
};
|
||||
},
|
||||
when: ctx => {
|
||||
const openDocService = ctx.std.get(OpenDocExtensionIdentifier);
|
||||
return openDocService.isAllowed('open-in-center-peek');
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -12,10 +12,8 @@ import {
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
CaptionIcon,
|
||||
CenterPeekIcon,
|
||||
CopyIcon,
|
||||
EditIcon,
|
||||
ExpandFullSmallIcon,
|
||||
MoreVerticalIcon,
|
||||
OpenIcon,
|
||||
PaletteIcon,
|
||||
@@ -48,6 +46,7 @@ import {
|
||||
GenerateDocUrlProvider,
|
||||
type GenerateDocUrlService,
|
||||
type LinkEventType,
|
||||
OpenDocExtensionIdentifier,
|
||||
type TelemetryEvent,
|
||||
TelemetryProvider,
|
||||
ThemeProvider,
|
||||
@@ -503,34 +502,42 @@ export class EmbedCardToolbar extends WidgetComponent<
|
||||
}
|
||||
|
||||
private _openMenuButton() {
|
||||
const buttons: MenuItem[] = [];
|
||||
|
||||
if (
|
||||
this.focusModel &&
|
||||
(isEmbedLinkedDocBlock(this.focusModel) ||
|
||||
isEmbedSyncedDocBlock(this.focusModel))
|
||||
) {
|
||||
buttons.push({
|
||||
type: 'open-this-doc',
|
||||
label: 'Open this doc',
|
||||
icon: ExpandFullSmallIcon,
|
||||
action: () => this.focusBlock?.open(),
|
||||
});
|
||||
}
|
||||
|
||||
// open in new tab
|
||||
|
||||
const openDocConfig = this.std.get(OpenDocExtensionIdentifier);
|
||||
const element = this.focusBlock;
|
||||
if (element && isPeekable(element)) {
|
||||
buttons.push({
|
||||
type: 'open-in-center-peek',
|
||||
label: 'Open in center peek',
|
||||
icon: CenterPeekIcon,
|
||||
action: () => peek(element),
|
||||
});
|
||||
}
|
||||
const buttons: MenuItem[] = openDocConfig.items
|
||||
.map(item => {
|
||||
if (
|
||||
item.type === 'open-in-center-peek' &&
|
||||
element &&
|
||||
!isPeekable(element)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// open in split view
|
||||
if (
|
||||
!(
|
||||
this.focusModel &&
|
||||
(isEmbedLinkedDocBlock(this.focusModel) ||
|
||||
isEmbedSyncedDocBlock(this.focusModel))
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
label: item.label,
|
||||
type: item.type,
|
||||
icon: item.icon,
|
||||
action: () => {
|
||||
if (item.type === 'open-in-center-peek') {
|
||||
element && peek(element);
|
||||
} else {
|
||||
this.focusBlock?.open({ openMode: item.type });
|
||||
}
|
||||
},
|
||||
};
|
||||
})
|
||||
.filter(item => item !== null);
|
||||
|
||||
if (buttons.length === 0) {
|
||||
return nothing;
|
||||
|
||||
Reference in New Issue
Block a user