feat: allow opening new tab for some navigation buttons (#7764)
fix AF-1010
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
|
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||||
import { ArrowDownSmallIcon } from '@blocksuite/icons/rc';
|
import { ArrowDownSmallIcon } from '@blocksuite/icons/rc';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { To } from 'react-router-dom';
|
import type { To } from 'react-router-dom';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ export const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
|
|||||||
MenuItem.displayName = 'MenuItem';
|
MenuItem.displayName = 'MenuItem';
|
||||||
|
|
||||||
export const MenuLinkItem = React.forwardRef<HTMLDivElement, MenuLinkItemProps>(
|
export const MenuLinkItem = React.forwardRef<HTMLDivElement, MenuLinkItemProps>(
|
||||||
({ to, linkComponent: LinkComponent = Link, ...props }, ref) => {
|
({ to, linkComponent: LinkComponent = WorkbenchLink, ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<LinkComponent to={to} className={styles.linkItemRoot}>
|
<LinkComponent to={to} className={styles.linkItemRoot}>
|
||||||
{/* The <a> element rendered by Link does not generate display box due to `display: contents` style */}
|
{/* The <a> element rendered by Link does not generate display box due to `display: contents` style */}
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
|
||||||
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
|
||||||
import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
|
import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
|
||||||
import { WorkspaceSubPath } from '@affine/core/shared';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { DocsService, initEmptyPage, useService } from '@toeverything/infra';
|
import { DocsService, initEmptyPage, useService } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
|
||||||
import type { DocCollection } from '../../../shared';
|
import type { DocCollection } from '../../../shared';
|
||||||
|
|
||||||
export const usePageHelper = (docCollection: DocCollection) => {
|
export const usePageHelper = (docCollection: DocCollection) => {
|
||||||
const { openPage, jumpToSubPath } = useNavigateHelper();
|
const workbench = useService(WorkbenchService).workbench;
|
||||||
const { createDoc } = useDocCollectionHelper(docCollection);
|
const { createDoc } = useDocCollectionHelper(docCollection);
|
||||||
const { setDocMeta } = useDocMetaHelper(docCollection);
|
|
||||||
const docRecordList = useService(DocsService).list;
|
const docRecordList = useService(DocsService).list;
|
||||||
|
|
||||||
const isPreferredEdgeless = useCallback(
|
const isPreferredEdgeless = useCallback(
|
||||||
@@ -22,18 +18,21 @@ export const usePageHelper = (docCollection: DocCollection) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const createPageAndOpen = useCallback(
|
const createPageAndOpen = useCallback(
|
||||||
(mode?: 'page' | 'edgeless', open?: boolean) => {
|
(mode?: 'page' | 'edgeless', open?: boolean | 'new-tab') => {
|
||||||
const page = createDoc();
|
const page = createDoc();
|
||||||
initEmptyPage(page);
|
initEmptyPage(page);
|
||||||
docRecordList.doc$(page.id).value?.setMode(mode || 'page');
|
docRecordList.doc$(page.id).value?.setMode(mode || 'page');
|
||||||
if (open !== false) openPage(docCollection.id, page.id);
|
if (open !== false)
|
||||||
|
workbench.openDoc(page.id, {
|
||||||
|
at: open === 'new-tab' ? 'new-tab' : 'active',
|
||||||
|
});
|
||||||
return page;
|
return page;
|
||||||
},
|
},
|
||||||
[docCollection.id, createDoc, openPage, docRecordList]
|
[createDoc, docRecordList, workbench]
|
||||||
);
|
);
|
||||||
|
|
||||||
const createEdgelessAndOpen = useCallback(
|
const createEdgelessAndOpen = useCallback(
|
||||||
(open?: boolean) => {
|
(open?: boolean | 'new-tab') => {
|
||||||
return createPageAndOpen('edgeless', open);
|
return createPageAndOpen('edgeless', open);
|
||||||
},
|
},
|
||||||
[createPageAndOpen]
|
[createPageAndOpen]
|
||||||
@@ -59,7 +58,7 @@ export const usePageHelper = (docCollection: DocCollection) => {
|
|||||||
}.`
|
}.`
|
||||||
);
|
);
|
||||||
if (options.isWorkspaceFile) {
|
if (options.isWorkspaceFile) {
|
||||||
jumpToSubPath(docCollection.id, WorkspaceSubPath.ALL);
|
workbench.openAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +66,7 @@ export const usePageHelper = (docCollection: DocCollection) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pageId = pageIds[0];
|
const pageId = pageIds[0];
|
||||||
openPage(docCollection.id, pageId);
|
workbench.openDoc(pageId);
|
||||||
};
|
};
|
||||||
showImportModal({
|
showImportModal({
|
||||||
collection: docCollection,
|
collection: docCollection,
|
||||||
@@ -78,47 +77,20 @@ export const usePageHelper = (docCollection: DocCollection) => {
|
|||||||
});
|
});
|
||||||
return await promise;
|
return await promise;
|
||||||
},
|
},
|
||||||
[docCollection, openPage, jumpToSubPath]
|
[docCollection, workbench]
|
||||||
);
|
|
||||||
|
|
||||||
const createLinkedPageAndOpen = useAsyncCallback(
|
|
||||||
async (pageId: string) => {
|
|
||||||
const page = createPageAndOpen();
|
|
||||||
page.load();
|
|
||||||
const parentPage = docCollection.getDoc(pageId);
|
|
||||||
if (parentPage) {
|
|
||||||
parentPage.load();
|
|
||||||
const text = parentPage.Text.fromDelta([
|
|
||||||
{
|
|
||||||
insert: ' ',
|
|
||||||
attributes: {
|
|
||||||
reference: {
|
|
||||||
type: 'LinkedPage',
|
|
||||||
pageId: page.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const [frame] = parentPage.getBlockByFlavour('affine:note');
|
|
||||||
frame && parentPage.addBlock('affine:paragraph', { text }, frame.id);
|
|
||||||
setDocMeta(page.id, {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[docCollection, createPageAndOpen, setDocMeta]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
return {
|
||||||
isPreferredEdgeless,
|
isPreferredEdgeless,
|
||||||
createPage: createPageAndOpen,
|
createPage: (open?: boolean | 'new-tab') =>
|
||||||
|
createPageAndOpen('page', open),
|
||||||
createEdgeless: createEdgelessAndOpen,
|
createEdgeless: createEdgelessAndOpen,
|
||||||
importFile: importFileAndOpen,
|
importFile: importFileAndOpen,
|
||||||
createLinkedPage: createLinkedPageAndOpen,
|
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
isPreferredEdgeless,
|
isPreferredEdgeless,
|
||||||
createEdgelessAndOpen,
|
createEdgelessAndOpen,
|
||||||
createLinkedPageAndOpen,
|
|
||||||
createPageAndOpen,
|
createPageAndOpen,
|
||||||
importFileAndOpen,
|
importFileAndOpen,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { BlockCard } from '@affine/component/card/block-card';
|
|||||||
import { track } from '@affine/core/mixpanel';
|
import { track } from '@affine/core/mixpanel';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons/rc';
|
import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { MouseEvent, PropsWithChildren } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { menuContent } from './new-page-button.css';
|
import { menuContent } from './new-page-button.css';
|
||||||
|
|
||||||
type NewPageButtonProps = {
|
type NewPageButtonProps = {
|
||||||
createNewPage: () => void;
|
createNewPage: (e?: MouseEvent) => void;
|
||||||
createNewEdgeless: () => void;
|
createNewEdgeless: (e?: MouseEvent) => void;
|
||||||
importFile?: () => void;
|
importFile?: () => void;
|
||||||
size?: 'small' | 'default';
|
size?: 'small' | 'default';
|
||||||
};
|
};
|
||||||
@@ -67,19 +67,26 @@ export const NewPageButton = ({
|
|||||||
}: PropsWithChildren<NewPageButtonProps>) => {
|
}: PropsWithChildren<NewPageButtonProps>) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const handleCreateNewPage = useCallback(() => {
|
const handleCreateNewPage: NewPageButtonProps['createNewPage'] = useCallback(
|
||||||
createNewPage();
|
e => {
|
||||||
setOpen(false);
|
createNewPage(e);
|
||||||
track.allDocs.header.actions.createDoc();
|
setOpen(false);
|
||||||
}, [createNewPage]);
|
track.allDocs.header.actions.createDoc();
|
||||||
|
},
|
||||||
|
[createNewPage]
|
||||||
|
);
|
||||||
|
|
||||||
const handleCreateNewEdgeless = useCallback(() => {
|
const handleCreateNewEdgeless: NewPageButtonProps['createNewEdgeless'] =
|
||||||
createNewEdgeless();
|
useCallback(
|
||||||
setOpen(false);
|
e => {
|
||||||
track.allDocs.header.actions.createDoc({
|
createNewEdgeless(e);
|
||||||
mode: 'edgeless',
|
setOpen(false);
|
||||||
});
|
track.allDocs.header.actions.createDoc({
|
||||||
}, [createNewEdgeless]);
|
mode: 'edgeless',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[createNewEdgeless]
|
||||||
|
);
|
||||||
|
|
||||||
const handleImportFile = useCallback(() => {
|
const handleImportFile = useCallback(() => {
|
||||||
importFile?.();
|
importFile?.();
|
||||||
|
|||||||
@@ -65,8 +65,13 @@ export const PageListHeader = () => {
|
|||||||
<PageListNewPageButton
|
<PageListNewPageButton
|
||||||
size="small"
|
size="small"
|
||||||
testId="new-page-button-trigger"
|
testId="new-page-button-trigger"
|
||||||
onCreateEdgeless={createEdgeless}
|
onCreateEdgeless={e =>
|
||||||
onCreatePage={createPage}
|
// todo: abstract this for ctrl check
|
||||||
|
createEdgeless(e?.metaKey || e?.ctrlKey ? 'new-tab' : true)
|
||||||
|
}
|
||||||
|
onCreatePage={e =>
|
||||||
|
createPage(e?.metaKey || e?.ctrlKey ? 'new-tab' : true)
|
||||||
|
}
|
||||||
onImportFile={onImportFile}
|
onImportFile={onImportFile}
|
||||||
>
|
>
|
||||||
<div className={styles.buttonText}>{t['New Page']()}</div>
|
<div className={styles.buttonText}>{t['New Page']()}</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { PropsWithChildren } from 'react';
|
import type { MouseEvent, PropsWithChildren } from 'react';
|
||||||
|
|
||||||
import { NewPageButton } from '../components/new-page-button';
|
import { NewPageButton } from '../components/new-page-button';
|
||||||
import * as styles from './page-list-new-page-button.css';
|
import * as styles from './page-list-new-page-button.css';
|
||||||
@@ -15,9 +15,9 @@ export const PageListNewPageButton = ({
|
|||||||
className?: string;
|
className?: string;
|
||||||
size?: 'small' | 'default';
|
size?: 'small' | 'default';
|
||||||
testId?: string;
|
testId?: string;
|
||||||
onCreatePage: () => void;
|
onCreatePage: (e?: MouseEvent) => void;
|
||||||
onCreateEdgeless: () => void;
|
onCreateEdgeless: (e?: MouseEvent) => void;
|
||||||
onImportFile?: () => void;
|
onImportFile?: (e?: MouseEvent) => void;
|
||||||
}>) => {
|
}>) => {
|
||||||
return (
|
return (
|
||||||
<div className={className} data-testid={testId}>
|
<div className={className} data-testid={testId}>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
} from '@affine/core/modules/explorer';
|
} from '@affine/core/modules/explorer';
|
||||||
import { ExplorerTags } from '@affine/core/modules/explorer/views/sections/tags';
|
import { ExplorerTags } from '@affine/core/modules/explorer/views/sections/tags';
|
||||||
import { CMDKQuickSearchService } from '@affine/core/modules/quicksearch/services/cmdk';
|
import { CMDKQuickSearchService } from '@affine/core/modules/quicksearch/services/cmdk';
|
||||||
import { pathGenerator } from '@affine/core/shared';
|
|
||||||
import { apis, events } from '@affine/electron-api';
|
import { apis, events } from '@affine/electron-api';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { AllDocsIcon, SettingsIcon } from '@blocksuite/icons/rc';
|
import { AllDocsIcon, SettingsIcon } from '@blocksuite/icons/rc';
|
||||||
@@ -69,7 +68,6 @@ export type RootAppSidebarProps = {
|
|||||||
*/
|
*/
|
||||||
export const RootAppSidebar = (): ReactElement => {
|
export const RootAppSidebar = (): ReactElement => {
|
||||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
const currentWorkspace = useService(WorkspaceService).workspace;
|
||||||
const currentWorkspaceId = currentWorkspace.id;
|
|
||||||
const { appSettings } = useAppSettingHelper();
|
const { appSettings } = useAppSettingHelper();
|
||||||
const docCollection = currentWorkspace.docCollection;
|
const docCollection = currentWorkspace.docCollection;
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
@@ -88,15 +86,13 @@ export const RootAppSidebar = (): ReactElement => {
|
|||||||
|
|
||||||
const onClickNewPage = useAsyncCallback(
|
const onClickNewPage = useAsyncCallback(
|
||||||
async (e?: MouseEvent) => {
|
async (e?: MouseEvent) => {
|
||||||
const page = pageHelper.createPage('page', false);
|
const page = pageHelper.createPage(
|
||||||
|
e?.ctrlKey || e?.metaKey ? 'new-tab' : true
|
||||||
|
);
|
||||||
page.load();
|
page.load();
|
||||||
track.$.navigationPanel.$.createDoc();
|
track.$.navigationPanel.$.createDoc();
|
||||||
|
|
||||||
workbench.openDoc(page.id, {
|
|
||||||
at: e?.ctrlKey || e?.metaKey ? 'new-tab' : 'active',
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[pageHelper, workbench]
|
[pageHelper]
|
||||||
);
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (environment.isDesktop) {
|
if (environment.isDesktop) {
|
||||||
@@ -145,11 +141,7 @@ export const RootAppSidebar = (): ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<AddPageButton onClick={onClickNewPage} />
|
<AddPageButton onClick={onClickNewPage} />
|
||||||
</div>
|
</div>
|
||||||
<MenuLinkItem
|
<MenuLinkItem icon={<AllDocsIcon />} active={allPageActive} to={'/all'}>
|
||||||
icon={<AllDocsIcon />}
|
|
||||||
active={allPageActive}
|
|
||||||
to={pathGenerator.all(currentWorkspaceId)}
|
|
||||||
>
|
|
||||||
<span data-testid="all-pages">
|
<span data-testid="all-pages">
|
||||||
{t['com.affine.workspaceSubPath.all']()}
|
{t['com.affine.workspaceSubPath.all']()}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { DocCollection } from '@affine/core/shared';
|
|||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { TodayIcon, TomorrowIcon, YesterdayIcon } from '@blocksuite/icons/rc';
|
import { TodayIcon, TomorrowIcon, YesterdayIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
|
import { type MouseEvent, useCallback } from 'react';
|
||||||
|
|
||||||
import { MenuItem } from '../app-sidebar';
|
import { MenuItem } from '../app-sidebar';
|
||||||
|
|
||||||
@@ -26,6 +27,13 @@ export const AppSidebarJournalButton = ({
|
|||||||
location.pathname.split('/')[1]
|
location.pathname.split('/')[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleOpenToday = useCallback(
|
||||||
|
(e: MouseEvent) => {
|
||||||
|
openToday(e.ctrlKey || e.metaKey);
|
||||||
|
},
|
||||||
|
[openToday]
|
||||||
|
);
|
||||||
|
|
||||||
const Icon =
|
const Icon =
|
||||||
isJournal && journalDate
|
isJournal && journalDate
|
||||||
? journalDate.isBefore(new Date(), 'day')
|
? journalDate.isBefore(new Date(), 'day')
|
||||||
@@ -39,7 +47,7 @@ export const AppSidebarJournalButton = ({
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
data-testid="slider-bar-journals-button"
|
data-testid="slider-bar-journals-button"
|
||||||
active={isJournal}
|
active={isJournal}
|
||||||
onClick={openToday}
|
onClick={handleOpenToday}
|
||||||
icon={<Icon />}
|
icon={<Icon />}
|
||||||
>
|
>
|
||||||
{t['com.affine.journal.app-sidebar-title']()}
|
{t['com.affine.journal.app-sidebar-title']()}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
useConfirmModal,
|
useConfirmModal,
|
||||||
useDropTarget,
|
useDropTarget,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import {
|
import {
|
||||||
@@ -62,7 +61,6 @@ export const TrashButton = () => {
|
|||||||
ref={dropTargetRef}
|
ref={dropTargetRef}
|
||||||
icon={<AnimatedDeleteIcon closed={draggedOver} />}
|
icon={<AnimatedDeleteIcon closed={draggedOver} />}
|
||||||
active={trashActive || draggedOver}
|
active={trashActive || draggedOver}
|
||||||
linkComponent={WorkbenchLink}
|
|
||||||
to={'/trash'}
|
to={'/trash'}
|
||||||
>
|
>
|
||||||
<span data-testid="trash-page">
|
<span data-testid="trash-page">
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { i18nTime } from '@affine/i18n';
|
import { i18nTime } from '@affine/i18n';
|
||||||
import { initEmptyPage } from '@toeverything/infra';
|
import { initEmptyPage, useService } from '@toeverything/infra';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { WorkbenchService } from '../modules/workbench';
|
||||||
import type { DocCollection } from '../shared';
|
import type { DocCollection } from '../shared';
|
||||||
import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter';
|
import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter';
|
||||||
import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
|
import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
|
||||||
import { useNavigateHelper } from './use-navigate-helper';
|
|
||||||
|
|
||||||
type MaybeDate = Date | string | number;
|
type MaybeDate = Date | string | number;
|
||||||
export const JOURNAL_DATE_FORMAT = 'YYYY-MM-DD';
|
export const JOURNAL_DATE_FORMAT = 'YYYY-MM-DD';
|
||||||
@@ -153,26 +153,32 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
|||||||
|
|
||||||
// split useJournalRouteHelper since it requires a <Route /> context, which may not work in lit
|
// split useJournalRouteHelper since it requires a <Route /> context, which may not work in lit
|
||||||
export const useJournalRouteHelper = (docCollection: DocCollection) => {
|
export const useJournalRouteHelper = (docCollection: DocCollection) => {
|
||||||
const navigateHelper = useNavigateHelper();
|
|
||||||
const { getJournalByDate } = useJournalHelper(docCollection);
|
const { getJournalByDate } = useJournalHelper(docCollection);
|
||||||
|
const workbench = useService(WorkbenchService).workbench;
|
||||||
/**
|
/**
|
||||||
* open journal by date, create one if not exist
|
* open journal by date, create one if not exist
|
||||||
*/
|
*/
|
||||||
const openJournal = useCallback(
|
const openJournal = useCallback(
|
||||||
(maybeDate: MaybeDate) => {
|
(maybeDate: MaybeDate, newTab?: boolean) => {
|
||||||
const page = getJournalByDate(maybeDate);
|
const page = getJournalByDate(maybeDate);
|
||||||
navigateHelper.openPage(docCollection.id, page.id);
|
workbench.openDoc(page.id, {
|
||||||
|
at: newTab ? 'new-tab' : 'active',
|
||||||
|
});
|
||||||
|
return page.id;
|
||||||
},
|
},
|
||||||
[getJournalByDate, navigateHelper, docCollection.id]
|
[getJournalByDate, workbench]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* open today's journal
|
* open today's journal
|
||||||
*/
|
*/
|
||||||
const openToday = useCallback(() => {
|
const openToday = useCallback(
|
||||||
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
(newTab?: boolean) => {
|
||||||
openJournal(date);
|
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
||||||
}, [openJournal]);
|
return openJournal(date, newTab);
|
||||||
|
},
|
||||||
|
[openJournal]
|
||||||
|
);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import type { AffineDNDData } from '@affine/core/types/dnd';
|
|||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { PlusIcon } from '@blocksuite/icons/rc';
|
import { PlusIcon } from '@blocksuite/icons/rc';
|
||||||
import { DocsService, useLiveData, useServices } from '@toeverything/infra';
|
import { DocsService, useLiveData, useServices } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { type MouseEventHandler, useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { ExplorerService } from '../../../services/explorer';
|
import { ExplorerService } from '../../../services/explorer';
|
||||||
import { CollapsibleSection } from '../../layouts/collapsible-section';
|
import { CollapsibleSection } from '../../layouts/collapsible-section';
|
||||||
@@ -88,21 +88,26 @@ export const ExplorerFavorites = () => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCreateNewFavoriteDoc = useCallback(() => {
|
const handleCreateNewFavoriteDoc: MouseEventHandler = useCallback(
|
||||||
const newDoc = docsService.createDoc();
|
e => {
|
||||||
favoriteService.favoriteList.add(
|
const newDoc = docsService.createDoc();
|
||||||
'doc',
|
favoriteService.favoriteList.add(
|
||||||
newDoc.id,
|
'doc',
|
||||||
favoriteService.favoriteList.indexAt('before')
|
newDoc.id,
|
||||||
);
|
favoriteService.favoriteList.indexAt('before')
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
);
|
||||||
explorerSection.setCollapsed(false);
|
workbenchService.workbench.openDoc(newDoc.id, {
|
||||||
}, [
|
at: e.ctrlKey || e.metaKey ? 'new-tab' : 'active',
|
||||||
docsService,
|
});
|
||||||
explorerSection,
|
explorerSection.setCollapsed(false);
|
||||||
favoriteService.favoriteList,
|
},
|
||||||
workbenchService.workbench,
|
[
|
||||||
]);
|
docsService,
|
||||||
|
explorerSection,
|
||||||
|
favoriteService.favoriteList,
|
||||||
|
workbenchService.workbench,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
const handleOnChildrenDrop = useCallback(
|
const handleOnChildrenDrop = useCallback(
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -59,8 +59,12 @@ export const AllPageHeader = ({
|
|||||||
styles.headerCreateNewButton,
|
styles.headerCreateNewButton,
|
||||||
!showCreateNew && styles.headerCreateNewButtonHidden
|
!showCreateNew && styles.headerCreateNewButtonHidden
|
||||||
)}
|
)}
|
||||||
onCreateEdgeless={createEdgeless}
|
onCreateEdgeless={e =>
|
||||||
onCreatePage={createPage}
|
createEdgeless(e?.metaKey || e?.ctrlKey ? 'new-tab' : true)
|
||||||
|
}
|
||||||
|
onCreatePage={e =>
|
||||||
|
createPage(e?.metaKey || e?.ctrlKey ? 'new-tab' : true)
|
||||||
|
}
|
||||||
onImportFile={onImportFile}
|
onImportFile={onImportFile}
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ const createAndPinCollection = async (
|
|||||||
await getBlockSuiteEditorTitle(page).click();
|
await getBlockSuiteEditorTitle(page).click();
|
||||||
await getBlockSuiteEditorTitle(page).fill('test page');
|
await getBlockSuiteEditorTitle(page).fill('test page');
|
||||||
|
|
||||||
|
// fixme: remove this timeout. looks like an issue with useBindWorkbenchToBrowserRouter?
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await page.getByTestId('all-pages').click();
|
await page.getByTestId('all-pages').click();
|
||||||
|
|
||||||
const cell = page.getByTestId('page-list-item-title').getByText('test page');
|
const cell = page.getByTestId('page-list-item-title').getByText('test page');
|
||||||
@@ -67,7 +70,7 @@ test('Show collections items in sidebar', async ({ page }) => {
|
|||||||
const collections = page.getByTestId('explorer-collections');
|
const collections = page.getByTestId('explorer-collections');
|
||||||
await collections.getByTestId('category-divider-collapse-button').click();
|
await collections.getByTestId('category-divider-collapse-button').click();
|
||||||
const items = collections.locator('[data-testid^="explorer-collection-"]');
|
const items = collections.locator('[data-testid^="explorer-collection-"]');
|
||||||
expect(await items.count()).toBe(1);
|
await expect(items).toHaveCount(1);
|
||||||
const first = items.first();
|
const first = items.first();
|
||||||
expect(await first.textContent()).toBe('test collection');
|
expect(await first.textContent()).toBe('test collection');
|
||||||
await first.getByTestId('explorer-collapsed-button').click();
|
await first.getByTestId('explorer-collapsed-button').click();
|
||||||
@@ -87,7 +90,7 @@ test('Show collections items in sidebar', async ({ page }) => {
|
|||||||
const deleteCollection = page.getByText('Delete');
|
const deleteCollection = page.getByText('Delete');
|
||||||
await deleteCollection.click();
|
await deleteCollection.click();
|
||||||
await page.waitForTimeout(50);
|
await page.waitForTimeout(50);
|
||||||
expect(await items.count()).toBe(0);
|
await expect(items).toHaveCount(0);
|
||||||
await createAndPinCollection(page);
|
await createAndPinCollection(page);
|
||||||
expect(await items.count()).toBe(1);
|
expect(await items.count()).toBe(1);
|
||||||
await clickSideBarAllPageButton(page);
|
await clickSideBarAllPageButton(page);
|
||||||
|
|||||||
Reference in New Issue
Block a user