forked from
pds.ls/pdsls
this repo has no description
1import { Handle } from "@atcute/lexicons";
2import { Meta, MetaProvider } from "@solidjs/meta";
3import { A, RouteSectionProps, useLocation, useNavigate } from "@solidjs/router";
4import { createEffect, createSignal, ErrorBoundary, onMount, Show, Suspense } from "solid-js";
5import { AccountManager } from "./components/account.jsx";
6import { RecordEditor } from "./components/create.jsx";
7import { DropdownMenu, MenuProvider, NavMenu } from "./components/dropdown.jsx";
8import { agent } from "./components/login.jsx";
9import { NavBar } from "./components/navbar.jsx";
10import { Search, SearchButton, showSearch } from "./components/search.jsx";
11import { themeEvent, ThemeSelection } from "./components/theme.jsx";
12import { resolveHandle } from "./utils/api.js";
13
14export const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 1;
15
16export const [notif, setNotif] = createSignal<{
17 show: boolean;
18 icon?: string;
19 text?: string;
20}>({ show: false });
21
22const Layout = (props: RouteSectionProps<unknown>) => {
23 const location = useLocation();
24 const navigate = useNavigate();
25 let timeout: number;
26
27 createEffect(async () => {
28 if (props.params.repo && !props.params.repo.startsWith("did:")) {
29 const did = await resolveHandle(props.params.repo as Handle);
30 navigate(location.pathname.replace(props.params.repo, did));
31 }
32 });
33
34 createEffect(() => {
35 if (notif().show) {
36 clearTimeout(timeout);
37 timeout = setTimeout(() => setNotif({ show: false }), 3000);
38 }
39 });
40
41 onMount(() => {
42 window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", themeEvent);
43 });
44
45 return (
46 <div id="main" class="m-4 flex flex-col items-center text-neutral-900 dark:text-neutral-200">
47 <MetaProvider>
48 <Show when={location.pathname !== "/"}>
49 <Meta name="robots" content="noindex, nofollow" />
50 </Show>
51 </MetaProvider>
52 <header class="mb-4 flex w-[22.5rem] items-center justify-between sm:w-[24.5rem]">
53 <A
54 href="/"
55 style='font-feature-settings: "cv05"'
56 class="flex items-center gap-1 rounded-lg px-1 text-xl font-semibold hover:bg-neutral-200 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-700"
57 >
58 <span class="iconify tabler--binary-tree-filled text-[#76c4e5]"></span>
59 <span>PDSls</span>
60 </A>
61 <div class="relative flex items-center gap-1">
62 <Show when={location.pathname !== "/"}>
63 <SearchButton />
64 </Show>
65 <Show when={agent()}>
66 <RecordEditor create={true} />
67 </Show>
68 <AccountManager />
69 <MenuProvider>
70 <DropdownMenu
71 icon="lucide--menu text-xl"
72 buttonClass="rounded-lg p-1"
73 menuClass="top-8 p-3 text-sm"
74 >
75 <NavMenu href="/jetstream" label="Jetstream" icon="lucide--radio-tower" />
76 <NavMenu href="/firehose" label="Firehose" icon="lucide--waves" />
77 <NavMenu href="/settings" label="Settings" icon="lucide--settings" />
78 <ThemeSelection />
79 </DropdownMenu>
80 </MenuProvider>
81 </div>
82 </header>
83 <div class="flex max-w-full min-w-[22rem] flex-col items-center gap-4 text-pretty sm:min-w-[24rem] md:max-w-[48rem]">
84 <Show when={showSearch() || location.pathname === "/"}>
85 <Search />
86 </Show>
87 <Show when={props.params.pds}>
88 <NavBar params={props.params} />
89 </Show>
90 <Show keyed when={location.pathname}>
91 <ErrorBoundary
92 fallback={(err) => <div class="mt-3 break-words">Error: {err.message}</div>}
93 >
94 <Suspense
95 fallback={
96 <span class="iconify lucide--loader-circle mt-3 animate-spin text-xl"></span>
97 }
98 >
99 {props.children}
100 </Suspense>
101 </ErrorBoundary>
102 </Show>
103 </div>
104 <Show when={notif().show}>
105 <button
106 class="dark:shadow-dark-800 dark:bg-dark-100 fixed bottom-10 z-50 flex items-center rounded-lg border-[0.5px] border-neutral-300 bg-white p-2 shadow-md dark:border-neutral-700"
107 onClick={() => setNotif({ show: false })}
108 >
109 <span class={`iconify ${notif().icon} mr-1`}></span>
110 {notif().text}
111 </button>
112 </Show>
113 </div>
114 );
115};
116
117export { Layout };