|
|
|
|
@ -70,36 +70,55 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
@@ -70,36 +70,55 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
if (window.location.pathname !== '/') { |
|
|
|
|
pushSecondaryPage(window.location.pathname + window.location.search + window.location.hash) |
|
|
|
|
const url = window.location.pathname + window.location.search + window.location.hash |
|
|
|
|
setSecondaryStack((prevStack) => { |
|
|
|
|
if (isCurrentPage(prevStack, url)) return prevStack |
|
|
|
|
|
|
|
|
|
const { newStack } = pushNewPageToStack( |
|
|
|
|
prevStack, |
|
|
|
|
url, |
|
|
|
|
maxStackSize, |
|
|
|
|
window.history.state?.index |
|
|
|
|
) |
|
|
|
|
return newStack |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const onPopState = (e: PopStateEvent) => { |
|
|
|
|
const state = e.state ?? { index: -1, url: '/' } |
|
|
|
|
setSecondaryStack((pre) => { |
|
|
|
|
const currentItem = pre[pre.length - 1] |
|
|
|
|
const currentIndex = currentItem ? currentItem.index : 0 |
|
|
|
|
const currentItem = pre[pre.length - 1] as TStackItem | undefined |
|
|
|
|
const currentIndex = currentItem?.index |
|
|
|
|
|
|
|
|
|
// Go forward
|
|
|
|
|
if (currentIndex === undefined || state.index > currentIndex) { |
|
|
|
|
const { newStack } = pushNewPageToStack(pre, state.url, maxStackSize) |
|
|
|
|
return newStack |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (state.index === currentIndex) { |
|
|
|
|
if (currentIndex !== 0) return pre |
|
|
|
|
|
|
|
|
|
window.history.replaceState(null, '', '/') |
|
|
|
|
return [] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Go back
|
|
|
|
|
if (state.index < currentIndex) { |
|
|
|
|
const newStack = pre.filter((item) => item.index <= state.index) |
|
|
|
|
const topItem = newStack[newStack.length - 1] |
|
|
|
|
// Load the component if it's not cached
|
|
|
|
|
if (topItem && !topItem.component) { |
|
|
|
|
topItem.component = findAndCreateComponent(topItem.url, state.index) |
|
|
|
|
} |
|
|
|
|
if (newStack.length === 0) { |
|
|
|
|
window.history.replaceState(null, '', '/') |
|
|
|
|
const newStack = pre.filter((item) => item.index <= state.index) |
|
|
|
|
const topItem = newStack[newStack.length - 1] as TStackItem | undefined |
|
|
|
|
if (!topItem) { |
|
|
|
|
// Create a new stack item if it's not exist (e.g. when the user refreshes the page, the stack will be empty)
|
|
|
|
|
const newComponent = findAndCreateComponent(state.url, state.index) |
|
|
|
|
if (newComponent) { |
|
|
|
|
newStack.push({ index: state.index, url: state.url, component: newComponent }) |
|
|
|
|
} |
|
|
|
|
return newStack |
|
|
|
|
} else if (!topItem.component) { |
|
|
|
|
// Load the component if it's not cached
|
|
|
|
|
topItem.component = findAndCreateComponent(topItem.url, state.index) |
|
|
|
|
} |
|
|
|
|
if (newStack.length === 0) { |
|
|
|
|
window.history.replaceState(null, '', '/') |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Go forward
|
|
|
|
|
const { newStack } = pushNewPageToStack(pre, state.url, maxStackSize) |
|
|
|
|
return newStack |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
@ -122,11 +141,11 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
@@ -122,11 +141,11 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const pushSecondaryPage = (url: string) => { |
|
|
|
|
const pushSecondaryPage = (url: string, index?: number) => { |
|
|
|
|
setSecondaryStack((prevStack) => { |
|
|
|
|
if (isCurrentPage(prevStack, url)) return prevStack |
|
|
|
|
|
|
|
|
|
const { newStack, newItem } = pushNewPageToStack(prevStack, url, maxStackSize) |
|
|
|
|
const { newStack, newItem } = pushNewPageToStack(prevStack, url, maxStackSize, index) |
|
|
|
|
if (newItem) { |
|
|
|
|
window.history.pushState({ index: newItem.index, url }, '', url) |
|
|
|
|
} |
|
|
|
|
@ -286,14 +305,19 @@ function findAndCreateComponent(url: string, index: number) {
@@ -286,14 +305,19 @@ function findAndCreateComponent(url: string, index: number) {
|
|
|
|
|
return null |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function pushNewPageToStack(stack: TStackItem[], url: string, maxStackSize = 5) { |
|
|
|
|
function pushNewPageToStack( |
|
|
|
|
stack: TStackItem[], |
|
|
|
|
url: string, |
|
|
|
|
maxStackSize = 5, |
|
|
|
|
specificIndex?: number |
|
|
|
|
) { |
|
|
|
|
const currentItem = stack[stack.length - 1] |
|
|
|
|
const currentIndex = currentItem ? currentItem.index + 1 : 0 |
|
|
|
|
const currentIndex = specificIndex ?? (currentItem ? currentItem.index + 1 : 0) |
|
|
|
|
|
|
|
|
|
const component = findAndCreateComponent(url, currentIndex) |
|
|
|
|
if (!component) return { newStack: stack, newItem: null } |
|
|
|
|
|
|
|
|
|
const newItem = { component, url, index: currentItem ? currentItem.index + 1 : 0 } |
|
|
|
|
const newItem = { component, url, index: currentIndex } |
|
|
|
|
const newStack = [...stack, newItem] |
|
|
|
|
const lastCachedIndex = newStack.findIndex((stack) => stack.component) |
|
|
|
|
// Clear the oldest cached component if there are too many cached components
|
|
|
|
|
|