StackedRouter: new router simulates app behaviour #45

Merged
Rubicon merged 18 commits from stacky into master 2024-11-18 10:35:30 +00:00
3 changed files with 44 additions and 108 deletions
Showing only changes of commit f0dadebfb6 - Show all commits

View file

@ -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>
</> </>
); );

View file

@ -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>();

View file

@ -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(