StackedRouter: new router simulates app behaviour #45
3 changed files with 44 additions and 108 deletions
|
@ -3,11 +3,9 @@ import {
|
||||||
Show,
|
Show,
|
||||||
onMount,
|
onMount,
|
||||||
type ParentComponent,
|
type ParentComponent,
|
||||||
children,
|
createRenderEffect,
|
||||||
Suspense,
|
|
||||||
} from "solid-js";
|
} from "solid-js";
|
||||||
import { useDocumentTitle } from "../utils";
|
import { useDocumentTitle } from "../utils";
|
||||||
import { type mastodon } from "masto";
|
|
||||||
import Scaffold from "../material/Scaffold";
|
import Scaffold from "../material/Scaffold";
|
||||||
import {
|
import {
|
||||||
AppBar,
|
AppBar,
|
||||||
|
@ -23,17 +21,11 @@ import ProfileMenuButton from "./ProfileMenuButton";
|
||||||
import Tabs from "../material/Tabs";
|
import Tabs from "../material/Tabs";
|
||||||
import Tab from "../material/Tab";
|
import Tab from "../material/Tab";
|
||||||
import { makeEventListener } from "@solid-primitives/event-listener";
|
import { makeEventListener } from "@solid-primitives/event-listener";
|
||||||
import BottomSheet, {
|
|
||||||
HERO as BOTTOM_SHEET_HERO,
|
|
||||||
} from "../material/BottomSheet";
|
|
||||||
import { $settings } from "../settings/stores";
|
import { $settings } from "../settings/stores";
|
||||||
import { useStore } from "@nanostores/solid";
|
import { useStore } from "@nanostores/solid";
|
||||||
import { HeroSourceProvider, type HeroSource } from "../platform/anim";
|
|
||||||
import { setCache as setTootBottomSheetCache } from "./TootBottomSheet";
|
|
||||||
import TrendTimelinePanel from "./TrendTimelinePanel";
|
import TrendTimelinePanel from "./TrendTimelinePanel";
|
||||||
import TimelinePanel from "./TimelinePanel";
|
import TimelinePanel from "./TimelinePanel";
|
||||||
import { useSessions } from "../masto/clients";
|
import { useSessions } from "../masto/clients";
|
||||||
import { useNavigator } from "../platform/StackedRouter";
|
|
||||||
|
|
||||||
const Home: ParentComponent = (props) => {
|
const Home: ParentComponent = (props) => {
|
||||||
let panelList: HTMLDivElement;
|
let panelList: HTMLDivElement;
|
||||||
|
@ -43,29 +35,17 @@ const Home: ParentComponent = (props) => {
|
||||||
const settings$ = useStore($settings);
|
const settings$ = useStore($settings);
|
||||||
|
|
||||||
const profiles = useSessions();
|
const profiles = useSessions();
|
||||||
const profile = () => {
|
|
||||||
const all = profiles();
|
|
||||||
if (all.length > 0) {
|
|
||||||
return all[0].account.inf;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const client = () => {
|
const client = () => {
|
||||||
const all = profiles();
|
const all = profiles();
|
||||||
return all?.[0]?.client;
|
return all?.[0]?.client;
|
||||||
};
|
};
|
||||||
const {pop, push} = useNavigator();
|
|
||||||
|
|
||||||
const [heroSrc, setHeroSrc] = createSignal<HeroSource>({});
|
|
||||||
const [panelOffset, setPanelOffset] = createSignal(0);
|
|
||||||
const prefetching = () => !settings$().prefetchTootsDisabled;
|
const prefetching = () => !settings$().prefetchTootsDisabled;
|
||||||
const [currentFocusOn, setCurrentFocusOn] = createSignal<HTMLElement[]>([]);
|
|
||||||
const [focusRange, setFocusRange] = createSignal([0, 0] as readonly [
|
const [focusRange, setFocusRange] = createSignal([0, 0] as readonly [
|
||||||
number,
|
number,
|
||||||
number,
|
number,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const child = children(() => props.children);
|
|
||||||
|
|
||||||
let scrollEventLockReleased = true;
|
let scrollEventLockReleased = true;
|
||||||
|
|
||||||
const recalculateTabIndicator = () => {
|
const recalculateTabIndicator = () => {
|
||||||
|
@ -102,17 +82,17 @@ const Home: ParentComponent = (props) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const requestRecalculateTabIndicator = () => {
|
||||||
|
if (scrollEventLockReleased) {
|
||||||
|
requestAnimationFrame(recalculateTabIndicator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createRenderEffect(() => {
|
||||||
|
makeEventListener(window, "resize", requestRecalculateTabIndicator);
|
||||||
|
});
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
makeEventListener(panelList, "scroll", () => {
|
|
||||||
if (scrollEventLockReleased) {
|
|
||||||
requestAnimationFrame(recalculateTabIndicator);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
makeEventListener(window, "resize", () => {
|
|
||||||
if (scrollEventLockReleased) {
|
|
||||||
requestAnimationFrame(recalculateTabIndicator);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
requestAnimationFrame(recalculateTabIndicator);
|
requestAnimationFrame(recalculateTabIndicator);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -135,30 +115,6 @@ const Home: ParentComponent = (props) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const openFullScreenToot = (
|
|
||||||
toot: mastodon.v1.Status,
|
|
||||||
srcElement?: HTMLElement,
|
|
||||||
reply?: boolean,
|
|
||||||
) => {
|
|
||||||
const p = profiles()[0];
|
|
||||||
const inf = p.account.inf ?? profile();
|
|
||||||
if (!inf) {
|
|
||||||
console.warn("no account info?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setHeroSrc((x) =>
|
|
||||||
Object.assign({}, x, { [BOTTOM_SHEET_HERO]: srcElement }),
|
|
||||||
);
|
|
||||||
const acct = `${inf.username}@${p.account.site}`;
|
|
||||||
setTootBottomSheetCache(acct, toot);
|
|
||||||
push(`/${encodeURIComponent(acct)}/toot/${toot.id}`, {
|
|
||||||
state: reply
|
|
||||||
? {
|
|
||||||
tootReply: true,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
css`
|
css`
|
||||||
.tab-panel {
|
.tab-panel {
|
||||||
|
@ -209,7 +165,7 @@ const Home: ParentComponent = (props) => {
|
||||||
class="responsive"
|
class="responsive"
|
||||||
sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}
|
sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }}
|
||||||
>
|
>
|
||||||
<Tabs onFocusChanged={setCurrentFocusOn} offset={panelOffset()}>
|
<Tabs>
|
||||||
<Tab focus={isTabFocus(0)} onClick={[onTabClick, 0]}>
|
<Tab focus={isTabFocus(0)} onClick={[onTabClick, 0]}>
|
||||||
Home
|
Home
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -239,48 +195,40 @@ const Home: ParentComponent = (props) => {
|
||||||
</AppBar>
|
</AppBar>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<HeroSourceProvider value={[heroSrc, setHeroSrc]}>
|
<TimeSourceProvider value={now}>
|
||||||
<TimeSourceProvider value={now}>
|
<Show when={!!client()}>
|
||||||
<Show when={!!client()}>
|
<div
|
||||||
<div class="panel-list" ref={panelList!}>
|
class="panel-list"
|
||||||
<div class="tab-panel">
|
ref={panelList!}
|
||||||
<div>
|
onScroll={requestRecalculateTabIndicator}
|
||||||
<TimelinePanel
|
>
|
||||||
client={client()}
|
<div class="tab-panel">
|
||||||
name="home"
|
<div>
|
||||||
prefetch={prefetching()}
|
<TimelinePanel
|
||||||
openFullScreenToot={openFullScreenToot}
|
client={client()}
|
||||||
/>
|
name="home"
|
||||||
</div>
|
prefetch={prefetching()}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-panel">
|
|
||||||
<div>
|
|
||||||
<TrendTimelinePanel
|
|
||||||
client={client()}
|
|
||||||
openFullScreenToot={openFullScreenToot}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab-panel">
|
|
||||||
<div>
|
|
||||||
<TimelinePanel
|
|
||||||
client={client()}
|
|
||||||
name="public"
|
|
||||||
prefetch={prefetching()}
|
|
||||||
openFullScreenToot={openFullScreenToot}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
<div class="tab-panel">
|
||||||
</TimeSourceProvider>
|
<div>
|
||||||
<Suspense>
|
<TrendTimelinePanel client={client()} />
|
||||||
<BottomSheet open={!!child()} onClose={() => pop(1)}>
|
</div>
|
||||||
{child()}
|
</div>
|
||||||
</BottomSheet>
|
<div class="tab-panel">
|
||||||
</Suspense>
|
<div>
|
||||||
</HeroSourceProvider>
|
<TimelinePanel
|
||||||
|
client={client()}
|
||||||
|
name="public"
|
||||||
|
prefetch={prefetching()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</TimeSourceProvider>
|
||||||
</Scaffold>
|
</Scaffold>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,12 +20,6 @@ const TimelinePanel: Component<{
|
||||||
client: mastodon.rest.Client;
|
client: mastodon.rest.Client;
|
||||||
name: "home" | "public";
|
name: "home" | "public";
|
||||||
prefetch?: boolean;
|
prefetch?: boolean;
|
||||||
|
|
||||||
openFullScreenToot: (
|
|
||||||
toot: mastodon.v1.Status,
|
|
||||||
srcElement?: HTMLElement,
|
|
||||||
reply?: boolean,
|
|
||||||
) => void;
|
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const [scrollLinked, setScrollLinked] = createSignal<HTMLElement>();
|
const [scrollLinked, setScrollLinked] = createSignal<HTMLElement>();
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,6 @@ import TootList from "./TootList.jsx";
|
||||||
|
|
||||||
const TrendTimelinePanel: Component<{
|
const TrendTimelinePanel: Component<{
|
||||||
client: mastodon.rest.Client;
|
client: mastodon.rest.Client;
|
||||||
|
|
||||||
openFullScreenToot: (
|
|
||||||
toot: mastodon.v1.Status,
|
|
||||||
srcElement?: HTMLElement,
|
|
||||||
reply?: boolean,
|
|
||||||
) => void;
|
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const [scrollLinked, setScrollLinked] = createSignal<HTMLElement>();
|
const [scrollLinked, setScrollLinked] = createSignal<HTMLElement>();
|
||||||
const [tl, snapshot, { refetch: refetchTimeline }] = createTimelineSnapshot(
|
const [tl, snapshot, { refetch: refetchTimeline }] = createTimelineSnapshot(
|
||||||
|
|
Loading…
Reference in a new issue