85 lines
2.9 KiB
TypeScript
85 lines
2.9 KiB
TypeScript
/**
|
|
* Platform detection shared by web and the Tauri mobile/native builds.
|
|
*
|
|
* - `IS_MOBILE_BUILD` is a *build-time* flag (set by `NEXT_PUBLIC_MOBILE=1`)
|
|
* used to gate the static export, drop server API routes, and switch auth to
|
|
* the native flow. It is statically analyzable so dead code is tree-shaken.
|
|
* - `isTauriRuntime()` is a *runtime* check (the same static bundle can be
|
|
* loaded by a browser during development, e.g. `pnpm dev`, even when built in
|
|
* mobile mode).
|
|
*/
|
|
|
|
/** True when the bundle was built for the Tauri native shells. */
|
|
export const IS_MOBILE_BUILD = process.env.NEXT_PUBLIC_MOBILE === "1"
|
|
|
|
/**
|
|
* The per-app product this build targets (UltiMail, UltiDrive, …). Drives the
|
|
* default start route, the deep-link scheme, and which sibling apps the suite
|
|
* launcher tries to open. Defaults to `mail` (the pilot).
|
|
*/
|
|
export type SuiteApp = "mail" | "drive" | "agenda" | "meet" | "chat" | "contacts"
|
|
|
|
export const SUITE_APP: SuiteApp =
|
|
(process.env.NEXT_PUBLIC_SUITE_APP as SuiteApp | undefined) ?? "mail"
|
|
|
|
/** Custom URL scheme for this app's deep links, e.g. `ultimail://`. */
|
|
export function appScheme(app: SuiteApp = SUITE_APP): string {
|
|
return `ulti${app}`
|
|
}
|
|
|
|
/** Default start route for an app shell. */
|
|
export function appStartRoute(app: SuiteApp = SUITE_APP): string {
|
|
switch (app) {
|
|
case "mail":
|
|
return "/mail"
|
|
case "drive":
|
|
return "/drive"
|
|
case "agenda":
|
|
return "/agenda"
|
|
case "meet":
|
|
return "/meet"
|
|
case "chat":
|
|
return "/chat"
|
|
case "contacts":
|
|
return "/contacts"
|
|
default:
|
|
return "/mail"
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Map an in-app route to the suite app that "owns" it, so the launcher can open
|
|
* the sibling native app instead of navigating in-webview. Returns null for
|
|
* routes that should stay in the current app (settings, account, admin, …).
|
|
*/
|
|
export function suiteAppForRoute(route: string): SuiteApp | null {
|
|
const path = route.split("?")[0]
|
|
if (path.startsWith("/mail")) return "mail"
|
|
if (path.startsWith("/drive")) return "drive"
|
|
if (path.startsWith("/agenda")) return "agenda"
|
|
if (path.startsWith("/meet")) return "agenda" // UltiCal+UltiMeet share one app
|
|
if (path.startsWith("/chat")) return "chat"
|
|
if (path.startsWith("/contacts")) return "contacts"
|
|
return null
|
|
}
|
|
|
|
/** True only when actually executing inside a Tauri webview. */
|
|
export function isTauriRuntime(): boolean {
|
|
if (typeof window === "undefined") return false
|
|
return (
|
|
"__TAURI_INTERNALS__" in window ||
|
|
"__TAURI__" in window ||
|
|
// Tauri v2 exposes this in some configurations.
|
|
(window as { isTauri?: boolean }).isTauri === true
|
|
)
|
|
}
|
|
|
|
/**
|
|
* True when we should use the native auth + runtime-config code paths.
|
|
* Mobile builds always use native paths; a mobile build opened in a plain
|
|
* browser (dev) also uses them so the flow can be exercised without a device.
|
|
*/
|
|
export function useNativeRuntime(): boolean {
|
|
return IS_MOBILE_BUILD || isTauriRuntime()
|
|
}
|