1import {
2 DEFAULT_BROWSER_PROFILE_ID,
3 resolveBrowserProfiles,
4 type BrowserProfile,
5 type DesktopPreviewTabDefaults,
6 type PreviewAppearancePreference,
7 type PreviewViewportSetting,
8} from "@t3tools/contracts";
9
10import {
11 ensureClientSettingsHydrated,
12 getClientSettings,
13 useClientSettings,
14} from "~/hooks/useSettings";
15
16import { resolveResponsiveBrowserViewportSize } from "./browserViewportLayout";
17
18export interface BrowserDefaults {
19 readonly viewport: PreviewViewportSetting;
20 readonly zoomFactor: number;
21 readonly appearance: PreviewAppearancePreference;
22 readonly autoShowFloatingPreview: boolean;
23 readonly profiles: ReadonlyArray<BrowserProfile>;
24 readonly profileId: string;
25}
26
27const toBrowserDefaults = (settings: {
28 readonly browserDefaultViewport: PreviewViewportSetting;
29 readonly browserDefaultZoomFactor: number;
30 readonly browserDefaultAppearance: PreviewAppearancePreference;
31 readonly browserAutoShowFloatingPreview: boolean;
32 readonly browserProfiles: ReadonlyArray<BrowserProfile>;
33 readonly browserDefaultProfileId: string;
34}): BrowserDefaults => {
35 const profiles = resolveBrowserProfiles(settings.browserProfiles);
36 return {
37 viewport: settings.browserDefaultViewport,
38 zoomFactor: settings.browserDefaultZoomFactor,
39 appearance: settings.browserDefaultAppearance,
40 autoShowFloatingPreview: settings.browserAutoShowFloatingPreview,
41 profiles,
42 profileId:
43 profiles.find(
44 (profile) =>
45 profile.id === settings.browserDefaultProfileId && profile.kind !== "incognito",
46 )?.id ?? DEFAULT_BROWSER_PROFILE_ID,
47 };
48};
49
50export function getBrowserDefaults(): BrowserDefaults {
51 return toBrowserDefaults(getClientSettings());
52}
53
54/** New tabs retain their initial defaults, so wait for settings hydration. Read failures reject. */
55export async function resolveBrowserDefaults(): Promise<BrowserDefaults> {
56 await ensureClientSettingsHydrated();
57 return getBrowserDefaults();
58}
59
60export function useBrowserDefaults(): BrowserDefaults {
61 return useClientSettings(toBrowserDefaults);
62}
63
64export function browserDefaultTabState(defaults: BrowserDefaults): DesktopPreviewTabDefaults {
65 return { zoomFactor: defaults.zoomFactor, colorScheme: defaults.appearance };
66}
67
68const FALLBACK_RESPONSIVE_VIEWPORT_SIZE = { width: 1024, height: 768 } as const;
69
70export function browserResponsiveViewportForToggle(input: {
71 readonly defaults?: BrowserDefaults;
72 readonly panelRect: { readonly width: number; readonly height: number } | null;
73 readonly zoomFactor: number | undefined;
74}): PreviewViewportSetting {
75 const defaults = input.defaults ?? getBrowserDefaults();
76 if (defaults.viewport._tag !== "fill") return defaults.viewport;
77 const size = input.panelRect
78 ? resolveResponsiveBrowserViewportSize(input.panelRect, input.zoomFactor)
79 : FALLBACK_RESPONSIVE_VIEWPORT_SIZE;
80 return { _tag: "freeform", ...size };
81}