Repository navigation
Expand file tree
/
Copy pathbrowserLinkTarget.ts
More file actions
51 lines (45 loc) · 1.61 KB
/
Copy pathbrowserLinkTarget.ts
File metadata and controls
51 lines (45 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import {
AuthPreviewOperateScope,
type BrowserLinkTarget,
type ScopedThreadRef,
} from "@t3tools/contracts";
import { ensureClientSettingsHydrated, getClientSettings } from "~/hooks/useSettings";
import { readEnvironmentScope } from "~/state/session";
import { isPreviewAvailableFor } from "./previewRuntime";
export interface ResolveLinkTargetInput {
readonly url: string;
readonly event: {
readonly metaKey: boolean;
readonly ctrlKey: boolean;
readonly button?: number | undefined;
};
readonly preference: BrowserLinkTarget;
readonly canOpenInApp: boolean;
}
export function resolveLinkTarget(input: ResolveLinkTargetInput): BrowserLinkTarget {
if (input.event.metaKey || input.event.ctrlKey || input.event.button === 1) return "system";
if (input.preference !== "app") return "system";
if (!input.canOpenInApp) return "system";
if (!isWebUrl(input.url)) return "system";
return "app";
}
export function isWebUrl(url: string): boolean {
try {
const { protocol } = new URL(url);
return protocol === "http:" || protocol === "https:";
} catch {
return false;
}
}
/** Before hydration, the default "system" would ignore a saved "app" link target. */
export async function resolveBrowserLinkTargetPreference(): Promise<BrowserLinkTarget> {
await ensureClientSettingsHydrated();
return getClientSettings().browserLinkTarget;
}
export function canOpenLinksInApp(threadRef: ScopedThreadRef | null | undefined): boolean {
return (
threadRef != null &&
readEnvironmentScope(threadRef.environmentId, AuthPreviewOperateScope) &&
isPreviewAvailableFor(threadRef.environmentId)
);
}