import type { CapacitorConfig } from "@capacitor/cli"; /* Two Android apps, one config. * * npx cap sync android → the counter app (tech.threadcount.app → /m) * TC_APP=staff npx cap sync android → the staff app (tech.threadcount.staff → /my) * * The Capacitor 6 CLI has no --config flag and always reads this file from the working directory, * so the alternative to branching here is swapping files around before every build — which is the * kind of step that eventually ships the wrong app id to Play. One file, one env var, two * `android.path`s, and neither project can overwrite the other. * * Both are the live site in a native shell, so the apps update when the site does and there is one * copy of every rule rather than two. Each bundles only its own first-run screens, which are the * only ones that must work before someone has signed in or has signal. */ const staff = process.env.TC_APP === "staff"; const counter: CapacitorConfig = { appId: "tech.threadcount.app", appName: "ThreadCount", // Splash, welcome (with the video) and the offline screen. webDir: "androidshell", server: { androidScheme: "https", cleartext: false, // The shell opens on its own bundled splash and welcome, then navigates to the live site. allowNavigation: ["threadcount.tech"], // A page that fails to load falls back to the bundled offline screen, not a browser error. errorPath: "error.html", }, android: { // A stock count is read at arm's length under ward lighting; let the OS text size apply. allowMixedContent: false, // captureInput is deliberately absent. It swaps the WebView's input connection for a bare // BaseInputConnection that never fills in the EditorInfo, so the keyboard sees no inputType on // any field: the numeric two-factor box gets a QWERTY keyboard, one-time-code autofill is // never offered, and a password manager loses the hints the assetlinks file goes out of its // way to enable. It only buys anything for a hardware keyboard-wedge scanner, and neither app // has one — every barcode here is read through the camera. webContentsDebuggingEnabled: false, }, plugins: { SplashScreen: { // Just long enough to cover the WebView starting. The bundled splash draws the mark from // here, so this screen is plain ink — showing the mark twice, once still and once drawing, // reads as a stutter. launchShowDuration: 350, backgroundColor: "#201e1dff", androidSplashResourceName: "splash", androidScaleType: "CENTER_CROP", showSpinner: false, }, }, }; /* The staff app. * * A separate app rather than a role switch inside the counter app, because the audiences share * nothing. The counter app goes on a handful of ward phones belonging to the people who run the * linen room; this one goes on every nurse's phone. One Play listing cannot describe both, and a * wearer opening an app whose home screen is a stocktake counter would reasonably conclude they * had installed the wrong thing. * * It carries no barcode scanner and asks for no camera permission: nothing a wearer does involves * scanning, and an app that every clinical staff member installs should ask for as little as it * possibly can. */ const staffApp: CapacitorConfig = { ...counter, appId: "tech.threadcount.staff", appName: "ThreadCount Staff", webDir: "staffshell", android: { ...counter.android, // Its own native project, beside the counter app's rather than replacing it. path: "android-staff", }, }; export default staff ? staffApp : counter;