Skip to content
Source
Sign inSign up

home-launch-splash.ts

75 lines2.2 KB

1import { useSyncExternalStore } from "react";
2​
3/**
4 * Whether the launch splash still waits for Home's list. A list holds the splash while it
5 * has cached rows to lay out, so the first frame after the splash shows them.
6 */
7export function createLaunchSplashHomeRows() {
8 let holds = 0;
9 let settled = false;
10 const listeners = new Set<() => void>();
11 const pending = () => !settled && holds > 0;
12 const change = (apply: () => void) => {
13 const before = pending();
14 apply();
15 if (pending() !== before) for (const listener of listeners) listener();
16 };
17 return {
18 pending,
19 /**
20 * A Home list has rows that are not laid out yet. Call the returned release when it no
21 * longer has them or unmounts; rows that come later can hold again.
22 */
23 hold: () => {
24 let held = true;
25 change(() => {
26 holds += 1;
27 });
28 return () => {
29 if (!held) return;
30 held = false;
31 change(() => {
32 holds -= 1;
33 });
34 };
35 },
36 /**
37 * The rows are laid out, the launch opened another route, or the splash is gone. It is
38 * final: lists that mount after the launch must not hold anything.
39 */
40 settle: () =>
41 change(() => {
42 settled = true;
43 }),
44 subscribe: (onChange: () => void) => {
45 listeners.add(onChange);
46 return () => {
47 listeners.delete(onChange);
48 };
49 },
50 };
52​
53const homeRows = createLaunchSplashHomeRows();
54​
55export const holdLaunchSplashForHomeRows = homeRows.hold;
56export const settleLaunchSplashHomeRows = homeRows.settle;
57export const launchSplashHomeRowsPending = homeRows.pending;
58​
59export function useLaunchSplashHomeRowsPending(): boolean {
60 return useSyncExternalStore(homeRows.subscribe, homeRows.pending);
62​
63/**
64 * Whether the native splash can hide: after the cached shells are read and Home's list has
65 * laid out their rows. One limit ends both waits.
66 */
67export function splashCanHide(input: {
68 readonly preferencesReady: boolean;
69 readonly shellCachesRead: boolean;
70 readonly homeRowsPending: boolean;
71 readonly waitEnded: boolean;
72}): boolean {
73 if (!input.preferencesReady) return false;
74 return input.waitEnded || (input.shellCachesRead && !input.homeRowsPending);