Fix Live Activity lock screen rendering and polish multi-account auth.

Flatten widget layouts and use system colors so banner and expanded regions render on vibrant lock screens; migrate auth sessions per account to prevent double sign-in; scope app lock PIN to accounts; default clock description to "Clock In"; add architecture docs and deferred form validation on auth screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-18 01:23:36 -04:00
parent e6ea3d7c5d
commit 32ffe782ea
35 changed files with 1659 additions and 442 deletions
+8 -10
View File
@@ -1,12 +1,11 @@
import { requireOptionalNativeModule } from "expo-modules-core";
import { Platform } from "react-native";
import { formatElapsedHoursMinutes, formatElapsedSeconds } from "@/lib/time-clock";
import { formatElapsedHoursMinutes, formatElapsedSeconds, resolveClockDescription } from "@/lib/time-clock";
import type { TimeClockActivityProps } from "@/lib/time-clock-live-activity.types";
import { ensureWidgetBrandAssets, getWidgetBrandAssetUris } from "@/lib/widget-brand-assets";
type RunningEntry = {
description: string;
startedAt: Date | string;
client?: { name: string } | null;
invoice?: { invoicePrefix: string | null; invoiceNumber: string } | null;
};
@@ -55,21 +54,19 @@ export function buildTimeClockActivityProps(
elapsedSeconds: number,
): TimeClockActivityProps {
const invoice = running.invoice;
const brand = getWidgetBrandAssetUris();
return {
startedAtMs: new Date(running.startedAt).getTime(),
elapsed: formatElapsedSeconds(elapsedSeconds),
elapsedShort: formatElapsedHoursMinutes(elapsedSeconds),
clockTime: new Date().toLocaleTimeString(undefined, {
hour: "numeric",
minute: "2-digit",
}),
description: running.description,
description: resolveClockDescription(running.description),
clientName: running.client?.name ?? "",
invoiceLabel: invoice
? `${invoice.invoicePrefix ?? "#"}${invoice.invoiceNumber}`
: "",
markImageUri: brand?.markUri,
logoImageUri: brand?.logoUri,
};
}
@@ -86,7 +83,6 @@ export async function syncTimeClockLiveActivity(
}
try {
await ensureWidgetBrandAssets();
const props = buildTimeClockActivityProps(running, elapsedSeconds);
const instances = factory.getInstances();
@@ -96,8 +92,10 @@ export async function syncTimeClockLiveActivity(
}
factory.start(props, "beenvoice://timer");
} catch {
// Native module can disappear between checks (e.g. hot reload in Expo Go).
} catch (error) {
if (__DEV__) {
console.warn("[LiveActivity] sync failed:", error);
}
factoryCache = undefined;
}
}