| 1 | /** |
| 2 | * The desktop app (apps/desktop) is for using g1t, not for browsing the |
| 3 | * site: someone signed out there lands on the sign-in page, never the |
| 4 | * landing page. The site knows it is inside the app by a cookie. The |
| 5 | * app's launcher opens `/?app=desktop`, and the home page answers that by |
| 6 | * setting the cookie; the bridge's presence on a page sets it too, for a |
| 7 | * build of the app older than the query (routes/home.tsx). The app keeps |
| 8 | * its own cookies, apart from any browser's, so the cookie never follows |
| 9 | * someone to the site in their browser. |
| 10 | */ |
| 11 | |
| 12 | import { readCookie } from "./github.ts"; |
| 13 | |
| 14 | export const DESKTOP_COOKIE = "g1t_app"; |
| 15 | export const DESKTOP_VALUE = "desktop"; |
| 16 | /** The query the launcher opens the server with: `/?app=desktop`. */ |
| 17 | export const DESKTOP_QUERY = "app"; |
| 18 | |
| 19 | /** A year: the cookie outlives sign-outs, and the app renews it at every launch. */ |
| 20 | export const DESKTOP_COOKIE_SECONDS = 365 * 24 * 60 * 60; |
| 21 | |
| 22 | /** Whether a request comes from the desktop app's window. */ |
| 23 | export function fromDesktopApp(request: Request): boolean { |
| 24 | return readCookie(request.headers.get("cookie"), DESKTOP_COOKIE) === DESKTOP_VALUE; |
| 25 | } |
| 26 | |
| 27 | /** Whether a request is the launcher's first, `/?app=desktop`. */ |
| 28 | export function launchedFromDesktopApp(url: URL): boolean { |
| 29 | return url.searchParams.get(DESKTOP_QUERY) === DESKTOP_VALUE; |
| 30 | } |
| 31 | |
| 32 | /** Sets the cookie from the page, for an app that opened `/` without the query. */ |
| 33 | export function rememberDesktopApp(): void { |
| 34 | if (typeof document === "undefined") return; |
| 35 | const secure = location.protocol === "https:" ? "; Secure" : ""; |
| 36 | document.cookie = `${DESKTOP_COOKIE}=${DESKTOP_VALUE}; Path=/; SameSite=Lax; Max-Age=${DESKTOP_COOKIE_SECONDS}${secure}`; |
| 37 | } |