mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
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;
|
|
}
|