115 lines
3.5 KiB
TypeScript
115 lines
3.5 KiB
TypeScript
import { HStack, Image, Text, VStack } from "@expo/ui/swift-ui";
|
|
import {
|
|
frame,
|
|
font,
|
|
foregroundStyle,
|
|
layoutPriority,
|
|
lineLimit,
|
|
minimumScaleFactor,
|
|
monospacedDigit,
|
|
padding,
|
|
widgetAccentedRenderingMode,
|
|
} from "@expo/ui/swift-ui/modifiers";
|
|
import { createLiveActivity, type LiveActivityEnvironment } from "expo-widgets";
|
|
|
|
import type { TimeClockActivityProps } from "@/lib/time-clock-live-activity.types";
|
|
|
|
function TimeClockActivity(props: TimeClockActivityProps, _environment: LiveActivityEnvironment) {
|
|
"widget";
|
|
|
|
const island = "#FFFFFF";
|
|
const businessLabel = props.businessName.trim();
|
|
const clientLabel = props.clientName.trim();
|
|
const title = clientLabel || businessLabel || "Clock In";
|
|
|
|
const timerMods = [
|
|
font({ weight: "bold", size: 17 }),
|
|
foregroundStyle({ type: "hierarchical", style: "primary" }),
|
|
lineLimit(1),
|
|
minimumScaleFactor(0.75),
|
|
layoutPriority(2),
|
|
frame({ width: 100, alignment: "center" }),
|
|
];
|
|
const compactTimerMods = [
|
|
font({ design: "monospaced", weight: "semibold", size: 11 }),
|
|
monospacedDigit(),
|
|
foregroundStyle(island),
|
|
lineLimit(1),
|
|
minimumScaleFactor(0.75),
|
|
frame({ minWidth: 38, alignment: "center" }),
|
|
layoutPriority(2),
|
|
];
|
|
const clientMods = [
|
|
font({ weight: "bold", size: 17 }),
|
|
foregroundStyle({ type: "hierarchical", style: "primary" }),
|
|
lineLimit(1),
|
|
minimumScaleFactor(0.75),
|
|
];
|
|
// Avoid greedy layout primitives here: the live timerInterval Text can
|
|
// collapse when paired with Spacer/maxWidth. Fixed centered boxes keep the
|
|
// content stable without forcing left/right edge alignment.
|
|
const titleRowMods = [
|
|
layoutPriority(1),
|
|
frame({ width: 140, alignment: "center" }),
|
|
];
|
|
const sideZoneMods = [
|
|
frame({ width: 100, alignment: "center" }),
|
|
];
|
|
const bannerRowMods = [
|
|
padding({ horizontal: 10, vertical: 10 }),
|
|
frame({ maxWidth: Infinity, alignment: "center" }),
|
|
];
|
|
|
|
const bannerTimer = <Text modifiers={timerMods}>{props.elapsedShort}</Text>;
|
|
const compactTimer = <Text modifiers={compactTimerMods}>{props.elapsedShort}</Text>;
|
|
const logoLarge = (
|
|
<Image
|
|
assetName="SplashScreenLogo"
|
|
systemName="dollarsign.circle.fill"
|
|
size={22}
|
|
modifiers={[
|
|
foregroundStyle({ type: "hierarchical", style: "primary" }),
|
|
frame({ width: 22, height: 22 }),
|
|
widgetAccentedRenderingMode("fullColor"),
|
|
]}
|
|
/>
|
|
);
|
|
const logoSmall = (
|
|
<Image
|
|
systemName="dollarsign.circle.fill"
|
|
color={island}
|
|
size={14}
|
|
modifiers={[frame({ width: 14, height: 14 }), widgetAccentedRenderingMode("fullColor")]}
|
|
/>
|
|
);
|
|
return {
|
|
banner: (
|
|
<HStack alignment="center" spacing={8} modifiers={bannerRowMods}>
|
|
<VStack alignment="center" modifiers={sideZoneMods}>
|
|
{logoLarge}
|
|
</VStack>
|
|
<VStack alignment="center" spacing={1} modifiers={titleRowMods}>
|
|
<Text modifiers={clientMods}>{title}</Text>
|
|
</VStack>
|
|
{bannerTimer}
|
|
</HStack>
|
|
),
|
|
bannerSmall: (
|
|
<HStack alignment="center" spacing={8} modifiers={bannerRowMods}>
|
|
<VStack alignment="center" modifiers={sideZoneMods}>
|
|
{logoLarge}
|
|
</VStack>
|
|
<VStack alignment="center" spacing={1} modifiers={titleRowMods}>
|
|
<Text modifiers={clientMods}>{title}</Text>
|
|
</VStack>
|
|
{bannerTimer}
|
|
</HStack>
|
|
),
|
|
compactLeading: logoSmall,
|
|
compactTrailing: compactTimer,
|
|
minimal: logoSmall,
|
|
};
|
|
}
|
|
|
|
export default createLiveActivity("TimeClockActivity", TimeClockActivity);
|