mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-25 09:02:04 +03:00
fix: improve navigate (#3420)
This commit is contained in:
parent
115f46a4fa
commit
b47fbde479
12
.eslintrc.js
12
.eslintrc.js
@ -22,10 +22,15 @@ const createPattern = packageName => [
|
|||||||
allowTypeImports: false,
|
allowTypeImports: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
group: ['@blocksuite/store'],
|
group: ['@blocksuite /store'],
|
||||||
message: "Import from '@blocksuite/global/utils'",
|
message: "Import from '@blocksuite/global/utils'",
|
||||||
importNames: ['assertExists', 'assertEquals'],
|
importNames: ['assertExists', 'assertEquals'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
group: ['react-router-dom'],
|
||||||
|
message: 'Use `useNavigateHelper` instead',
|
||||||
|
importNames: ['useNavigate'],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const allPackages = [
|
const allPackages = [
|
||||||
@ -144,6 +149,11 @@ const config = {
|
|||||||
message: "Import from '@blocksuite/global/utils'",
|
message: "Import from '@blocksuite/global/utils'",
|
||||||
importNames: ['assertExists', 'assertEquals'],
|
importNames: ['assertExists', 'assertEquals'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
group: ['react-router-dom'],
|
||||||
|
message: 'Use `useNavigateHelper` instead',
|
||||||
|
importNames: ['useNavigate'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { atomWithStorage, createJSONStorage } from 'jotai/utils';
|
import { atomWithStorage, createJSONStorage } from 'jotai/utils';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { router } from '../router';
|
import { router } from '../router';
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import {
|
import {
|
||||||
DeleteTemporarilyIcon,
|
DeleteTemporarilyIcon,
|
||||||
@ -9,23 +10,27 @@ import type { FC, SVGProps } from 'react';
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { openSettingModalAtom } from '../../../atoms';
|
import { openSettingModalAtom } from '../../../atoms';
|
||||||
import { pathGenerator } from '../../../shared';
|
|
||||||
|
|
||||||
export const useSwitchToConfig = (
|
export type Config =
|
||||||
workspaceId: string
|
| {
|
||||||
): {
|
title: string;
|
||||||
title: string;
|
icon: FC<SVGProps<SVGSVGElement>>;
|
||||||
href?: string;
|
subPath: WorkspaceSubPath;
|
||||||
onClick?: () => void;
|
}
|
||||||
icon: FC<SVGProps<SVGSVGElement>>;
|
| {
|
||||||
}[] => {
|
title: string;
|
||||||
|
icon: FC<SVGProps<SVGSVGElement>>;
|
||||||
|
onClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSwitchToConfig = (workspaceId: string): Config[] => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const [, setOpenSettingModalAtom] = useAtom(openSettingModalAtom);
|
const [, setOpenSettingModalAtom] = useAtom(openSettingModalAtom);
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
title: t['All pages'](),
|
title: t['All pages'](),
|
||||||
href: pathGenerator.all(workspaceId),
|
subPath: WorkspaceSubPath.ALL,
|
||||||
icon: FolderIcon,
|
icon: FolderIcon,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -41,7 +46,7 @@ export const useSwitchToConfig = (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t['Trash'](),
|
title: t['Trash'](),
|
||||||
href: pathGenerator.trash(workspaceId),
|
subPath: WorkspaceSubPath.TRASH,
|
||||||
icon: DeleteTemporarilyIcon,
|
icon: DeleteTemporarilyIcon,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2,8 +2,7 @@ import { Modal, ModalWrapper } from '@affine/component';
|
|||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { Command } from 'cmdk';
|
import { Command } from 'cmdk';
|
||||||
import { startTransition } from 'react';
|
import { startTransition } from 'react';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
|
|
||||||
import type { AllWorkspace } from '../../../shared';
|
import type { AllWorkspace } from '../../../shared';
|
||||||
import { Footer } from './footer';
|
import { Footer } from './footer';
|
||||||
@ -37,15 +36,7 @@ export const QuickSearchModal: React.FC<QuickSearchModalProps> = ({
|
|||||||
_setQuery(query);
|
_setQuery(query);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
const location = useLocation();
|
|
||||||
const isPublicWorkspace = useMemo(
|
|
||||||
() => location.pathname.startsWith('/public-workspace'),
|
|
||||||
[location]
|
|
||||||
);
|
|
||||||
const [showCreatePage, setShowCreatePage] = useState(true);
|
const [showCreatePage, setShowCreatePage] = useState(true);
|
||||||
const isPublicAndNoQuery = useCallback(() => {
|
|
||||||
return isPublicWorkspace && query.length === 0;
|
|
||||||
}, [isPublicWorkspace, query.length]);
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}, [setOpen]);
|
}, [setOpen]);
|
||||||
@ -88,7 +79,7 @@ export const QuickSearchModal: React.FC<QuickSearchModalProps> = ({
|
|||||||
width={608}
|
width={608}
|
||||||
style={{
|
style={{
|
||||||
maxHeight: '80vh',
|
maxHeight: '80vh',
|
||||||
minHeight: isPublicAndNoQuery() ? '72px' : '412px',
|
minHeight: '412px',
|
||||||
top: '80px',
|
top: '80px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}}
|
}}
|
||||||
@ -134,13 +125,9 @@ export const QuickSearchModal: React.FC<QuickSearchModalProps> = ({
|
|||||||
: 'Ctrl + K'}
|
: 'Ctrl + K'}
|
||||||
</StyledShortcut>
|
</StyledShortcut>
|
||||||
</StyledModalHeader>
|
</StyledModalHeader>
|
||||||
<StyledModalDivider
|
<StyledModalDivider />
|
||||||
style={{ display: isPublicAndNoQuery() ? 'none' : '' }}
|
|
||||||
/>
|
|
||||||
<Command.List>
|
<Command.List>
|
||||||
<StyledContent
|
<StyledContent>
|
||||||
style={{ display: isPublicAndNoQuery() ? 'none' : '' }}
|
|
||||||
>
|
|
||||||
<Results
|
<Results
|
||||||
query={query}
|
query={query}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
@ -148,7 +135,7 @@ export const QuickSearchModal: React.FC<QuickSearchModalProps> = ({
|
|||||||
setShowCreatePage={setShowCreatePage}
|
setShowCreatePage={setShowCreatePage}
|
||||||
/>
|
/>
|
||||||
</StyledContent>
|
</StyledContent>
|
||||||
{isPublicWorkspace ? null : showCreatePage ? (
|
{showCreatePage ? (
|
||||||
<>
|
<>
|
||||||
<StyledModalDivider />
|
<StyledModalDivider />
|
||||||
<StyledModalFooter>
|
<StyledModalFooter>
|
||||||
|
@ -7,8 +7,6 @@ import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suit
|
|||||||
import { Command } from 'cmdk';
|
import { Command } from 'cmdk';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import type { Dispatch, FC, SetStateAction } from 'react';
|
import type { Dispatch, FC, SetStateAction } from 'react';
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { recentPageSettingsAtom } from '../../../atoms';
|
import { recentPageSettingsAtom } from '../../../atoms';
|
||||||
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
||||||
@ -32,12 +30,11 @@ export const Results: FC<ResultsProps> = ({
|
|||||||
useBlockSuiteWorkspaceHelper(blockSuiteWorkspace);
|
useBlockSuiteWorkspaceHelper(blockSuiteWorkspace);
|
||||||
const pageList = useBlockSuitePageMeta(blockSuiteWorkspace);
|
const pageList = useBlockSuitePageMeta(blockSuiteWorkspace);
|
||||||
assertExists(blockSuiteWorkspace.id);
|
assertExists(blockSuiteWorkspace.id);
|
||||||
const List = useSwitchToConfig(workspace.id);
|
const list = useSwitchToConfig(workspace.id);
|
||||||
|
|
||||||
const recentPageSetting = useAtomValue(recentPageSettingsAtom);
|
const recentPageSetting = useAtomValue(recentPageSettingsAtom);
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const navigate = useNavigate();
|
const { jumpToPage, jumpToSubPath } = useNavigateHelper();
|
||||||
const { jumpToPage } = useNavigateHelper();
|
|
||||||
const results = blockSuiteWorkspace.search({ query });
|
const results = blockSuiteWorkspace.search({ query });
|
||||||
|
|
||||||
// remove `space:` prefix
|
// remove `space:` prefix
|
||||||
@ -55,10 +52,7 @@ export const Results: FC<ResultsProps> = ({
|
|||||||
return page.trash !== true;
|
return page.trash !== true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
setShowCreatePage(resultsPageMeta.length === 0);
|
||||||
setShowCreatePage(!resultsPageMeta.length);
|
|
||||||
//Determine whether to display the ‘+ New page’
|
|
||||||
}, [resultsPageMeta.length, setShowCreatePage]);
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -90,15 +84,20 @@ export const Results: FC<ResultsProps> = ({
|
|||||||
</Command.Group>
|
</Command.Group>
|
||||||
)}
|
)}
|
||||||
<Command.Group heading={t['Jump to']()}>
|
<Command.Group heading={t['Jump to']()}>
|
||||||
{List.map(link => {
|
{list.map(link => {
|
||||||
return (
|
return (
|
||||||
<Command.Item
|
<Command.Item
|
||||||
key={link.title}
|
key={link.title}
|
||||||
value={link.title}
|
value={link.title}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
onClose();
|
onClose();
|
||||||
link.href && navigate(link.href);
|
if ('subPath' in link) {
|
||||||
link.onClick?.();
|
jumpToSubPath(blockSuiteWorkspace.id, link.subPath);
|
||||||
|
} else if ('onClick' in link) {
|
||||||
|
link.onClick();
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid link');
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StyledListItem>
|
<StyledListItem>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { WorkspaceSubPath } from '@affine/env/workspace';
|
import type { WorkspaceSubPath } from '@affine/env/workspace';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
export enum RouteLogic {
|
export enum RouteLogic {
|
||||||
|
@ -12,7 +12,7 @@ import { useAtomValue } from 'jotai';
|
|||||||
import { useAtom } from 'jotai/react';
|
import { useAtom } from 'jotai/react';
|
||||||
import { type ReactElement, useCallback, useEffect } from 'react';
|
import { type ReactElement, useCallback, useEffect } from 'react';
|
||||||
import type { LoaderFunction } from 'react-router-dom';
|
import type { LoaderFunction } from 'react-router-dom';
|
||||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { getUIAdapter } from '../../adapters/workspace';
|
import { getUIAdapter } from '../../adapters/workspace';
|
||||||
import { useCurrentWorkspace } from '../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../hooks/current/use-current-workspace';
|
||||||
@ -71,7 +71,7 @@ const DetailPageImpl = (): ReactElement => {
|
|||||||
export const DetailPage = (): ReactElement => {
|
export const DetailPage = (): ReactElement => {
|
||||||
const { workspaceId, pageId } = useParams();
|
const { workspaceId, pageId } = useParams();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const { jumpTo404 } = useNavigateHelper();
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const [currentPageId, setCurrentPageId] = useAtom(currentPageIdAtom);
|
const [currentPageId, setCurrentPageId] = useAtom(currentPageIdAtom);
|
||||||
const page = currentPageId
|
const page = currentPageId
|
||||||
@ -91,7 +91,7 @@ export const DetailPage = (): ReactElement => {
|
|||||||
const page =
|
const page =
|
||||||
currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
|
currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
navigate('/404');
|
jumpTo404();
|
||||||
} else {
|
} else {
|
||||||
// fixme: cleanup jumpOnce in the right time
|
// fixme: cleanup jumpOnce in the right time
|
||||||
if (page.meta.jumpOnce) {
|
if (page.meta.jumpOnce) {
|
||||||
@ -106,8 +106,8 @@ export const DetailPage = (): ReactElement => {
|
|||||||
currentPageId,
|
currentPageId,
|
||||||
currentWorkspace.blockSuiteWorkspace,
|
currentWorkspace.blockSuiteWorkspace,
|
||||||
currentWorkspace.id,
|
currentWorkspace.id,
|
||||||
|
jumpTo404,
|
||||||
location.pathname,
|
location.pathname,
|
||||||
navigate,
|
|
||||||
pageId,
|
pageId,
|
||||||
setCurrentPageId,
|
setCurrentPageId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
|
Loading…
Reference in New Issue
Block a user