mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(electron): track router history (#2336)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
This commit is contained in:
99
apps/web/src/atoms/history.ts
Normal file
99
apps/web/src/atoms/history.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { atom, useAtom, useSetAtom } from 'jotai';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
export type History = {
|
||||
stack: string[];
|
||||
current: number;
|
||||
skip: boolean;
|
||||
};
|
||||
|
||||
export const MAX_HISTORY = 50;
|
||||
|
||||
export const historyBaseAtom = atom<History>({
|
||||
stack: [],
|
||||
current: 0,
|
||||
skip: false,
|
||||
});
|
||||
|
||||
// fixme(himself65): don't use hooks, use atom lifecycle instead
|
||||
export function useTrackRouterHistoryEffect() {
|
||||
const setBase = useSetAtom(historyBaseAtom);
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
const callback = (url: string) => {
|
||||
setBase(prev => {
|
||||
console.log('push', url, prev.skip, prev.stack.length, prev.current);
|
||||
if (prev.skip) {
|
||||
return {
|
||||
stack: [...prev.stack],
|
||||
current: prev.current,
|
||||
skip: false,
|
||||
};
|
||||
} else {
|
||||
if (prev.current < prev.stack.length - 1) {
|
||||
const newStack = prev.stack.slice(0, prev.current);
|
||||
newStack.push(url);
|
||||
if (newStack.length > MAX_HISTORY) {
|
||||
newStack.shift();
|
||||
}
|
||||
return {
|
||||
stack: newStack,
|
||||
current: newStack.length - 1,
|
||||
skip: false,
|
||||
};
|
||||
} else {
|
||||
const newStack = [...prev.stack, url];
|
||||
if (newStack.length > MAX_HISTORY) {
|
||||
newStack.shift();
|
||||
}
|
||||
return {
|
||||
stack: newStack,
|
||||
current: newStack.length - 1,
|
||||
skip: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', callback);
|
||||
return () => {
|
||||
router.events.off('routeChangeComplete', callback);
|
||||
};
|
||||
}, [router.events, setBase]);
|
||||
}
|
||||
|
||||
export function useHistoryAtom() {
|
||||
const router = useRouter();
|
||||
const [base, setBase] = useAtom(historyBaseAtom);
|
||||
return [
|
||||
base,
|
||||
useCallback(
|
||||
(forward: boolean) => {
|
||||
setBase(prev => {
|
||||
if (forward) {
|
||||
const target = Math.min(prev.stack.length - 1, prev.current + 1);
|
||||
const url = prev.stack[target];
|
||||
void router.push(url);
|
||||
return {
|
||||
...prev,
|
||||
current: target,
|
||||
skip: true,
|
||||
};
|
||||
} else {
|
||||
const target = Math.max(0, prev.current - 1);
|
||||
const url = prev.stack[target];
|
||||
void router.push(url);
|
||||
return {
|
||||
...prev,
|
||||
current: target,
|
||||
skip: true,
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
[router, setBase]
|
||||
),
|
||||
] as const;
|
||||
}
|
||||
@@ -23,8 +23,9 @@ import type { Page } from '@blocksuite/store';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import type { ReactElement } from 'react';
|
||||
import type React from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
|
||||
import { useHistoryAtom } from '../../atoms/history';
|
||||
import type { AllWorkspace } from '../../shared';
|
||||
import FavoriteList from '../pure/workspace-slider-bar/favorite/favorite-list';
|
||||
import { WorkspaceSelector } from '../pure/workspace-slider-bar/WorkspaceSelector';
|
||||
@@ -115,10 +116,22 @@ export const RootAppSidebar = ({
|
||||
}, [sidebarOpen, setSidebarOpen]);
|
||||
|
||||
const clientUpdateAvailable = useAtomValue(updateAvailableAtom);
|
||||
const [history, setHistory] = useHistoryAtom();
|
||||
const router = useMemo(() => {
|
||||
return {
|
||||
forward: () => {
|
||||
setHistory(true);
|
||||
},
|
||||
back: () => {
|
||||
setHistory(false);
|
||||
},
|
||||
history,
|
||||
};
|
||||
}, [history, setHistory]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppSidebar>
|
||||
<AppSidebar router={router}>
|
||||
<SidebarContainer>
|
||||
<WorkspaceSelector
|
||||
currentWorkspace={currentWorkspace}
|
||||
|
||||
@@ -27,6 +27,7 @@ import type { FC, PropsWithChildren, ReactElement } from 'react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useMemo } from 'react';
|
||||
|
||||
import { openQuickSearchModalAtom, openWorkspacesModalAtom } from '../atoms';
|
||||
import { useTrackRouterHistoryEffect } from '../atoms/history';
|
||||
import {
|
||||
publicWorkspaceAtom,
|
||||
publicWorkspaceIdAtom,
|
||||
@@ -166,6 +167,7 @@ export const WorkspaceLayout: FC<PropsWithChildren> =
|
||||
// todo(himself65): this is a hack, we should use a better way to set the language
|
||||
setUpLanguage(i18n);
|
||||
}, [i18n]);
|
||||
useTrackRouterHistoryEffect();
|
||||
const currentWorkspaceId = useAtomValue(rootCurrentWorkspaceIdAtom);
|
||||
const jotaiWorkspaces = useAtomValue(rootWorkspacesMetadataAtom);
|
||||
const meta = useMemo(
|
||||
|
||||
Reference in New Issue
Block a user