feat(core): set doc mode and primary doc mode separately (#8359)

https://github.com/user-attachments/assets/98c282f2-4c53-475f-bf10-936a626c2630
This commit is contained in:
JimmFly
2024-10-17 13:48:45 +00:00
parent 7dae5c5dd5
commit bfb8d582ed
15 changed files with 192 additions and 90 deletions

View File

@@ -11,4 +11,9 @@ export const BUILT_IN_CUSTOM_PROPERTY_TYPE = [
type: 'tags', type: 'tags',
index: 'a0000001', index: 'a0000001',
}, },
{
id: 'docPrimaryMode',
type: 'docPrimaryMode',
show: 'always-hide',
},
] as DocCustomPropertyInfo[]; ] as DocCustomPropertyInfo[];

View File

@@ -65,6 +65,7 @@ export const hide = style({
export const propertyNameContainer = style({ export const propertyNameContainer = style({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
justifyContent: 'center',
position: 'relative', position: 'relative',
borderRadius: 4, borderRadius: 4,
fontSize: cssVar('fontSm'), fontSize: cssVar('fontSm'),

View File

@@ -1,4 +1,4 @@
import { toast } from '@affine/component'; import { notify } from '@affine/component';
import { import {
Menu, Menu,
MenuItem, MenuItem,
@@ -74,6 +74,7 @@ export const PageHeaderMenuButton = ({
editorService.editor.doc.meta$.map(meta => meta.trash) editorService.editor.doc.meta$.map(meta => meta.trash)
); );
const currentMode = useLiveData(editorService.editor.mode$); const currentMode = useLiveData(editorService.editor.mode$);
const primaryMode = useLiveData(editorService.editor.doc.primaryMode$);
const workbench = useService(WorkbenchService).workbench; const workbench = useService(WorkbenchService).workbench;
@@ -148,16 +149,22 @@ export const PageHeaderMenuButton = ({
}, [rename]); }, [rename]);
const handleSwitchMode = useCallback(() => { const handleSwitchMode = useCallback(() => {
editorService.editor.toggleMode(); const mode = primaryMode === 'page' ? 'edgeless' : 'page';
editorService.editor.doc.setPrimaryMode(mode);
track.$.header.docOptions.switchPageMode({ track.$.header.docOptions.switchPageMode({
mode: currentMode === 'page' ? 'edgeless' : 'page', mode,
}); });
toast( notify.success({
currentMode === 'page' title:
? t['com.affine.toastMessage.edgelessMode']() primaryMode === 'page'
: t['com.affine.toastMessage.pageMode']() ? t['com.affine.toastMessage.defaultMode.edgeless.title']()
); : t['com.affine.toastMessage.defaultMode.page.title'](),
}, [currentMode, editorService, t]); message:
primaryMode === 'page'
? t['com.affine.toastMessage.defaultMode.edgeless.message']()
: t['com.affine.toastMessage.defaultMode.page.message'](),
});
}, [primaryMode, editorService, t]);
const handleMenuOpenChange = useCallback((open: boolean) => { const handleMenuOpenChange = useCallback((open: boolean) => {
if (open) { if (open) {
@@ -264,14 +271,13 @@ export const PageHeaderMenuButton = ({
</MenuItem> </MenuItem>
)} )}
<MenuItem <MenuItem
prefixIcon={currentMode === 'page' ? <EdgelessIcon /> : <PageIcon />} prefixIcon={primaryMode === 'page' ? <EdgelessIcon /> : <PageIcon />}
data-testid="editor-option-menu-edgeless" data-testid="editor-option-menu-edgeless"
onSelect={handleSwitchMode} onSelect={handleSwitchMode}
> >
{t['Convert to ']()} {primaryMode === 'page'
{currentMode === 'page' ? t['com.affine.editorDefaultMode.edgeless']()
? t['com.affine.pageMode.edgeless']() : t['com.affine.editorDefaultMode.page']()}
: t['com.affine.pageMode.page']()}
</MenuItem> </MenuItem>
<MenuItem <MenuItem
data-testid="editor-option-menu-favorite" data-testid="editor-option-menu-favorite"

View File

@@ -1,4 +1,4 @@
import { RadioGroup, type RadioItem, toast, Tooltip } from '@affine/component'; import { RadioGroup, type RadioItem, Tooltip } from '@affine/component';
import { registerAffineCommand } from '@affine/core/commands'; import { registerAffineCommand } from '@affine/core/commands';
import { EditorService } from '@affine/core/modules/editor'; import { EditorService } from '@affine/core/modules/editor';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
@@ -41,19 +41,15 @@ export const EditorModeSwitch = () => {
if (currentMode === 'page' || isSharedMode || trash) return; if (currentMode === 'page' || isSharedMode || trash) return;
editor.setMode('page'); editor.setMode('page');
editor.setSelector(undefined); editor.setSelector(undefined);
editor.doc.setPrimaryMode('page');
toast(t['com.affine.toastMessage.pageMode']());
track.$.header.actions.switchPageMode({ mode: 'page' }); track.$.header.actions.switchPageMode({ mode: 'page' });
}, [currentMode, editor, isSharedMode, t, trash]); }, [currentMode, editor, isSharedMode, trash]);
const toggleEdgeless = useCallback(() => { const toggleEdgeless = useCallback(() => {
if (currentMode === 'edgeless' || isSharedMode || trash) return; if (currentMode === 'edgeless' || isSharedMode || trash) return;
editor.setMode('edgeless'); editor.setMode('edgeless');
editor.setSelector(undefined); editor.setSelector(undefined);
editor.doc.setPrimaryMode('edgeless');
toast(t['com.affine.toastMessage.edgelessMode']());
track.$.header.actions.switchPageMode({ mode: 'edgeless' }); track.$.header.actions.switchPageMode({ mode: 'edgeless' });
}, [currentMode, editor, isSharedMode, t, trash]); }, [currentMode, editor, isSharedMode, trash]);
const onModeChange = useCallback( const onModeChange = useCallback(
(mode: DocMode) => { (mode: DocMode) => {

View File

@@ -3,6 +3,7 @@ import {
CheckBoxCheckLinearIcon, CheckBoxCheckLinearIcon,
CreatedEditedIcon, CreatedEditedIcon,
DateTimeIcon, DateTimeIcon,
FileIcon,
NumberIcon, NumberIcon,
TagIcon, TagIcon,
TextIcon, TextIcon,
@@ -11,6 +12,7 @@ import {
import { CheckboxValue } from './checkbox'; import { CheckboxValue } from './checkbox';
import { CreatedByValue, UpdatedByValue } from './created-updated-by'; import { CreatedByValue, UpdatedByValue } from './created-updated-by';
import { DateValue } from './date'; import { DateValue } from './date';
import { DocPrimaryModeValue } from './doc-primary-mode';
import { NumberValue } from './number'; import { NumberValue } from './number';
import { TagsValue } from './tags'; import { TagsValue } from './tags';
import { TextValue } from './text'; import { TextValue } from './text';
@@ -54,6 +56,11 @@ export const DocPropertyTypes = {
uniqueId: 'tags', uniqueId: 'tags',
renameable: false, renameable: false,
}, },
docPrimaryMode: {
icon: FileIcon,
value: DocPrimaryModeValue,
name: 'com.affine.page-properties.property.docPrimaryMode',
},
} as Record< } as Record<
string, string,
{ {

View File

@@ -0,0 +1,58 @@
import {
notify,
PropertyValue,
RadioGroup,
type RadioItem,
} from '@affine/component';
import { useI18n } from '@affine/i18n';
import type { DocMode } from '@blocksuite/affine/blocks';
import { DocService, useLiveData, useService } from '@toeverything/infra';
import { useCallback, useMemo } from 'react';
export const DocPrimaryModeValue = () => {
const t = useI18n();
const doc = useService(DocService).doc;
const primaryMode = useLiveData(doc.primaryMode$);
const DocModeItems = useMemo<RadioItem[]>(
() => [
{
value: 'page' as DocMode,
label: t['Page'](),
},
{
value: 'edgeless' as DocMode,
label: t['Edgeless'](),
},
],
[t]
);
const handleChange = useCallback(
(mode: DocMode) => {
doc.setPrimaryMode(mode);
notify.success({
title:
mode === 'page'
? t['com.affine.toastMessage.defaultMode.page.title']()
: t['com.affine.toastMessage.defaultMode.edgeless.title'](),
message:
mode === 'page'
? t['com.affine.toastMessage.defaultMode.page.message']()
: t['com.affine.toastMessage.defaultMode.edgeless.message'](),
});
},
[doc, t]
);
return (
<PropertyValue>
<RadioGroup
width={194}
value={primaryMode}
onChange={handleChange}
items={DocModeItems}
/>
</PropertyValue>
);
};

View File

@@ -1,4 +1,4 @@
import { IconButton, toast } from '@affine/component'; import { IconButton, notify } from '@affine/component';
import { import {
MenuSeparator, MenuSeparator,
MobileMenu, MobileMenu,
@@ -39,21 +39,29 @@ export const PageHeaderMenuButton = () => {
const isInTrash = useLiveData( const isInTrash = useLiveData(
editorService.editor.doc.meta$.map(meta => meta.trash) editorService.editor.doc.meta$.map(meta => meta.trash)
); );
const currentMode = useLiveData(editorService.editor.mode$); const primaryMode = useLiveData(editorService.editor.doc.primaryMode$);
const { favorite, toggleFavorite } = useFavorite(docId); const { favorite, toggleFavorite } = useFavorite(docId);
const handleSwitchMode = useCallback(() => { const handleSwitchMode = useCallback(() => {
editorService.editor.toggleMode(); const mode = primaryMode === 'page' ? 'edgeless' : 'page';
// TODO(@JimmFly): remove setMode when there has view mode switch
editorService.editor.setMode(mode);
editorService.editor.doc.setPrimaryMode(mode);
track.$.header.docOptions.switchPageMode({ track.$.header.docOptions.switchPageMode({
mode: currentMode === 'page' ? 'edgeless' : 'page', mode,
}); });
toast( notify.success({
currentMode === 'page' title:
? t['com.affine.toastMessage.edgelessMode']() primaryMode === 'page'
: t['com.affine.toastMessage.pageMode']() ? t['com.affine.toastMessage.defaultMode.edgeless.title']()
); : t['com.affine.toastMessage.defaultMode.page.title'](),
}, [currentMode, editorService, t]); message:
primaryMode === 'page'
? t['com.affine.toastMessage.defaultMode.edgeless.message']()
: t['com.affine.toastMessage.defaultMode.page.message'](),
});
}, [primaryMode, editorService, t]);
const handleMenuOpenChange = useCallback((open: boolean) => { const handleMenuOpenChange = useCallback((open: boolean) => {
if (open) { if (open) {
@@ -75,14 +83,13 @@ export const PageHeaderMenuButton = () => {
const EditMenu = ( const EditMenu = (
<> <>
<MobileMenuItem <MobileMenuItem
prefixIcon={currentMode === 'page' ? <EdgelessIcon /> : <PageIcon />} prefixIcon={primaryMode === 'page' ? <EdgelessIcon /> : <PageIcon />}
data-testid="editor-option-menu-mode-switch" data-testid="editor-option-menu-mode-switch"
onSelect={handleSwitchMode} onSelect={handleSwitchMode}
> >
{t['Convert to ']()} {primaryMode === 'page'
{currentMode === 'page' ? t['com.affine.editorDefaultMode.edgeless']()
? t['com.affine.pageMode.edgeless']() : t['com.affine.editorDefaultMode.page']()}
: t['com.affine.pageMode.page']()}
</MobileMenuItem> </MobileMenuItem>
<MobileMenuItem <MobileMenuItem
data-testid="editor-option-menu-favorite" data-testid="editor-option-menu-favorite"

View File

@@ -1,12 +1,12 @@
{ {
"ar": 87, "ar": 86,
"ca": 6, "ca": 6,
"da": 7, "da": 7,
"de": 32, "de": 32,
"en": 100, "en": 100,
"es-AR": 16, "es-AR": 15,
"es-CL": 18, "es-CL": 18,
"es": 16, "es": 15,
"fr": 77, "fr": 77,
"hi": 2, "hi": 2,
"it": 1, "it": 1,
@@ -14,9 +14,9 @@
"ko": 92, "ko": 92,
"pl": 0, "pl": 0,
"pt-BR": 99, "pt-BR": 99,
"ru": 85, "ru": 84,
"sv-SE": 5, "sv-SE": 5,
"ur": 3, "ur": 3,
"zh-Hans": 100, "zh-Hans": 100,
"zh-Hant": 100 "zh-Hant": 99
} }

View File

@@ -92,6 +92,7 @@
"Successfully deleted": "Successfully deleted", "Successfully deleted": "Successfully deleted",
"Successfully joined!": "Successfully joined!", "Successfully joined!": "Successfully joined!",
"Switch": "Switch", "Switch": "Switch",
"switchView": "Switch view",
"Sync": "Sync", "Sync": "Sync",
"Synced with AFFiNE Cloud": "Synced with AFFiNE Cloud", "Synced with AFFiNE Cloud": "Synced with AFFiNE Cloud",
"Tags": "Tags", "Tags": "Tags",
@@ -425,6 +426,8 @@
"com.affine.editCollectionName.createTips": "Collection is a smart folder where you can manually add docs or automatically add docs through rules.", "com.affine.editCollectionName.createTips": "Collection is a smart folder where you can manually add docs or automatically add docs through rules.",
"com.affine.editCollectionName.name": "Name", "com.affine.editCollectionName.name": "Name",
"com.affine.editCollectionName.name.placeholder": "Collection name", "com.affine.editCollectionName.name.placeholder": "Collection name",
"com.affine.editorDefaultMode.edgeless": "Default to Edgeless mode",
"com.affine.editorDefaultMode.page": "Default to Page mode",
"com.affine.empty.collection-detail.action.add-doc": "Add docs", "com.affine.empty.collection-detail.action.add-doc": "Add docs",
"com.affine.empty.collection-detail.action.add-rule": "Add rules", "com.affine.empty.collection-detail.action.add-rule": "Add rules",
"com.affine.empty.collection-detail.description": "Collection is a smart folder where you can manually add docs or automatically add docs through rules.", "com.affine.empty.collection-detail.description": "Collection is a smart folder where you can manually add docs or automatically add docs through rules.",
@@ -527,7 +530,7 @@
"com.affine.keyboardShortcuts.elbowedConnector": "Elbowed connector", "com.affine.keyboardShortcuts.elbowedConnector": "Elbowed connector",
"com.affine.keyboardShortcuts.expandOrCollapseSidebar": "Expand/collapse sidebar", "com.affine.keyboardShortcuts.expandOrCollapseSidebar": "Expand/collapse sidebar",
"com.affine.keyboardShortcuts.goBack": "Go back", "com.affine.keyboardShortcuts.goBack": "Go back",
"com.affine.keyboardShortcuts.goForward": "Go Forward", "com.affine.keyboardShortcuts.goForward": "Go forward",
"com.affine.keyboardShortcuts.group": "Group", "com.affine.keyboardShortcuts.group": "Group",
"com.affine.keyboardShortcuts.groupDatabase": "Group as database", "com.affine.keyboardShortcuts.groupDatabase": "Group as database",
"com.affine.keyboardShortcuts.hand": "Hand", "com.affine.keyboardShortcuts.hand": "Hand",
@@ -551,7 +554,7 @@
"com.affine.keyboardShortcuts.straightConnector": "Straight connector", "com.affine.keyboardShortcuts.straightConnector": "Straight connector",
"com.affine.keyboardShortcuts.strikethrough": "Strikethrough", "com.affine.keyboardShortcuts.strikethrough": "Strikethrough",
"com.affine.keyboardShortcuts.subtitle": "Check keyboard shortcuts quickly", "com.affine.keyboardShortcuts.subtitle": "Check keyboard shortcuts quickly",
"com.affine.keyboardShortcuts.switch": "Switch", "com.affine.keyboardShortcuts.switch": "Switch view",
"com.affine.keyboardShortcuts.text": "Text", "com.affine.keyboardShortcuts.text": "Text",
"com.affine.keyboardShortcuts.title": "Keyboard shortcuts", "com.affine.keyboardShortcuts.title": "Keyboard shortcuts",
"com.affine.keyboardShortcuts.unGroup": "Ungroup", "com.affine.keyboardShortcuts.unGroup": "Ungroup",
@@ -647,6 +650,7 @@
"com.affine.page-properties.property.required": "Required", "com.affine.page-properties.property.required": "Required",
"com.affine.page-properties.property.show-in-view": "Show in view", "com.affine.page-properties.property.show-in-view": "Show in view",
"com.affine.page-properties.property.tags": "Tags", "com.affine.page-properties.property.tags": "Tags",
"com.affine.page-properties.property.docPrimaryMode": "Doc mode",
"com.affine.page-properties.property.text": "Text", "com.affine.page-properties.property.text": "Text",
"com.affine.page-properties.property.updatedBy": "Last edited by", "com.affine.page-properties.property.updatedBy": "Last edited by",
"com.affine.propertySidebar.property-list.section": "Properties", "com.affine.propertySidebar.property-list.section": "Properties",
@@ -1213,6 +1217,10 @@
"com.affine.toastMessage.edgelessMode": "Edgeless mode", "com.affine.toastMessage.edgelessMode": "Edgeless mode",
"com.affine.toastMessage.movedTrash": "Moved to trash", "com.affine.toastMessage.movedTrash": "Moved to trash",
"com.affine.toastMessage.pageMode": "Page Mode", "com.affine.toastMessage.pageMode": "Page Mode",
"com.affine.toastMessage.defaultMode.page.title": "Default mode has changed",
"com.affine.toastMessage.defaultMode.page.message": "The default mode for this document has been changed to Page mode",
"com.affine.toastMessage.defaultMode.edgeless.title": "Default mode has changed",
"com.affine.toastMessage.defaultMode.edgeless.message": "The default mode for this document has been changed to Edgeless mode",
"com.affine.toastMessage.permanentlyDeleted": "Permanently deleted", "com.affine.toastMessage.permanentlyDeleted": "Permanently deleted",
"com.affine.toastMessage.removedFavorites": "Removed from favourites", "com.affine.toastMessage.removedFavorites": "Removed from favourites",
"com.affine.toastMessage.rename": "Successfully renamed", "com.affine.toastMessage.rename": "Successfully renamed",

View File

@@ -682,7 +682,6 @@
"com.affine.editCollectionName.name": "이름", "com.affine.editCollectionName.name": "이름",
"com.affine.editCollectionName.name.placeholder": "컬렉션 이름", "com.affine.editCollectionName.name.placeholder": "컬렉션 이름",
"com.affine.editor.reference-not-found": "연결된 페이지를 찾을 수 없음", "com.affine.editor.reference-not-found": "연결된 페이지를 찾을 수 없음",
"com.affine.editorModeSwitch.tooltip": "전환",
"com.affine.empty.collection-detail.action.add-doc": "문서 추가", "com.affine.empty.collection-detail.action.add-doc": "문서 추가",
"com.affine.empty.collection-detail.action.add-rule": "규칙 추가", "com.affine.empty.collection-detail.action.add-rule": "규칙 추가",
"com.affine.empty.collection-detail.description": "컬렉션은 페이지를 수동으로 추가하거나 규칙을 통해 자동으로 페이지를 추가할 수 있는 스마트 폴더입니다.", "com.affine.empty.collection-detail.description": "컬렉션은 페이지를 수동으로 추가하거나 규칙을 통해 자동으로 페이지를 추가할 수 있는 스마트 폴더입니다.",

View File

@@ -92,6 +92,7 @@
"Successfully deleted": "成功删除。", "Successfully deleted": "成功删除。",
"Successfully joined!": "加入成功!", "Successfully joined!": "加入成功!",
"Switch": "切换", "Switch": "切换",
"switchView": "切换视图",
"Sync": "同步", "Sync": "同步",
"Synced with AFFiNE Cloud": "AFFiNE Cloud 同步完成", "Synced with AFFiNE Cloud": "AFFiNE Cloud 同步完成",
"Tags": "标签", "Tags": "标签",
@@ -438,6 +439,9 @@
"com.affine.empty.docs.trash-description": "已删除的文档将显示在此处。", "com.affine.empty.docs.trash-description": "已删除的文档将显示在此处。",
"com.affine.empty.tags.description": "为您的文档创建一个新标签。", "com.affine.empty.tags.description": "为您的文档创建一个新标签。",
"com.affine.empty.tags.title": "标签管理", "com.affine.empty.tags.title": "标签管理",
"com.affine.editorDefaultMode.edgeless": "默认为无界模式",
"com.affine.editorDefaultMode.page": "默认为文档模式",
"com.affine.editor.reference-not-found": "未找到已链接的文档",
"com.affine.emptyDesc": "这里还没有文档", "com.affine.emptyDesc": "这里还没有文档",
"com.affine.enableAffineCloudModal.button.cancel": "取消", "com.affine.enableAffineCloudModal.button.cancel": "取消",
"com.affine.error.hide-error": "隐藏错误详情", "com.affine.error.hide-error": "隐藏错误详情",
@@ -551,7 +555,7 @@
"com.affine.keyboardShortcuts.straightConnector": "直线连接器快捷键", "com.affine.keyboardShortcuts.straightConnector": "直线连接器快捷键",
"com.affine.keyboardShortcuts.strikethrough": "删除线", "com.affine.keyboardShortcuts.strikethrough": "删除线",
"com.affine.keyboardShortcuts.subtitle": "快速查看快捷键", "com.affine.keyboardShortcuts.subtitle": "快速查看快捷键",
"com.affine.keyboardShortcuts.switch": "切换快捷键", "com.affine.keyboardShortcuts.switch": "切换视图快捷键",
"com.affine.keyboardShortcuts.text": "文本", "com.affine.keyboardShortcuts.text": "文本",
"com.affine.keyboardShortcuts.title": "键盘快捷键", "com.affine.keyboardShortcuts.title": "键盘快捷键",
"com.affine.keyboardShortcuts.unGroup": "取消分组", "com.affine.keyboardShortcuts.unGroup": "取消分组",
@@ -642,6 +646,7 @@
"com.affine.page-properties.property.required": "必选", "com.affine.page-properties.property.required": "必选",
"com.affine.page-properties.property.show-in-view": "在视图中显示", "com.affine.page-properties.property.show-in-view": "在视图中显示",
"com.affine.page-properties.property.tags": "标签", "com.affine.page-properties.property.tags": "标签",
"com.affine.page-properties.property.docPrimaryMode": "文档模式",
"com.affine.page-properties.property.text": "文本", "com.affine.page-properties.property.text": "文本",
"com.affine.page-properties.property.updatedBy": "最后编辑者", "com.affine.page-properties.property.updatedBy": "最后编辑者",
"com.affine.page-properties.settings.title": "自定义属性", "com.affine.page-properties.settings.title": "自定义属性",
@@ -1206,6 +1211,10 @@
"com.affine.toastMessage.rename": "更名成功", "com.affine.toastMessage.rename": "更名成功",
"com.affine.toastMessage.restored": "{{title}} 已恢复", "com.affine.toastMessage.restored": "{{title}} 已恢复",
"com.affine.toastMessage.successfullyDeleted": "删除成功", "com.affine.toastMessage.successfullyDeleted": "删除成功",
"com.affine.toastMessage.defaultMode.page.title": "默认模式已更改",
"com.affine.toastMessage.defaultMode.page.message": "该文档的默认模式已更改为页面模式",
"com.affine.toastMessage.defaultMode.edgeless.title": "默认模式已更改",
"com.affine.toastMessage.defaultMode.edgeless.message": "该文档的默认模式已更改为无界模式",
"com.affine.today": "今天", "com.affine.today": "今天",
"com.affine.tomorrow": "明日", "com.affine.tomorrow": "明日",
"com.affine.top-tip.mobile": "在移动设备上仅限于查看。", "com.affine.top-tip.mobile": "在移动设备上仅限于查看。",

View File

@@ -8,56 +8,20 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
import { import {
clickNewPageButton, clickNewPageButton,
clickPageMoreActions, clickPageMoreActions,
getBlockSuiteEditorTitle,
waitForAllPagesLoad,
waitForEditorLoad, waitForEditorLoad,
} from '@affine-test/kit/utils/page-logic'; } from '@affine-test/kit/utils/page-logic';
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
import { expect } from '@playwright/test'; import { expect } from '@playwright/test';
test('Switch to edgeless by switch edgeless item', async ({ page }) => { test('Switch to edgeless by switch edgeless item', async ({ page }) => {
async function getCount(): Promise<number> {
return page.evaluate(() => {
// @ts-expect-error
return globalThis.__toastCount;
});
}
await openHomePage(page); await openHomePage(page);
await waitForEditorLoad(page); await waitForEditorLoad(page);
await clickNewPageButton(page); await clickNewPageButton(page);
const btn = page.getByTestId('switch-edgeless-mode-button'); const btn = page.getByTestId('switch-edgeless-mode-button');
await page.evaluate(() => { await btn.click({ delay: 100 });
// @ts-expect-error await ensureInEdgelessMode(page);
globalThis.__toastCount = 0;
window.addEventListener('affine-toast:emit', () => {
// @ts-expect-error
globalThis.__toastCount++;
});
});
await btn.click();
await page.waitForTimeout(100);
{
const count = await getCount();
expect(count).toBe(1);
}
const edgeless = page.locator('affine-edgeless-root');
await expect(edgeless).toBeVisible();
const editorWrapperPadding = await page
.locator('.editor-wrapper.edgeless-mode')
.evaluate(element => {
return window.getComputedStyle(element).getPropertyValue('padding');
});
expect(editorWrapperPadding).toBe('0px');
{
const count = await getCount();
expect(count).toBe(1);
}
await btn.click();
await btn.click();
await btn.click();
await page.waitForTimeout(100);
{
const count = await getCount();
expect(count).toBe(1);
}
}); });
test('Quick Switch Doc Mode, Doc Mode should stable', async ({ page }) => { test('Quick Switch Doc Mode, Doc Mode should stable', async ({ page }) => {
@@ -94,13 +58,26 @@ test('Quick Switch Doc Mode, Doc Mode should stable', async ({ page }) => {
expect(await getPageMode(page)).toBe('page'); expect(await getPageMode(page)).toBe('page');
}); });
test('Convert to edgeless by editor header items', async ({ page }) => { test('default to edgeless by editor header items', async ({ page }) => {
await openHomePage(page); await openHomePage(page);
await waitForEditorLoad(page); await waitForEditorLoad(page);
await clickNewPageButton(page); await clickNewPageButton(page, 'this is a new page');
const title = getBlockSuiteEditorTitle(page);
expect(await title.textContent()).toBe('this is a new page');
await clickPageMoreActions(page); await clickPageMoreActions(page);
const menusEdgelessItem = page.getByTestId('editor-option-menu-edgeless'); const menusEdgelessItem = page.getByTestId('editor-option-menu-edgeless');
await menusEdgelessItem.click({ delay: 100 }); await menusEdgelessItem.click({ delay: 100 });
await clickSideBarAllPageButton(page);
await waitForAllPagesLoad(page);
const docItem = page.locator(
`[data-testid="page-list-item"]:has-text("this is a new page")`
);
expect(docItem).not.toBeUndefined();
await docItem.click();
await waitForEditorLoad(page);
const edgeless = page.locator('affine-edgeless-root'); const edgeless = page.locator('affine-edgeless-root');
await expect(edgeless).toBeVisible(); await expect(edgeless).toBeVisible();
}); });

View File

@@ -22,6 +22,7 @@ import {
openWorkspaceProperties, openWorkspaceProperties,
removeSelectedTag, removeSelectedTag,
searchAndCreateTag, searchAndCreateTag,
togglePropertyListVisibility,
} from '@affine-test/kit/utils/properties'; } from '@affine-test/kit/utils/properties';
import { expect } from '@playwright/test'; import { expect } from '@playwright/test';
@@ -117,8 +118,9 @@ test('property table reordering', async ({ page }) => {
'bottom' 'bottom'
); );
// new order should be (Tags), Number, Date, Checkbox, Text // new order should be Doc mode, (Tags), Number, Date, Checkbox, Text
for (const [index, property] of [ for (const [index, property] of [
'Doc mode',
'Tags', 'Tags',
'Number', 'Number',
'Date', 'Date',
@@ -157,6 +159,7 @@ test('page info show more will show all properties', async ({ page }) => {
await page.click('[data-testid="property-collapsible-button"]'); await page.click('[data-testid="property-collapsible-button"]');
for (const [index, property] of [ for (const [index, property] of [
'Doc mode',
'Tags', 'Tags',
'Text', 'Text',
'Number', 'Number',
@@ -179,6 +182,7 @@ test('change page properties visibility', async ({ page }) => {
await addCustomProperty(page, page, 'number'); await addCustomProperty(page, page, 'number');
await addCustomProperty(page, page, 'date'); await addCustomProperty(page, page, 'date');
await addCustomProperty(page, page, 'checkbox'); await addCustomProperty(page, page, 'checkbox');
await togglePropertyListVisibility(page);
// add some number to number property // add some number to number property
await clickPropertyValue(page, 'Number'); await clickPropertyValue(page, 'Number');

View File

@@ -18,7 +18,7 @@ test('switch to page mode', async ({ page }) => {
await page.click('[data-testid="detail-page-header-more-button"]'); await page.click('[data-testid="detail-page-header-more-button"]');
await expect(page.getByRole('dialog')).toBeVisible(); await expect(page.getByRole('dialog')).toBeVisible();
await page.getByRole('menuitem', { name: 'convert to page' }).click(); await page.getByRole('menuitem', { name: 'Default to Page mode' }).click();
await expect(page.locator('.doc-title-container')).toBeVisible(); await expect(page.locator('.doc-title-container')).toBeVisible();
}); });

View File

@@ -93,11 +93,36 @@ export const clickAddPropertyButton = async (root: Locator | Page) => {
.click(); .click();
}; };
export const ensureAddPropertyButtonVisible = async (
page: Page,
root: Locator | Page
) => {
if (
await root
.getByRole('button', {
name: 'Add property',
})
.isVisible()
) {
return;
}
await togglePropertyListVisibility(page);
await page.waitForTimeout(500);
await expect(
root.getByRole('button', { name: 'Add property' })
).toBeVisible();
};
export const togglePropertyListVisibility = async (page: Page) => {
await page.getByTestId('property-collapsible-button').click();
};
export const addCustomProperty = async ( export const addCustomProperty = async (
page: Page, page: Page,
root: Locator | Page, root: Locator | Page,
type: string type: string
) => { ) => {
ensureAddPropertyButtonVisible(page, root);
await clickAddPropertyButton(root); await clickAddPropertyButton(root);
await page await page
.locator( .locator(