mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-23 15:04:09 +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 {
|
import {
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Drawer,
|
Drawer,
|
||||||
@ -9,13 +10,13 @@ import {
|
|||||||
DrawerProps,
|
DrawerProps,
|
||||||
IconButton,
|
IconButton,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { PropsWithChildren, createContext, useCallback, useContext, useMemo, useState } from "react";
|
import { Location, RouteObject, RouterProvider, To, createMemoryRouter, useNavigate } from "react-router-dom";
|
||||||
import { RouteObject, RouterProvider, To, createMemoryRouter, useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
import { ErrorBoundary } from "../components/error-boundary";
|
import { ErrorBoundary } from "../components/error-boundary";
|
||||||
import NoteView from "../views/note";
|
import NoteView from "../views/note";
|
||||||
import { ChevronLeftIcon, ChevronRightIcon, ExternalLinkIcon } from "../components/icons";
|
import { ChevronLeftIcon, ChevronRightIcon, ExternalLinkIcon } from "../components/icons";
|
||||||
import { PageProviders } from ".";
|
import { PageProviders } from ".";
|
||||||
|
import { logger } from "../helpers/debug";
|
||||||
|
|
||||||
type Router = ReturnType<typeof createMemoryRouter>;
|
type Router = ReturnType<typeof createMemoryRouter>;
|
||||||
|
|
||||||
@ -82,40 +83,85 @@ export function useNavigateInDrawer() {
|
|||||||
return isInDrawer ? navigate : openDrawer;
|
return isInDrawer ? navigate : openDrawer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const log = logger.extend("DrawerRouter");
|
||||||
|
|
||||||
export default function DrawerSubViewProvider({
|
export default function DrawerSubViewProvider({
|
||||||
children,
|
children,
|
||||||
parentRouter,
|
parentRouter,
|
||||||
}: PropsWithChildren & { parentRouter: Router }) {
|
}: PropsWithChildren & { parentRouter: Router }) {
|
||||||
const [router, setRouter] = useState<Router | null>(null);
|
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) => {
|
(to: To) => {
|
||||||
parentRouter.navigate(to);
|
marker.current = 0;
|
||||||
setRouter(null);
|
parentRouter.navigate(".", { state: { ...parentRouter.state.location.state, subRouterPath: to } });
|
||||||
},
|
},
|
||||||
[parentRouter],
|
[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(() => {
|
const closeDrawer = useCallback(() => {
|
||||||
setRouter(null);
|
const i = marker.current;
|
||||||
}, [setRouter]);
|
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(
|
const context = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user