mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-09 20:29:17 +02:00
Improve drawer navigation
This commit is contained in:
parent
0f1e677459
commit
7b03925054
5
.changeset/cold-snakes-turn.md
Normal file
5
.changeset/cold-snakes-turn.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": patch
|
||||
---
|
||||
|
||||
Improve drawer navigation
|
@ -1,3 +1,4 @@
|
||||
import { PropsWithChildren, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
ButtonGroup,
|
||||
Drawer,
|
||||
@ -9,13 +10,13 @@ import {
|
||||
DrawerProps,
|
||||
IconButton,
|
||||
} from "@chakra-ui/react";
|
||||
import { PropsWithChildren, createContext, useCallback, useContext, useMemo, useState } from "react";
|
||||
import { RouteObject, RouterProvider, To, createMemoryRouter, useNavigate } from "react-router-dom";
|
||||
import { Location, RouteObject, RouterProvider, To, createMemoryRouter, useNavigate } from "react-router-dom";
|
||||
|
||||
import { ErrorBoundary } from "../components/error-boundary";
|
||||
import NoteView from "../views/note";
|
||||
import { ChevronLeftIcon, ChevronRightIcon, ExternalLinkIcon } from "../components/icons";
|
||||
import { PageProviders } from ".";
|
||||
import { logger } from "../helpers/debug";
|
||||
|
||||
type Router = ReturnType<typeof createMemoryRouter>;
|
||||
|
||||
@ -82,40 +83,85 @@ export function useNavigateInDrawer() {
|
||||
return isInDrawer ? navigate : openDrawer;
|
||||
}
|
||||
|
||||
const log = logger.extend("DrawerRouter");
|
||||
|
||||
export default function DrawerSubViewProvider({
|
||||
children,
|
||||
parentRouter,
|
||||
}: PropsWithChildren & { parentRouter: Router }) {
|
||||
const [router, setRouter] = useState<Router | null>(null);
|
||||
|
||||
const openInParent = useCallback(
|
||||
const openInParent = useCallback((to: To) => parentRouter.navigate(to), [parentRouter]);
|
||||
|
||||
const direction = useRef<"up" | "down">();
|
||||
const marker = useRef<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
return parentRouter.subscribe((event) => {
|
||||
const location = event.location as Location<{ subRouterPath?: To | null } | null>;
|
||||
const subRoute = location.state?.subRouterPath;
|
||||
|
||||
if (event.historyAction === "PUSH") marker.current++;
|
||||
else if (event.historyAction === "POP") marker.current--;
|
||||
|
||||
if (subRoute) {
|
||||
if (router) {
|
||||
if (router.state.location.pathname !== subRoute && direction.current !== "up") {
|
||||
log("Updating router from parent state");
|
||||
direction.current = "down";
|
||||
router.navigate(subRoute);
|
||||
direction.current = undefined;
|
||||
}
|
||||
} else {
|
||||
log("Create Router");
|
||||
|
||||
const newRouter = createMemoryRouter(routes, { initialEntries: [subRoute] });
|
||||
newRouter.subscribe((e) => {
|
||||
if (e.errors && e.errors[0].status === 404 && e.errors[0].internal) {
|
||||
openInParent(e.location);
|
||||
} else if (direction.current !== "down") {
|
||||
log("Updating parent state from Router");
|
||||
direction.current = "up";
|
||||
parentRouter.navigate(".", {
|
||||
state: { ...parentRouter.state.location.state, subRouterPath: e.location.pathname },
|
||||
});
|
||||
}
|
||||
direction.current = undefined;
|
||||
});
|
||||
|
||||
// use the parent routers createHref method so that users can open links in new tabs
|
||||
newRouter.createHref = parentRouter.createHref;
|
||||
|
||||
setRouter(newRouter);
|
||||
}
|
||||
} else if (router) {
|
||||
log("Destroy Router");
|
||||
setRouter(null);
|
||||
}
|
||||
});
|
||||
}, [parentRouter, router, setRouter]);
|
||||
|
||||
const openDrawer = useCallback(
|
||||
(to: To) => {
|
||||
parentRouter.navigate(to);
|
||||
setRouter(null);
|
||||
marker.current = 0;
|
||||
parentRouter.navigate(".", { state: { ...parentRouter.state.location.state, subRouterPath: to } });
|
||||
},
|
||||
[parentRouter],
|
||||
);
|
||||
|
||||
const openDrawer = useCallback(
|
||||
(to: To) => {
|
||||
const newRouter = createMemoryRouter(routes, { initialEntries: [to] });
|
||||
newRouter.subscribe((e) => {
|
||||
if (e.errors && e.errors[0].status === 404 && e.errors[0].internal) {
|
||||
openInParent(e.location);
|
||||
}
|
||||
});
|
||||
|
||||
// use the parent routers createHref method so that users can open links in new tabs
|
||||
newRouter.createHref = parentRouter.createHref;
|
||||
|
||||
setRouter(newRouter);
|
||||
},
|
||||
[setRouter, openInParent],
|
||||
);
|
||||
|
||||
const closeDrawer = useCallback(() => {
|
||||
setRouter(null);
|
||||
}, [setRouter]);
|
||||
const i = marker.current;
|
||||
if (i > 0) {
|
||||
log(`Navigating back ${i} entries to the point the drawer was opened`);
|
||||
parentRouter.navigate(-i);
|
||||
} else {
|
||||
log(`Failed to navigate back, clearing state`);
|
||||
parentRouter.navigate(".", { state: { ...parentRouter.state.location.state, subRouterPath: undefined } });
|
||||
}
|
||||
|
||||
// reset marker
|
||||
marker.current = 0;
|
||||
}, [parentRouter]);
|
||||
|
||||
const context = useMemo(
|
||||
() => ({
|
||||
|
Loading…
x
Reference in New Issue
Block a user