Add iOS Shortcuts/Siri intents, local send-reminder notifications, stable client picker with last-client defaults, account refresh/remove, and softer session handling on unauthorized API responses. Co-authored-by: Cursor <cursoragent@cursor.com>
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import * as Linking from "expo-linking";
|
|
|
|
export type ShortcutAction = "clock-in" | "clock-out" | "open-timer";
|
|
|
|
export type ParsedShortcut = {
|
|
action: ShortcutAction;
|
|
title: string;
|
|
clientId: string;
|
|
};
|
|
|
|
function queryParam(value: string | string[] | undefined): string {
|
|
if (Array.isArray(value)) return value[0] ?? "";
|
|
return value ?? "";
|
|
}
|
|
|
|
/** Parse `beenvoice://shortcuts/clock-in` and related URLs from Shortcuts / Siri. */
|
|
export function parseShortcutUrl(url: string | null | undefined): ParsedShortcut | null {
|
|
if (!url) return null;
|
|
|
|
const parsed = Linking.parse(url);
|
|
if (parsed.scheme !== "beenvoice") return null;
|
|
|
|
const path = (parsed.path ?? "").replace(/^\/+/, "");
|
|
const host = parsed.hostname ?? "";
|
|
|
|
if (path === "timer" || host === "timer") {
|
|
return { action: "open-timer", title: "", clientId: "" };
|
|
}
|
|
|
|
let shortcutAction: string | null = null;
|
|
if (host === "shortcuts" && path) {
|
|
shortcutAction = path;
|
|
} else {
|
|
const match = path.match(/^shortcuts\/(clock-in|clock-out)$/);
|
|
shortcutAction = match?.[1] ?? null;
|
|
}
|
|
|
|
if (shortcutAction === "clock-in" || shortcutAction === "clock-out") {
|
|
return {
|
|
action: shortcutAction,
|
|
title: queryParam(parsed.queryParams?.title),
|
|
clientId: queryParam(parsed.queryParams?.clientId),
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export const SHORTCUT_URLS = {
|
|
timer: "beenvoice://timer",
|
|
clockIn: "beenvoice://shortcuts/clock-in",
|
|
clockOut: "beenvoice://shortcuts/clock-out",
|
|
} as const;
|