import { app } from "../app.ts"; import { network } from "../network/network.ts"; import { useNavigate, useOutlet } from "react-router"; import { createContext, useContext, useEffect, useState } from "react"; import { MdArrowUpward, MdOutlinePerson, MdSearch } from "react-icons/md"; import { useTranslation } from "../utils/i18n"; import UploadingSideBar from "./uploading_side_bar.tsx"; import { ThemeSwitcher } from "./theme_switcher.tsx"; import { IoLogoGithub } from "react-icons/io"; import { useAppContext } from "./AppContext.tsx"; import { AnimatePresence, motion } from "framer-motion"; export default function Navigator() { const outlet = useOutlet(); const navigate = useNavigate(); const [key, setKey] = useState(0); const [background, setBackground] = useState(undefined); const appContext = useAppContext(); const [naviContext, _] = useState({ refresh: () => { setKey(key + 1); }, setBackground: (b: string) => { if (b !== background) { setBackground(b); } }, }); const { t } = useTranslation(); return ( <> {/* background */} {background && (
)} {/* Background overlay */} {background && (
)} {/* Content overlay with backdrop blur */}
{app.isLoggedIn() ? ( ) : ( )}
{outlet}
); } interface NavigatorContext { refresh: () => void; setBackground: (background: string) => void; } const navigatorContext = createContext({ refresh: () => { // do nothing }, setBackground: (_) => { // do nothing }, }); export function useNavigator() { return useContext(navigatorContext); } function UserButton() { let avatar = "./avatar.png"; if (app.user) { avatar = network.getUserAvatar(app.user); } const navigate = useNavigate(); const { t } = useTranslation(); return ( <>

{t("Log out")}

{t("Are you sure you want to log out?")}

); } function SearchBar() { const [small, setSmall] = useState(window.innerWidth < 640); const navigate = useNavigate(); const [search, setSearch] = useState(""); const { t } = useTranslation(); useEffect(() => { const handleResize = () => { if (window.innerWidth < 640) { setSmall(true); } else { setSmall(false); } }; window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); }; }, []); const doSearch = () => { if (search.length === 0) { return; } const replace = window.location.pathname === "/search"; navigate(`/search?keyword=${search}`, { replace: replace }); }; const searchField = ( ); if (small) { return ( <>

{t("Search")}

{searchField}
); } return searchField; } function FloatingToTopButton() { const [visible, setVisible] = useState(false); useEffect(() => { let lastScrollY = window.scrollY; const handleScroll = () => { const isScrollingUp = window.scrollY < lastScrollY; const isAboveThreshold = window.scrollY > 200; setVisible(isScrollingUp && isAboveThreshold); lastScrollY = window.scrollY; }; window.addEventListener("scroll", handleScroll); return () => { window.removeEventListener("scroll", handleScroll); }; }, []); return ( ); }