9 changed files with 156 additions and 26 deletions
@ -0,0 +1,60 @@ |
|||||||
|
import { useLayoutEffect, useState } from "react"; |
||||||
|
|
||||||
|
export function useFloatingRouter(initial = "/") { |
||||||
|
const [route, setRoute] = useState<string[]>( |
||||||
|
initial.split("/").filter((v) => v.length > 0) |
||||||
|
); |
||||||
|
const [previousRoute, setPreviousRoute] = useState(route); |
||||||
|
const currentPage = route[route.length - 1] ?? "/"; |
||||||
|
|
||||||
|
useLayoutEffect(() => { |
||||||
|
if (previousRoute.length === route.length) return; |
||||||
|
// when navigating backwards, we delay the updating by a bit so transitions can be applied correctly
|
||||||
|
setTimeout(() => { |
||||||
|
setPreviousRoute(route); |
||||||
|
}, 20); |
||||||
|
}, [route, previousRoute]); |
||||||
|
|
||||||
|
function navigate(path: string) { |
||||||
|
const newRoute = path.split("/").filter((v) => v.length > 0); |
||||||
|
if (newRoute.length > previousRoute.length) setPreviousRoute(newRoute); |
||||||
|
setRoute(newRoute); |
||||||
|
} |
||||||
|
|
||||||
|
function isActive(page: string) { |
||||||
|
if (page === "/") return true; |
||||||
|
const index = previousRoute.indexOf(page); |
||||||
|
if (index === -1) return false; // not active
|
||||||
|
if (index === previousRoute.length - 1) return false; // active but latest route so shouldnt be counted as active
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
function isCurrentPage(page: string) { |
||||||
|
return page === currentPage; |
||||||
|
} |
||||||
|
|
||||||
|
function isLoaded(page: string) { |
||||||
|
if (page === "/") return true; |
||||||
|
return route.includes(page); |
||||||
|
} |
||||||
|
|
||||||
|
function pageProps(page: string) { |
||||||
|
return { |
||||||
|
show: isCurrentPage(page), |
||||||
|
active: isActive(page), |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function reset() { |
||||||
|
navigate("/"); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
navigate, |
||||||
|
reset, |
||||||
|
isLoaded, |
||||||
|
isCurrentPage, |
||||||
|
pageProps, |
||||||
|
isActive, |
||||||
|
}; |
||||||
|
} |
||||||
@ -1,22 +1,48 @@ |
|||||||
|
import { FloatingView } from "@/components/popout/FloatingView"; |
||||||
|
import { useFloatingRouter } from "@/hooks/useFloatingRouter"; |
||||||
import { DownloadAction } from "@/video/components/actions/list-entries/DownloadAction"; |
import { DownloadAction } from "@/video/components/actions/list-entries/DownloadAction"; |
||||||
import { useState } from "react"; |
|
||||||
import { CaptionsSelectionAction } from "../actions/CaptionsSelectionAction"; |
import { CaptionsSelectionAction } from "../actions/CaptionsSelectionAction"; |
||||||
import { SourceSelectionAction } from "../actions/SourceSelectionAction"; |
import { SourceSelectionAction } from "../actions/SourceSelectionAction"; |
||||||
import { CaptionSelectionPopout } from "./CaptionSelectionPopout"; |
import { CaptionSelectionPopout } from "./CaptionSelectionPopout"; |
||||||
import { PopoutSection } from "./PopoutUtils"; |
import { PopoutSection } from "./PopoutUtils"; |
||||||
import { SourceSelectionPopout } from "./SourceSelectionPopout"; |
|
||||||
|
|
||||||
export function SettingsPopout() { |
function TestPopout(props: { router: ReturnType<typeof useFloatingRouter> }) { |
||||||
const [popoutId, setPopoutId] = useState(""); |
const isCollapsed = props.router.isLoaded("embed"); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<p onClick={() => props.router.navigate("/")}>go back</p> |
||||||
|
<p>{isCollapsed ? "opened" : "closed"}</p> |
||||||
|
<p onClick={() => props.router.navigate("/source/embed")}>Open</p> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
if (popoutId === "source") return <SourceSelectionPopout />; |
export function SettingsPopout() { |
||||||
if (popoutId === "captions") return <CaptionSelectionPopout />; |
const floatingRouter = useFloatingRouter(); |
||||||
|
const { pageProps, navigate, isLoaded, isActive } = floatingRouter; |
||||||
|
|
||||||
return ( |
return ( |
||||||
<PopoutSection> |
<> |
||||||
<DownloadAction /> |
<FloatingView {...pageProps("/")} width={320}> |
||||||
<SourceSelectionAction onClick={() => setPopoutId("source")} /> |
<PopoutSection> |
||||||
<CaptionsSelectionAction onClick={() => setPopoutId("captions")} /> |
<DownloadAction /> |
||||||
</PopoutSection> |
<SourceSelectionAction onClick={() => navigate("/source")} /> |
||||||
|
<CaptionsSelectionAction onClick={() => navigate("/captions")} /> |
||||||
|
</PopoutSection> |
||||||
|
</FloatingView> |
||||||
|
<FloatingView |
||||||
|
active={isActive("source")} |
||||||
|
show={isLoaded("source")} |
||||||
|
height={500} |
||||||
|
width={320} |
||||||
|
> |
||||||
|
<TestPopout router={floatingRouter} /> |
||||||
|
{/* <SourceSelectionPopout /> */} |
||||||
|
</FloatingView> |
||||||
|
<FloatingView {...pageProps("captions")} height={500} width={320}> |
||||||
|
<CaptionSelectionPopout /> |
||||||
|
</FloatingView> |
||||||
|
</> |
||||||
); |
); |
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue