From 8a7cf24f901a740454c4b34fef4f6c199223b13c Mon Sep 17 00:00:00 2001 From: Peer Richelsen Date: Fri, 6 Feb 2026 13:32:46 +0100 Subject: [PATCH] feat(companion): add upcoming bookings widget for iOS and Android (#27199) * feat(companion): add upcoming bookings widget for iOS and Android - Add iOS widget using @bacons/apple-targets with SwiftUI - Add Android widget using react-native-android-widget - Configure App Groups for iOS data sharing between app and widget - Create widget sync hook to update widget data when bookings change - Widget displays up to 5 upcoming bookings with title, time, and attendee - Widget refreshes every 15 minutes and when app goes to background Co-Authored-By: peer@cal.com * fix(companion): refactor useWidgetSync to avoid React Compiler limitation Move conditional logic outside of try/catch block to fix React Compiler error: 'Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement' Co-Authored-By: peer@cal.com * fix(companion): fix widget data sync issues - Fix Swift widget to read data as JSON string (format used by react-native-shared-group-preferences) - Add fallback to read as raw Data for compatibility - Fix query key mismatch by checking multiple common filter combinations - Ensure widget finds cached bookings regardless of which filter the app used Co-Authored-By: peer@cal.com * fix(companion): use ExtensionStorage from @bacons/apple-targets for widget data - Replace react-native-shared-group-preferences with ExtensionStorage - ExtensionStorage properly stores data in iOS App Groups - Add ExtensionStorage.reloadWidget() call to trigger widget refresh - This ensures the widget picks up new data immediately Co-Authored-By: peer@cal.com * feat(companion): add upcoming bookings widget for ios - all shapes (#27564) * ios working widget * fix(companion): remove sensitive data logging from widget storage Remove console.log statements that were logging full widgetData payload and formatted widget bookings containing attendee names and booking details. This addresses security concerns identified by Cubic AI review (confidence 9/10). Co-Authored-By: unknown <> * dark mode * new look * fix deeplink * fix biome lint * fix(companion): remove booking titles from console logs to avoid PII exposure Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * lock the versions and dev mode logging * remove dynamic imports * feat(companion): upcoming bookings widget android (#27689) * companion-upcoming-bookings-widget-android * fix(companion): remove stale relative countdowns and fix past-time clamping in Android widget - Remove relative countdown text (In 15m, In 1h, Now) that becomes stale due to Android widget 30+ min update interval (Cubic violation 2) - Remove Math.max(0, minutes) clamping that caused ended meetings to display as 'Now' indefinitely (Cubic violation 1) - Simplify accent color logic to use startTimeISO directly - Keep absolute time display (date + startTime) which remains accurate Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Dhairyashil Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com> Co-authored-by: Volnei Munhoz --- companion/app.json | 41 +- companion/app/(tabs)/(bookings)/_layout.tsx | 6 + companion/app/_layout.tsx | 5 +- companion/bun.lock | 112 ++++- companion/components/WidgetSyncProvider.tsx | 6 + companion/hooks/index.ts | 2 + companion/hooks/useWidgetSync.ts | 155 +++++++ companion/index.js | 5 + companion/package.json | 3 + .../AppIcon.appiconset/App-Icon-20x20@1x.png | Bin 0 -> 583 bytes .../AppIcon.appiconset/App-Icon-20x20@2x.png | Bin 0 -> 1562 bytes .../AppIcon.appiconset/App-Icon-20x20@3x.png | Bin 0 -> 2642 bytes .../AppIcon.appiconset/App-Icon-29x29@1x.png | Bin 0 -> 1028 bytes .../AppIcon.appiconset/App-Icon-29x29@2x.png | Bin 0 -> 2492 bytes .../AppIcon.appiconset/App-Icon-29x29@3x.png | Bin 0 -> 4307 bytes .../AppIcon.appiconset/App-Icon-40x40@1x.png | Bin 0 -> 1562 bytes .../AppIcon.appiconset/App-Icon-40x40@2x.png | Bin 0 -> 3806 bytes .../AppIcon.appiconset/App-Icon-40x40@3x.png | Bin 0 -> 6565 bytes .../AppIcon.appiconset/App-Icon-60x60@2x.png | Bin 0 -> 6565 bytes .../AppIcon.appiconset/App-Icon-60x60@3x.png | Bin 0 -> 10430 bytes .../AppIcon.appiconset/App-Icon-76x76@1x.png | Bin 0 -> 3499 bytes .../AppIcon.appiconset/App-Icon-76x76@2x.png | Bin 0 -> 8492 bytes .../App-Icon-83.5x83.5@2x.png | Bin 0 -> 9469 bytes .../AppIcon.appiconset/Contents.json | 122 +++++ .../AppIcon.appiconset/ItunesArtwork@2x.png | Bin 0 -> 59468 bytes companion/targets/widget/Info.plist | 11 + .../targets/widget/expo-target.config.js | 9 + .../targets/widget/generated.entitlements | 10 + companion/targets/widget/index.swift | 9 + companion/targets/widget/widgets.swift | 431 ++++++++++++++++++ companion/utils/widgetStorage.android.ts | 53 +++ companion/utils/widgetStorage.ios.ts | 54 +++ companion/utils/widgetStorage.shared.ts | 106 +++++ companion/utils/widgetStorage.ts | 26 ++ companion/widgets/UpcomingBookingsWidget.tsx | 246 ++++++++++ companion/widgets/index.ts | 2 + companion/widgets/widgetTaskHandler.tsx | 55 +++ 37 files changed, 1455 insertions(+), 14 deletions(-) create mode 100644 companion/components/WidgetSyncProvider.tsx create mode 100644 companion/hooks/useWidgetSync.ts create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 companion/targets/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png create mode 100644 companion/targets/widget/Info.plist create mode 100644 companion/targets/widget/expo-target.config.js create mode 100644 companion/targets/widget/generated.entitlements create mode 100644 companion/targets/widget/index.swift create mode 100644 companion/targets/widget/widgets.swift create mode 100644 companion/utils/widgetStorage.android.ts create mode 100644 companion/utils/widgetStorage.ios.ts create mode 100644 companion/utils/widgetStorage.shared.ts create mode 100644 companion/utils/widgetStorage.ts create mode 100644 companion/widgets/UpcomingBookingsWidget.tsx create mode 100644 companion/widgets/index.ts create mode 100644 companion/widgets/widgetTaskHandler.tsx diff --git a/companion/app.json b/companion/app.json index 33da374fd2..9cb1e75570 100644 --- a/companion/app.json +++ b/companion/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Calcom", "slug": "calcom-companion", - "scheme": "expo-wxt-app", + "scheme": "calcom", "version": "1.0.3", "orientation": "portrait", "icon": "./assets/icon.png", @@ -15,6 +15,7 @@ }, "ios": { "supportsTablet": false, + "appleTeamId": "ADWKXDJV75", "deploymentTarget": "18.0", "bundleIdentifier": "com.cal.companion", "userInterfaceStyle": "automatic", @@ -22,7 +23,8 @@ "ITSAppUsesNonExemptEncryption": false }, "entitlements": { - "com.apple.developer.default-data-protection": "NSFileProtectionComplete" + "com.apple.developer.default-data-protection": "NSFileProtectionComplete", + "com.apple.security.application-groups": ["group.com.cal.companion"] }, "icon": "./assets/cal-logo.icon" }, @@ -73,13 +75,40 @@ } }, "timePicker": { - "background": { "light": "#ffffff" }, - "numbersBackgroundColor": { "light": "#ffffff" }, - "headerBackground": { "light": "#000000" }, - "numbersSelectorColor": { "light": "#000000" } + "background": { + "light": "#ffffff" + }, + "numbersBackgroundColor": { + "light": "#ffffff" + }, + "headerBackground": { + "light": "#000000" + }, + "numbersSelectorColor": { + "light": "#000000" + } } } } + ], + "@bacons/apple-targets", + [ + "react-native-android-widget", + { + "widgets": [ + { + "name": "UpcomingBookingsWidget", + "label": "Upcoming Bookings", + "minWidth": "180dp", + "minHeight": "110dp", + "description": "View your upcoming Cal.com bookings", + "previewImage": "./assets/icon.png", + "resizeMode": "horizontal|vertical", + "targetCellWidth": 3, + "targetCellHeight": 2 + } + ] + } ] ], "experiments": { diff --git a/companion/app/(tabs)/(bookings)/_layout.tsx b/companion/app/(tabs)/(bookings)/_layout.tsx index 972e613628..47b53ec36e 100644 --- a/companion/app/(tabs)/(bookings)/_layout.tsx +++ b/companion/app/(tabs)/(bookings)/_layout.tsx @@ -1,6 +1,12 @@ import { Stack } from "expo-router"; import { Platform } from "react-native"; +// Define initial route for deep linking +// This ensures booking-detail has index as parent in the stack +export const unstable_settings = { + initialRouteName: "index", +}; + export default function BookingsLayout() { return ( diff --git a/companion/app/_layout.tsx b/companion/app/_layout.tsx index 5de4af4865..3bbee33423 100644 --- a/companion/app/_layout.tsx +++ b/companion/app/_layout.tsx @@ -10,6 +10,7 @@ import { CalComLogo } from "@/components/CalComLogo"; import LoginScreenComponent from "@/components/LoginScreen"; import { NetworkStatusBanner } from "@/components/NetworkStatusBanner"; import { GlobalToast } from "@/components/ui/GlobalToast"; +import { WidgetSyncProvider } from "@/components/WidgetSyncProvider"; import { getColors, colors as semanticColors } from "@/constants/colors"; import { AuthProvider, useAuth } from "@/contexts/AuthContext"; import { QueryProvider } from "@/contexts/QueryContext"; @@ -454,7 +455,9 @@ export default function RootLayout() { - + + + diff --git a/companion/bun.lock b/companion/bun.lock index 859c330275..b4bb2fba63 100644 --- a/companion/bun.lock +++ b/companion/bun.lock @@ -4,6 +4,7 @@ "": { "name": "cal-companion", "dependencies": { + "@bacons/apple-targets": "^3.0.7", "@expo/ui": "0.2.0-canary-20251230-fc48ddc", "@expo/vector-icons": "15.0.3", "@react-native-async-storage/async-storage": "2.2.0", @@ -40,6 +41,7 @@ "react": "19.2.4", "react-dom": "19.2.4", "react-native": "0.83.1", + "react-native-android-widget": "^0.20.1", "react-native-gesture-handler": "2.28.0", "react-native-reanimated": "4.2.0", "react-native-safe-area-context": "5.6.2", @@ -268,6 +270,10 @@ "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + "@bacons/apple-targets": ["@bacons/apple-targets@3.0.7", "", { "dependencies": { "@bacons/xcode": "1.0.0-alpha.27", "@react-native/normalize-colors": "^0.79.2", "debug": "^4.3.4", "glob": "^10.4.2" } }, "sha512-RpzofKGvll8BPrvgf1Xj5raoHffJRW2qfWl7Q9F/25eo6lZeRa9R5NRIZCpUYoVnsL7whCQV9NIp0/ai4O+Ejw=="], + + "@bacons/xcode": ["@bacons/xcode@1.0.0-alpha.27", "", { "dependencies": { "@expo/plist": "^0.0.18", "debug": "^4.3.4", "uuid": "^8.3.2" } }, "sha512-WlemTiwpwwVH8IMvg4VBsyxGUuFWUfzeWKzxhU+dRxd8MHvnX7F9PlWCf7T0ZXmtjbl39iEgQB+/Tf3wuGJbyg=="], + "@biomejs/biome": ["@biomejs/biome@2.3.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.10", "@biomejs/cli-darwin-x64": "2.3.10", "@biomejs/cli-linux-arm64": "2.3.10", "@biomejs/cli-linux-arm64-musl": "2.3.10", "@biomejs/cli-linux-x64": "2.3.10", "@biomejs/cli-linux-x64-musl": "2.3.10", "@biomejs/cli-win32-arm64": "2.3.10", "@biomejs/cli-win32-x64": "2.3.10" }, "bin": { "biome": "bin/biome" } }, "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ=="], "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w=="], @@ -404,7 +410,7 @@ "@expo/package-manager": ["@expo/package-manager@1.9.10-canary-20251230-fc48ddc", "", { "dependencies": { "@expo/json-file": "10.0.9-canary-20251230-fc48ddc", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-Yy74eMzqJKlk1H3B7w1geOyXOz15aOvjgUeRdgBikMj9lgBA6iPGER+cRObGiI5e2nE5eZYQxFOecV0kJawntg=="], - "@expo/plist": ["@expo/plist@0.4.9-canary-20251230-fc48ddc", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-I/x0ULbAtHRHgfW5oZ+rx5+qe9/Y6vA7yQZYZ3ip9e31g1kxpwxhcmHDhFBS62jJLrZ/PWIJ5N5LWQOlL66uYw=="], + "@expo/plist": ["@expo/plist@0.0.18", "", { "dependencies": { "@xmldom/xmldom": "~0.7.0", "base64-js": "^1.2.3", "xmlbuilder": "^14.0.0" } }, "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w=="], "@expo/prebuild-config": ["@expo/prebuild-config@54.0.9-canary-20251230-fc48ddc", "", { "dependencies": { "@expo/config": "12.0.14-canary-20251230-fc48ddc", "@expo/config-plugins": "54.0.5-canary-20251230-fc48ddc", "@expo/config-types": "55.0.0-canary-20251230-fc48ddc", "@expo/image-utils": "0.8.9-canary-20251230-fc48ddc", "@expo/json-file": "10.0.9-canary-20251230-fc48ddc", "@react-native/normalize-colors": "0.83.1", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "55.0.0-canary-20251230-fc48ddc" } }, "sha512-fQTz858QMQqlx7v9rf75FOS+nJJ5EgFIVJVFfn4TVPYi9wPlLtOieEKVh3RK8ZKg9VTt81kp/dFpgcLS12AiGA=="], @@ -446,6 +452,8 @@ "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], @@ -484,6 +492,8 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@pnpm/config.env-replace": ["@pnpm/config.env-replace@1.1.0", "", {}, "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w=="], "@pnpm/network.ca-file": ["@pnpm/network.ca-file@1.0.2", "", { "dependencies": { "graceful-fs": "4.2.10" } }, "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA=="], @@ -576,7 +586,7 @@ "@react-native/js-polyfills": ["@react-native/js-polyfills@0.83.1", "", {}, "sha512-qgPpdWn/c5laA+3WoJ6Fak8uOm7CG50nBsLlPsF8kbT7rUHIVB9WaP6+GPsoKV/H15koW7jKuLRoNVT7c3Ht3w=="], - "@react-native/normalize-colors": ["@react-native/normalize-colors@0.83.1", "", {}, "sha512-84feABbmeWo1kg81726UOlMKAhcQyFXYz2SjRKYkS78QmfhVDhJ2o/ps1VjhFfBz0i/scDwT1XNv9GwmRIghkg=="], + "@react-native/normalize-colors": ["@react-native/normalize-colors@0.79.7", "", {}, "sha512-RrvewhdanEWhlyrHNWGXGZCc6MY0JGpNgRzA8y6OomDz0JmlnlIsbBHbNpPnIrt9Jh2KaV10KTscD1Ry8xU9gQ=="], "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.83.1", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-MdmoAbQUTOdicCocm5XAFDJWsswxk7hxa6ALnm6Y88p01HFML0W593hAn6qOt9q6IM1KbAcebtH6oOd4gcQy8w=="], @@ -744,7 +754,7 @@ "@wxt-dev/storage": ["@wxt-dev/storage@1.2.6", "", { "dependencies": { "@wxt-dev/browser": "^0.1.4", "async-mutex": "^0.5.0", "dequal": "^2.0.3" } }, "sha512-f6AknnpJvhNHW4s0WqwSGCuZAj0fjP3EVNPBO5kB30pY+3Zt/nqZGqJN6FgBLCSkYjPJ8VL1hNX5LMVmvxQoDw=="], - "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + "@xmldom/xmldom": ["@xmldom/xmldom@0.7.13", "", {}, "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g=="], "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], @@ -1014,6 +1024,8 @@ "dotenv-expand": ["dotenv-expand@12.0.3", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA=="], + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="], @@ -1192,6 +1204,8 @@ "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + "form-data-encoder": ["form-data-encoder@4.1.0", "", {}, "sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw=="], "formdata-node": ["formdata-node@6.0.3", "", {}, "sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg=="], @@ -1228,7 +1242,7 @@ "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], - "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -1356,6 +1370,8 @@ "istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="], + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + "jest-environment-node": ["jest-environment-node@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw=="], "jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="], @@ -1624,6 +1640,8 @@ "package-json": ["package-json@10.0.1", "", { "dependencies": { "ky": "^1.2.0", "registry-auth-token": "^5.0.2", "registry-url": "^6.0.1", "semver": "^7.6.0" } }, "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], @@ -1642,7 +1660,7 @@ "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -1744,6 +1762,8 @@ "react-native": ["react-native@0.83.1", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.1", "@react-native/codegen": "0.83.1", "@react-native/community-cli-plugin": "0.83.1", "@react-native/gradle-plugin": "0.83.1", "@react-native/js-polyfills": "0.83.1", "@react-native/normalize-colors": "0.83.1", "@react-native/virtualized-lists": "0.83.1", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "hermes-compiler": "0.14.0", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-mL1q5HPq5cWseVhWRLl+Fwvi5z1UO+3vGOpjr+sHFwcUletPRZ5Kv+d0tUfqHmvi73/53NjlQqX1Pyn4GguUfA=="], + "react-native-android-widget": ["react-native-android-widget@0.20.1", "", { "peerDependencies": { "expo": ">=54.0.0", "react": "*", "react-native": "*" }, "optionalPeers": ["expo"] }, "sha512-m3akQCyoG6XUH8OLHOyL3/Xxx/XXTXf9ZyFYmWvSQrv1YUaZ7kVjmeLIYnaNz+qQ9VrTAS9OygCxZQptqCGzjQ=="], + "react-native-css-interop": ["react-native-css-interop@0.2.1", "", { "dependencies": { "@babel/helper-module-imports": "^7.22.15", "@babel/traverse": "^7.23.0", "@babel/types": "^7.23.0", "debug": "^4.3.7", "lightningcss": "~1.27.0", "semver": "^7.6.3" }, "peerDependencies": { "react": ">=18", "react-native": "*", "react-native-reanimated": ">=3.6.2", "tailwindcss": "~3" } }, "sha512-B88f5rIymJXmy1sNC/MhTkb3xxBej1KkuAt7TiT9iM7oXz3RM8Bn+7GUrfR02TvSgKm4cg2XiSuLEKYfKwNsjA=="], "react-native-gesture-handler": ["react-native-gesture-handler@2.28.0", "", { "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A=="], @@ -1910,10 +1930,14 @@ "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-bom": ["strip-bom@5.0.0", "", {}, "sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A=="], "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], @@ -2094,6 +2118,8 @@ "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="], @@ -2110,7 +2136,7 @@ "xml2js": ["xml2js@0.6.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w=="], - "xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + "xmlbuilder": ["xmlbuilder@14.0.0", "", {}, "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], @@ -2154,6 +2180,8 @@ "@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="], + "@expo/cli/@expo/plist": ["@expo/plist@0.4.9-canary-20251230-fc48ddc", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-I/x0ULbAtHRHgfW5oZ+rx5+qe9/Y6vA7yQZYZ3ip9e31g1kxpwxhcmHDhFBS62jJLrZ/PWIJ5N5LWQOlL66uYw=="], + "@expo/cli/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], "@expo/cli/glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], @@ -2176,6 +2204,8 @@ "@expo/config/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "@expo/config-plugins/@expo/plist": ["@expo/plist@0.4.9-canary-20251230-fc48ddc", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-I/x0ULbAtHRHgfW5oZ+rx5+qe9/Y6vA7yQZYZ3ip9e31g1kxpwxhcmHDhFBS62jJLrZ/PWIJ5N5LWQOlL66uYw=="], + "@expo/config-plugins/glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], "@expo/config-plugins/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], @@ -2212,12 +2242,18 @@ "@expo/package-manager/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="], + "@expo/prebuild-config/@react-native/normalize-colors": ["@react-native/normalize-colors@0.83.1", "", {}, "sha512-84feABbmeWo1kg81726UOlMKAhcQyFXYz2SjRKYkS78QmfhVDhJ2o/ps1VjhFfBz0i/scDwT1XNv9GwmRIghkg=="], + "@expo/prebuild-config/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "@expo/router-server/expo-font": ["expo-font@14.1.0-canary-20251230-fc48ddc", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "55.0.0-canary-20251230-fc48ddc", "react": "*", "react-native": "*" } }, "sha512-OQdE9hB4y1N/Aub5S9c8GOlWGaxB6FIIbwxiCg74yMr5c61QlV9RN7a5QAWdIB8ghHlJMZ8HDH/R6taR5AOA2g=="], "@expo/xcpretty/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="], + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], "@istanbuljs/load-nyc-config/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], @@ -2248,6 +2284,8 @@ "@react-native/babel-preset/@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ=="], + "@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "@react-native/codegen/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="], "@react-native/community-cli-plugin/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], @@ -2356,6 +2394,8 @@ "fx-runner/which": ["which@1.2.4", "", { "dependencies": { "is-absolute": "^0.1.7", "isexe": "^1.1.1" }, "bin": { "which": "./bin/which" } }, "sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA=="], + "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "global-directory/ini": ["ini@4.1.1", "", {}, "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g=="], "global-dirs/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], @@ -2436,7 +2476,11 @@ "parse-json/type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="], - "path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + + "plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], "postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], @@ -2452,10 +2496,14 @@ "rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], + "react-native/@react-native/normalize-colors": ["@react-native/normalize-colors@0.83.1", "", {}, "sha512-84feABbmeWo1kg81726UOlMKAhcQyFXYz2SjRKYkS78QmfhVDhJ2o/ps1VjhFfBz0i/scDwT1XNv9GwmRIghkg=="], + "react-native/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.32.0", "", { "dependencies": { "hermes-parser": "0.32.0" } }, "sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg=="], "react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + "react-native/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "react-native/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "react-native-css-interop/lightningcss": ["lightningcss@1.27.0", "", { "dependencies": { "detect-libc": "^1.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.27.0", "lightningcss-darwin-x64": "1.27.0", "lightningcss-freebsd-x64": "1.27.0", "lightningcss-linux-arm-gnueabihf": "1.27.0", "lightningcss-linux-arm64-gnu": "1.27.0", "lightningcss-linux-arm64-musl": "1.27.0", "lightningcss-linux-x64-gnu": "1.27.0", "lightningcss-linux-x64-musl": "1.27.0", "lightningcss-win32-arm64-msvc": "1.27.0", "lightningcss-win32-x64-msvc": "1.27.0" } }, "sha512-8f7aNmS1+etYSLHht0fQApPc2kNO8qGRutifN5rVIc6Xo6ABsEbqOr758UwI7ALVbTt4x1fllKt0PYgzD9S3yQ=="], @@ -2476,6 +2524,8 @@ "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "serve-static/send": ["send@0.19.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="], @@ -2492,6 +2542,10 @@ "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], @@ -2506,6 +2560,8 @@ "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "unimport/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -2532,6 +2588,10 @@ "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "wxt/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], @@ -2554,8 +2614,14 @@ "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + "@expo/cli/@expo/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + + "@expo/cli/@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + "@expo/cli/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "@expo/cli/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "@expo/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], @@ -2570,16 +2636,28 @@ "@expo/cli/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@expo/config-plugins/@expo/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + + "@expo/config-plugins/@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + "@expo/config-plugins/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "@expo/config-plugins/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "@expo/config/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "@expo/config/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "@expo/fingerprint/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "@expo/fingerprint/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@expo/metro-config/glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "@expo/metro-config/glob/path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + "@expo/metro-config/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], "@expo/metro-config/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -2594,6 +2672,10 @@ "@expo/package-manager/ora/strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="], + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], @@ -2604,6 +2686,8 @@ "@jest/types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="], @@ -2656,6 +2740,8 @@ "fx-runner/which/isexe": ["isexe@1.1.2", "", {}, "sha512-d2eJzK691yZwPHcv1LbeAOa91yMJ9QmfTgSO1oXB65ezVhXQsxBac2vEB4bMVms9cGzaA99n6V2viHMq82VLDw=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "jest-environment-node/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "jest-haste-map/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], @@ -2710,6 +2796,8 @@ "terminal-link/ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "wxt/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -2720,6 +2808,8 @@ "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "@expo/cli/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "@expo/cli/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "@expo/cli/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -2732,6 +2822,14 @@ "@expo/cli/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@expo/config-plugins/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + + "@expo/config/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + + "@expo/fingerprint/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + + "@expo/metro-config/glob/path-scurry/lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "@expo/package-manager/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "@expo/package-manager/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], diff --git a/companion/components/WidgetSyncProvider.tsx b/companion/components/WidgetSyncProvider.tsx new file mode 100644 index 0000000000..864ccb4ede --- /dev/null +++ b/companion/components/WidgetSyncProvider.tsx @@ -0,0 +1,6 @@ +import { useWidgetSync } from "@/hooks/useWidgetSync"; + +export function WidgetSyncProvider({ children }: { children: React.ReactNode }) { + useWidgetSync(); + return <>{children}; +} diff --git a/companion/hooks/index.ts b/companion/hooks/index.ts index 25657f8d65..f40491509b 100644 --- a/companion/hooks/index.ts +++ b/companion/hooks/index.ts @@ -75,3 +75,5 @@ export { useUsername, useUserProfile, } from "./useUserProfile"; +// Widget sync hook +export { useWidgetSync } from "./useWidgetSync"; diff --git a/companion/hooks/useWidgetSync.ts b/companion/hooks/useWidgetSync.ts new file mode 100644 index 0000000000..c7747dc393 --- /dev/null +++ b/companion/hooks/useWidgetSync.ts @@ -0,0 +1,155 @@ +import { useEffect, useCallback } from "react"; +import { Platform } from "react-native"; +import { useQueryClient } from "@tanstack/react-query"; +import { queryKeys } from "@/config/cache.config"; +import { CalComAPIService, type Booking } from "@/services/calcom"; +import { + updateWidgetBookings, + clearWidgetBookings, + setupWidgetRefreshOnAppStateChange, +} from "@/utils/widgetStorage"; + +export function useWidgetSync() { + const queryClient = useQueryClient(); + + const syncBookingsToWidget = useCallback(async () => { + if (__DEV__) { + console.log("[Widget Debug] syncBookingsToWidget called, Platform:", Platform.OS); + } + + if (Platform.OS === "web") { + if (__DEV__) { + console.log("[Widget Debug] Skipping - web platform"); + } + return; + } + + // Try to get cached bookings from any of the common query keys used in the app + // The app uses different filter combinations, so we check multiple keys + const possibleFilters = [ + { status: ["upcoming"], limit: 50 }, + { status: ["upcoming"] }, + { status: ["upcoming", "unconfirmed"] }, + {}, + ]; + + let cachedBookings: Booking[] | undefined; + for (const filters of possibleFilters) { + const cached = queryClient.getQueryData(queryKeys.bookings.list(filters)); + if (__DEV__) { + console.log( + "[Widget Debug] Checking cache for filters:", + JSON.stringify(filters), + "found:", + cached?.length ?? 0 + ); + } + if (cached !== undefined && cached.length > 0) { + cachedBookings = cached; + break; + } + } + + if (cachedBookings !== undefined && cachedBookings.length > 0) { + if (__DEV__) { + console.log("[Widget Debug] Using cached bookings, count:", cachedBookings.length); + console.log("[Widget Debug] Current time (UTC):", new Date().toISOString()); + } + + // Log each booking's times for debugging - check both property name formats + if (__DEV__) { + cachedBookings.slice(0, 3).forEach((booking, i) => { + console.log( + `[Widget Debug] Booking ${i}: startTime=${booking.startTime}, start=${booking.start}, endTime=${booking.endTime}, end=${booking.end}` + ); + }); + } + + try { + // Filter bookings that haven't ended yet (includes ongoing meetings) + // Sort by start time to show soonest first + // Note: API may return either start/end or startTime/endTime + const upcomingBookings = cachedBookings + .filter((booking) => { + const endTimeStr = booking.endTime || booking.end; + if (!endTimeStr) { + if (__DEV__) { + console.log(`[Widget Debug] Booking ${booking.id}: No end time found, skipping`); + } + return false; + } + const endTime = new Date(endTimeStr); + const isUpcoming = endTime > new Date(); + if (__DEV__) { + console.log( + `[Widget Debug] Booking ${booking.id}: endTime=${endTime.toISOString()}, isUpcoming=${isUpcoming}` + ); + } + return isUpcoming; + }) + .sort((a, b) => { + const aStart = new Date(a.startTime || a.start || "").getTime(); + const bStart = new Date(b.startTime || b.start || "").getTime(); + return aStart - bStart; + }); + + if (__DEV__) { + console.log("[Widget Debug] Filtered upcoming bookings, count:", upcomingBookings.length); + } + await updateWidgetBookings(upcomingBookings); + } catch (error) { + console.warn("Failed to sync cached bookings to widget:", error); + } + } else { + // No cached data found, fetch from API + if (__DEV__) { + console.log("[Widget Debug] No cached data, fetching from API..."); + } + try { + const bookings = await CalComAPIService.getBookings({ + status: ["upcoming"], + limit: 10, + }); + + if (__DEV__) { + console.log("[Widget Debug] API returned bookings, count:", bookings.length); + } + + // Filter bookings that haven't ended yet (includes ongoing meetings) + const upcomingBookings = bookings + .filter((booking) => { + const endTime = new Date(booking.endTime); + return endTime > new Date(); + }) + .sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime()); + + if (__DEV__) { + console.log( + "[Widget Debug] Filtered upcoming bookings from API, count:", + upcomingBookings.length + ); + } + await updateWidgetBookings(upcomingBookings); + } catch (error) { + console.warn("Failed to fetch and sync bookings to widget:", error); + } + } + }, [queryClient]); + + useEffect(() => { + if (Platform.OS === "web") { + return; + } + + syncBookingsToWidget(); + + const cleanup = setupWidgetRefreshOnAppStateChange(syncBookingsToWidget); + + return cleanup; + }, [syncBookingsToWidget]); + + return { + syncBookingsToWidget, + clearWidgetBookings, + }; +} diff --git a/companion/index.js b/companion/index.js index 80d3d998f1..a84621eb20 100644 --- a/companion/index.js +++ b/companion/index.js @@ -1 +1,6 @@ +import { registerWidgetTaskHandler } from "react-native-android-widget"; +import { widgetTaskHandler } from "./widgets/widgetTaskHandler"; + +registerWidgetTaskHandler(widgetTaskHandler); + import "expo-router/entry"; diff --git a/companion/package.json b/companion/package.json index ad07557749..8277dbe773 100644 --- a/companion/package.json +++ b/companion/package.json @@ -8,6 +8,7 @@ "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", + "prewidget": "EXPO_NO_GIT_STATUS=1 npx expo prebuild --template ./node_modules/@bacons/apple-targets/prebuild-blank.tgz --clean", "typecheck": "tsc -p tsconfig.json --noEmit", "typecheck:extension": "tsc -p tsconfig.extension.json --noEmit", "typecheck:all": "npm run typecheck && npm run typecheck:extension", @@ -49,6 +50,7 @@ "check:ci": "biome ci ." }, "dependencies": { + "@bacons/apple-targets": "^3.0.7", "@expo/ui": "0.2.0-canary-20251230-fc48ddc", "@expo/vector-icons": "15.0.3", "@react-native-async-storage/async-storage": "2.2.0", @@ -85,6 +87,7 @@ "react": "19.2.4", "react-dom": "19.2.4", "react-native": "0.83.1", + "react-native-android-widget": "^0.20.1", "react-native-gesture-handler": "2.28.0", "react-native-reanimated": "4.2.0", "react-native-safe-area-context": "5.6.2", diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..ae598628b0774b0580f942bef18725214c910cc2 GIT binary patch literal 583 zcmV-N0=WH&P)Th01*MOZ5#eb_-%~C-CL_75{s%vMDJrxt+n8XL=ww=v-eSJiHI={cNY-= z5uvI%ZzA$~ednCkW&`#oAK&*$Uy`rh{k7R55gQEMT2 zU9+{Ks`x=wTPxQ!N!D7%IItv=5peg27~^cMxH|xMKhFuozGqc+_nf!hk5aO`-#0~| zW;W++tGw@lHM7?0oOf$=&S_?fMMT`)OaZuiM3k~)DP@lc zcL!jm?k*x&G(JQmmh+rB=lEgY^Lbve0EiF8zlh-fQ2B@mS@wN9&r5zd&uibaECA#~ zu|$NKkp!TsB61ujmg6`@L{$NhG_#1nq9nI%>wTnTy&ojqJtZ^K_j~j{%rqr)capsy zDOvAh+cuKP%mB=(BGOv9u9@>@OG+ssR29p0&DKgpsA@_EK(W+X#yHF@=dJgHBz_>- z`;qfzW@8++7A%P*mYnnJ^<8TzC12Mh4?utbU}mM{hW|a literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ff9d54105a61b538281bd51e5fbfce5148dc24ba GIT binary patch literal 1562 zcmV+#2IcvQP)yp|?5(dyOt1=6O?#AnR|Hm7zF+xZPt1h|jiXj#S(cbp_*g1#hdBN7YdglaN>*}2o zJV|eq+2YB%dglaN>*}2oY#IDR7{5tX{hJtLP*r9Tu_8i5_#KRoi7^htEu}<6@`jmr zs)>l!)z9-yRgE#bodX0P!1!Oh_v1Jbp>11h4Ia`PWwyKB4q1%pav5*8d(%`Rf?s01 zPgRFuG=@HX>bwuu8vK&Arm9L29>;4+x2|i52=Cx^_1Fp_0EjV;<5brrGkYI?!e8{q zk2S`alKy0^vDWT(4j=#_1OP=*gb==dJvB{btqmdI1v@8rL4n}k23x8+j@RR{$HO>I z%X07g_HZchONT?z_wBOW$8o~L@z{^!q^j65*cyhht}7x!HVhXLZrcVQ*0zlZ55ol+ z5!H1$3?sG-o_Oz#A!bH4j+1k)DE9bGMX`6zjpKxjnT;XuJ)Rgm8ONzX9`~J&qHe@Va_rF-9WtKKumWe7^L3yRIHt2mufG`+ZsN#u&|tV*eAe z5CR?!hvIy`^nDvb06;{`a<|qZW9J0fFx=X;VIl&X>B!oB&m!c^C_~T#c zjWXMLUdHj-buF_6;GE#0stz$mW_C{6wz*!fUDqNrct|N(YmnV;OIaSU6+#?_%kkKk zWq~JUSsai3FkC{2*ec7z?Y1DZ)})m1V34UQ5#cXNM0ha_m*cS~BD^4?$st;Lg+5}jWO0*03ifsw$=hL$V9C70U5JhSC6ft*v<2TUz+EoDE8P|S1%&SybmH4nL#EZ z-g{&svaTLm`~7}d7FESNRCQUF{eF+Fb@k2(GVi^JAT!8_NLBHms(8_L?dfz@RlHEu z)9KuGEncW99#oZxkQqD}V`5Cm%JMKxGq#v**R`k9d7c+MndjwnI(J>mY_T;>b6Fmc z#h8pSc;I#Q$acHk^J3cyLaTIVVk1r#H%MvE`f~ zJD)Fo--$2)5mwcr*yF+ANz+v0cts|{B0SGG{4Mi*6JZfXHjdY(sqn<$iHM}6Ap~Sq zRmK>n>4x7lO}7|hRh7s>2q~$E;EBOj*EQGcq^ii8rUvwUz5t33(ewENXw%flRP}nD zyRN~O!4?rUO?^6@@laJ|U6;c!UazyN;vK4bz0Sih)^%A`B_2+vbJJ8rge}GkYi--s z-@bi69(y7Jz|39Os_OZC0aP+$C?yRc_za-3JnVLknUSgL>2z+}S{1K&T|Kr!2+UlT zhp%5xbzL$ufDi&RS5*lhgz)3XkCc)stTiIC+wG8r5RiosuGhI~DpiCK@PeHayl_qc z+3$D5FnaHsrUu}gAahQDBE3;&i!Biz$7@RZ<;#(XkU1yVV!V%t`o8tvfB!xZp>11h z4c-@Hnx`{2D-Rbxz1?24km2QWUy zTHAFk09EyGVvIpmnZ-FN%L5SsSXYmaVf-c{a&M5{D6_@iV(<_7510c{2V}S|F#rGn M07*qoM6N<$f|nELNB{r; literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7913561ebaa00410802aed219b9d9f71ea5b36 GIT binary patch literal 2642 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 A1^@s6 literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2b59a92be53d395890bc551929c7db147c38703 GIT binary patch literal 1028 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 Ai~s-t literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f0e2b6213587afa2f359092c6c6f134ce191c14 GIT binary patch literal 4307 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 M07*qoM6N<$f|nELNB{r; literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3b831397fe71276dd0a51778ceef02ff1fa649c9 GIT binary patch literal 3806 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 w=`kO)>S_Q(lIogT58w=N)i}i#wh5Un6Qtq5uE@ literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6cd063f2dc5a41a3332d9e1fd18176095a8a92df GIT binary patch literal 6565 zcmYM33p~^7AIFy*mZNOtGPMdJN--SGJsD*u%F1nSX}LAm++q@P85SpvilI2j7-@~; zF3bGmn94D?voUgZ+zwL6t^cF*f4%;%*UWF*@AvHaJ zWy8cgfb1DJ%_M!u+18Y^$>iT)%=Old?mz#21ojo38Hy&H5V>W)LAyB&Xn)XuEu0xS zNO-B$DXfa{cB#WFW_E;XaTZ6n(Qz9vWS2@u@W$lYyk*Gdit^4oVqMpzF>4nv;_x-GU2Rd zgX~I2r4+@t-|Z$9iL45PGm1Y8BrRZF^s$8#YNeD!rS>y)dfbDuJ*{4hN;;NU!g664 zEPu@oD^v~5Ep^Ea;VzBA*RuQ=PL;ipODmqxRn-tJ&e^2HWIqE}E%{0v z>6+@(*{YmA)%4|LeIn}Y?5v=|1-rUx$?tA7xZPdX_mMtxrsVs@mnbL$#OI(OYl^VHeCbvL z#~5a1KcNv3IIS0ZpUj($WxmY;>pW=aB&!DY<%@vei4k9z{^2aIu?;f!gNTBHNRvXi zF2s!DH*Jd2G0R^+eT~NFHuAX$!dm)jYjvPK6`c-Egq&Xz9I%IpuXPx%Zkn)o1qFL^ zaDLVpNTSl&dvtm?ju<#I60?v7?L`o1%Q~{yw`fOu*=J8y&7fkN`ASeO*X|XsuTPKh zWq8;I43mfo;ev>$9&4u0u5ZW9n7VsiCt4UW(0wozNm}4nHr6>fC|+SW=1<)^EN+p z^6p~y1+3u_b2C%hnrbdv=gmoC0n4r%dLE9JCn$AzQYtu;lAN{PUT;JS`WK!L3mWe;{t5H!h=fq3iC&PB_dmtM98e7WRXZe0M0?*J&KZnfN$%pJWY_B%@ zOs~3U&6&ypYt7+>D5h4YphKs*wH29l^q+r@R9Bz=m9l6c29iIcvAS#WymDe?Wrh;; zMSZcx@rMm4^~`~(DVIETkkx2=*?kf%ac%YdAcc&9t*wXDm!pA_ySn0%pkNd*7H2Yb zcJ^luT5xuJZ&gHA))mf>UpQQR*UFW_NTY(_`efXvnHd$3fQLB0c>Cv;TG`u`XOx%Q zWWT|6>&OmS!obaR&d+c0`IA#qih}sbz3LC2tZvWDxRD_nE~lODZbv)i#-QiM{-l5~ zPrZ=6_SavZ<^rCxwwL>wrfwx~LE&!h1*C^uJDKJ%GKQp9h~1Wc>3kDB7y)5l$d8C(mL&FD@dj zgdsy+N8~dG*zB;}(!s$;=b)SVNicBWl51vSqAh=N?%Cih#(r&a@gfEd>q_upTDcF3 zMCCNS*uLwvc^7?JJVX-{R3M+ygt>`{SA(+`)tQ~wlNY=w1w}=?2-EyiAxfE+2!ebD z5VjoMj#aHkm2YqG7NRcMNvx$6(4^P5{<)#+dfI92h-OJ#Ta$AY1%(#xQZ6j?@j|R@ zxI-{QUd&-L^S+oCE|}}3VDwy6Q-Me{?8EF_{k*}~kuEAM0~ZK*vu?yYF-F%YUdI`| zlapbUIbiU`47BOtSNP${NhVLi7{#%>B#F=eV$>x-uUKN3!zMi+RMTo7hW#TH+I0WD zxhdX8U0yz*S(2K1T!f6oW}|yP3Zy|w3=-Hxo6Ak{(pdaa$}%+4;P>V0 ztdVQw8tHgOK&|tB_)2?i>KCJW9=O@L8;tymKJ$^e-kNbPF1dB1!#8x9Jg@TCPl*iI zny@(ws(0Fgi&ieqn%nSFYst#pRi(p8K0^-f?Sju$i+ss56e+ST$Y(J;ya)+dQQS8{ zt0B6APr6@*?=0e_n3jF5AzW8t&&xMXzf$Bgyk+;qW{uM(e^hC{CVlr`Oz%W>r8lg$m%CXPZ~oj&mDe z7RWA_Tqt~8Zs*M4=u4D@uuN_8Vj?Q`ewZ2Jb6J0MwrZ%>QaThupy;KvMKl$Zm#3j} za8eM$+M(~GLp9YR@mh{vh)APTn+M?JX6pW$!XjUs^;Vn$$%|%Os+t#AKXt3&MEd@C zs(sVp^Y*Hk@s@g?wf&9ng_-FQ%$tqKR^U>i)33M4pfClbq6AT_Z!qS9pJ* z>BaOJ1^>M9A4PxqFx?rv$t41^^5Me--2PxTLgJoaYwL1@pMrqIHO$*H zM-?Tn{&BN($iLRvM$y|PyDSN$2$(Ra71eKOJt=w_MEUzPos>++^&88e0d$q|@t1C+6nFg9(hLw!8Xe z2ls8Xc%-6Ic9;5Rt1f}8?3MSf(AMrthAv9*gGAH*IEM(?WItHSGn{T;{d{DK53-m1 zT%%j-=i2_8tbJmFAm7{f8tdxoS9v3|vl-v(v^|2b6}P&+{sB)Skvs?GgWm=DTC_V= z{scnll?GPjoL;7ncSXyp|G~*IofHMkP(U5Sk%M5@Rz-js0jaJzkJW5`g8Q@{BR>Am zKdCMBI`NPdJo7r^RC;m0|D?9qvf}35IwGxn2I)sVwyOmV*Cus+wRXW;) zU{h#%`o~ltv@m2Q83H6^_Z~PzsRIr?I{C$J5d~_S#5*|l)F~p6#q+!DAQw-kE3%(a zDt0*&Sv>SFEH1vB#Yw1QL8=(w^<{?vNEHiD)PGL=8G|Qs5UsC6O;W~I)Tub2Vkl0> zWsTBz?Iban)ia!wBmt5H!)hX*({FNamdftC!Pu>Yc~0#}ATO#&C*!2{QYsJxtme)j z@8eN_nLY!;AHRAel|b3`f+yVVG7Hg3Id*$tNzqboAq}N3Tst$Dvw8%0MQ}4{DN!^1 zMC?;K9S!U#l4~d#kD42A@uh%B2u2?iw-~3f?Iszp@_acGy?3=H&7W zMTzkxyUy=c79$>xoS+Rv+%M5kyI%oJJdA5dprakpSocw-@u9bd$CJ+P&XhO@C7uH3 zIXT=f`PE;mccNekKEj9Fm=cm6Iajt^Yh^phu zbFT7(4xO){kC1Ap7(F6C1B5$>9x5C{IH9kUh|5Mf<{mt6la0Qh~*HK7M>Rfezw5iV4g>g`J%QFx*re z7KD<2AX?;wCJ{%csPDr8z>-q4(Nb_Zt0!fs z$PXhI6j2;7I~Qc-%Rh!RdvFU|k*?#;Y%kC5zqhw5s!zo|Z>$5-gR^FP9qk$k`f=e- zZs|~kRs`}SP>fvF+AuESo)69%XPs}G354vlcAw%TkhzG!rF(y{TAE1LD4rgLdYq7| zUiC-1*}CWS2$ZnXHrK($@?Gg+t^C}f3VzU3w2;QG{q9^Le+n{L2Dd@aFh7rI9~c0B zI&+HF1B5=vt9-uhBdx1;M_?(ns%gL-7L3eGw}VYOl=SSk)>hebe+mSBqMubd?8$y+ zo&w0UFDkx;0Om{n9w(&m6wReW~@@PRuxz+pq7=FaQPq8z!mE%6{l(>GIc?{r;ic zC4=uh$b6mi>A{C@!*!q7C~B&eXzW*66u1)8{sYuFhsSv=bvFCW@#FVY)0RLMik7`A zbFA#i1&)=rd1bV)IaLa3Epf-IjFDkozy>%~-p9dPaf3g>LxUDi^nB=5FR~LA*!?)B z)bS%{@lj(PH=41RuqF@pfWoCyO^Kt?9#roJ50QYhc|hbwe##H>c2U6qG+~*fKoPp~ zjED@BgeOe+17XeFvGV@v=^h+G+QU%9h`=A>ES_OhHdd2b>Ua|WcQ^~C+i6hGhq~#- zAq{T8#V^XmOto}XDvcM|ks929q46f)wM=Sz_f3@cE(xlQ_MML$2`Y#D>*;9J>^muK z(F;p*DzO=6_g0U9HLFp)qWx$#sQ$3{pQJ1&0V$qr0^hE4t1i}{>Z*K#kQeX5gxV^Z zgxE_pgLh)`#4TV}@YZX;@35MsWZccBQ-iac>+9L5xoa1vXc?1;)JpogRh~N9&D|9e ziX@c3y#copzI_{yO3|*0z{qx?TA$OqAJ5Fqse&7dxh#Lh5${Asb|Bbx;1K#g$aiRW*AWB(L=N+9CB4Hgvil6z}?dMTSzMF zPlkcYM=(cjcv1FBY?+M7Tcs5s2nq_mH0ILUds3EX(rTPZ+((+b8x6&I0jyed>tX42 z3TiHu5Ii4QMvaXtgu^5EtNhk%QbQ!&{f5D;O~c;yq~kycm->Rh7**WIvO*Kk!-BBAoSF;n!G~L4X5bspIG*>dV2| z-$g$YPQ+e9R)X;uU-*2mbLMIbpzFNH1CG-qQ?9k^@l7+&72qe-_Pq{$`ueFtig0pL z4=yBSs~)+3noGhg@j7bDO`Do`pwujnwa6&I}Yx0g9SUnBzk_fE|aq8;l; z_lTJtF$Yy`OIo4@bnuX@tcL?PCuwZSTijkz#&E!{@%44EyV*xPLkc`r@ean`!^bv4zv} zm0w~&^~zQaV!hP*8Q`E%wCGdwP{5~RjeGG?MhuUdV@c168)6%^y!%};yhbn;9ce}c z7?gmLP-*@}x3RGik#!Wz^Iy0lNP+>80|s?CU~sm#zyIUcCz@&xK?asmKhg;10usa4 zWu{nzWdITsq~@;!SVIx|vio3E)OSC9?mNFZc0my^s6Y9paqHpcJ4_-J%8f4Xp9#nF zMohFlKw}QpT}j$%2Sp`8(K2X}z?fJNww=S|4X_w=diAMzrSZ@z5HFz3Qx1`3e7U{( z#;~omRhkVmPXy4=er9C<1C(4VND+XgK*(OYB#G73XY!0hl#0dsXvfeh2%U~65-xrz z*7~WX!@SnXqMfbt`^&4EidM?)5VWYEa`DnXIVib2e+ED&=fr(|Ef?NCma1uv(xy~| z$btfDPg}-(q_LgsE~U;!Y=72wz=FP+Yq)(sj7wUeSu&NNAM|bd#XVtg2$BDz<}nDs zNDsq~^wPovBoT7^{%V|==gmMoql(W3-?y0jjRJgHI>@H~@$02a{&{b9zy`2To10g= zp<_B_x43FH6t;uImWu5GWOX$IrEYUQmi_pq?h^+GfE?x`N7qtVnPfnS?9l>??~w=J zftCSvO5c^iV5hpOcl7o?2R-OvXtRuF$qobc$@m)EFdP6D$!7ng=!)#r@^V%6EHE;N z&j`ZpqhbpwC>q+ zOpJ~F>-7M0{-wQ^93swfF7L--|N2@-pZOY#D&Xd1yX2PnYn8sqB2b2ddQ8S{2BLla z^MGn`U2;p;Ld3p3Ks(;E==+zwiV5h z$z2NPF!t0k8`)%>wHHE{v-t2|(hAIVtA!vf9BtaUoA=W0F xNq`IMw?hB-0|&D04m5MjOuQ@j=)|{O*3egZE~Sfx;O7^Jjg=jy`rNg|{{o*q*joSq literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6cd063f2dc5a41a3332d9e1fd18176095a8a92df GIT binary patch literal 6565 zcmYM33p~^7AIFy*mZNOtGPMdJN--SGJsD*u%F1nSX}LAm++q@P85SpvilI2j7-@~; zF3bGmn94D?voUgZ+zwL6t^cF*f4%;%*UWF*@AvHaJ zWy8cgfb1DJ%_M!u+18Y^$>iT)%=Old?mz#21ojo38Hy&H5V>W)LAyB&Xn)XuEu0xS zNO-B$DXfa{cB#WFW_E;XaTZ6n(Qz9vWS2@u@W$lYyk*Gdit^4oVqMpzF>4nv;_x-GU2Rd zgX~I2r4+@t-|Z$9iL45PGm1Y8BrRZF^s$8#YNeD!rS>y)dfbDuJ*{4hN;;NU!g664 zEPu@oD^v~5Ep^Ea;VzBA*RuQ=PL;ipODmqxRn-tJ&e^2HWIqE}E%{0v z>6+@(*{YmA)%4|LeIn}Y?5v=|1-rUx$?tA7xZPdX_mMtxrsVs@mnbL$#OI(OYl^VHeCbvL z#~5a1KcNv3IIS0ZpUj($WxmY;>pW=aB&!DY<%@vei4k9z{^2aIu?;f!gNTBHNRvXi zF2s!DH*Jd2G0R^+eT~NFHuAX$!dm)jYjvPK6`c-Egq&Xz9I%IpuXPx%Zkn)o1qFL^ zaDLVpNTSl&dvtm?ju<#I60?v7?L`o1%Q~{yw`fOu*=J8y&7fkN`ASeO*X|XsuTPKh zWq8;I43mfo;ev>$9&4u0u5ZW9n7VsiCt4UW(0wozNm}4nHr6>fC|+SW=1<)^EN+p z^6p~y1+3u_b2C%hnrbdv=gmoC0n4r%dLE9JCn$AzQYtu;lAN{PUT;JS`WK!L3mWe;{t5H!h=fq3iC&PB_dmtM98e7WRXZe0M0?*J&KZnfN$%pJWY_B%@ zOs~3U&6&ypYt7+>D5h4YphKs*wH29l^q+r@R9Bz=m9l6c29iIcvAS#WymDe?Wrh;; zMSZcx@rMm4^~`~(DVIETkkx2=*?kf%ac%YdAcc&9t*wXDm!pA_ySn0%pkNd*7H2Yb zcJ^luT5xuJZ&gHA))mf>UpQQR*UFW_NTY(_`efXvnHd$3fQLB0c>Cv;TG`u`XOx%Q zWWT|6>&OmS!obaR&d+c0`IA#qih}sbz3LC2tZvWDxRD_nE~lODZbv)i#-QiM{-l5~ zPrZ=6_SavZ<^rCxwwL>wrfwx~LE&!h1*C^uJDKJ%GKQp9h~1Wc>3kDB7y)5l$d8C(mL&FD@dj zgdsy+N8~dG*zB;}(!s$;=b)SVNicBWl51vSqAh=N?%Cih#(r&a@gfEd>q_upTDcF3 zMCCNS*uLwvc^7?JJVX-{R3M+ygt>`{SA(+`)tQ~wlNY=w1w}=?2-EyiAxfE+2!ebD z5VjoMj#aHkm2YqG7NRcMNvx$6(4^P5{<)#+dfI92h-OJ#Ta$AY1%(#xQZ6j?@j|R@ zxI-{QUd&-L^S+oCE|}}3VDwy6Q-Me{?8EF_{k*}~kuEAM0~ZK*vu?yYF-F%YUdI`| zlapbUIbiU`47BOtSNP${NhVLi7{#%>B#F=eV$>x-uUKN3!zMi+RMTo7hW#TH+I0WD zxhdX8U0yz*S(2K1T!f6oW}|yP3Zy|w3=-Hxo6Ak{(pdaa$}%+4;P>V0 ztdVQw8tHgOK&|tB_)2?i>KCJW9=O@L8;tymKJ$^e-kNbPF1dB1!#8x9Jg@TCPl*iI zny@(ws(0Fgi&ieqn%nSFYst#pRi(p8K0^-f?Sju$i+ss56e+ST$Y(J;ya)+dQQS8{ zt0B6APr6@*?=0e_n3jF5AzW8t&&xMXzf$Bgyk+;qW{uM(e^hC{CVlr`Oz%W>r8lg$m%CXPZ~oj&mDe z7RWA_Tqt~8Zs*M4=u4D@uuN_8Vj?Q`ewZ2Jb6J0MwrZ%>QaThupy;KvMKl$Zm#3j} za8eM$+M(~GLp9YR@mh{vh)APTn+M?JX6pW$!XjUs^;Vn$$%|%Os+t#AKXt3&MEd@C zs(sVp^Y*Hk@s@g?wf&9ng_-FQ%$tqKR^U>i)33M4pfClbq6AT_Z!qS9pJ* z>BaOJ1^>M9A4PxqFx?rv$t41^^5Me--2PxTLgJoaYwL1@pMrqIHO$*H zM-?Tn{&BN($iLRvM$y|PyDSN$2$(Ra71eKOJt=w_MEUzPos>++^&88e0d$q|@t1C+6nFg9(hLw!8Xe z2ls8Xc%-6Ic9;5Rt1f}8?3MSf(AMrthAv9*gGAH*IEM(?WItHSGn{T;{d{DK53-m1 zT%%j-=i2_8tbJmFAm7{f8tdxoS9v3|vl-v(v^|2b6}P&+{sB)Skvs?GgWm=DTC_V= z{scnll?GPjoL;7ncSXyp|G~*IofHMkP(U5Sk%M5@Rz-js0jaJzkJW5`g8Q@{BR>Am zKdCMBI`NPdJo7r^RC;m0|D?9qvf}35IwGxn2I)sVwyOmV*Cus+wRXW;) zU{h#%`o~ltv@m2Q83H6^_Z~PzsRIr?I{C$J5d~_S#5*|l)F~p6#q+!DAQw-kE3%(a zDt0*&Sv>SFEH1vB#Yw1QL8=(w^<{?vNEHiD)PGL=8G|Qs5UsC6O;W~I)Tub2Vkl0> zWsTBz?Iban)ia!wBmt5H!)hX*({FNamdftC!Pu>Yc~0#}ATO#&C*!2{QYsJxtme)j z@8eN_nLY!;AHRAel|b3`f+yVVG7Hg3Id*$tNzqboAq}N3Tst$Dvw8%0MQ}4{DN!^1 zMC?;K9S!U#l4~d#kD42A@uh%B2u2?iw-~3f?Iszp@_acGy?3=H&7W zMTzkxyUy=c79$>xoS+Rv+%M5kyI%oJJdA5dprakpSocw-@u9bd$CJ+P&XhO@C7uH3 zIXT=f`PE;mccNekKEj9Fm=cm6Iajt^Yh^phu zbFT7(4xO){kC1Ap7(F6C1B5$>9x5C{IH9kUh|5Mf<{mt6la0Qh~*HK7M>Rfezw5iV4g>g`J%QFx*re z7KD<2AX?;wCJ{%csPDr8z>-q4(Nb_Zt0!fs z$PXhI6j2;7I~Qc-%Rh!RdvFU|k*?#;Y%kC5zqhw5s!zo|Z>$5-gR^FP9qk$k`f=e- zZs|~kRs`}SP>fvF+AuESo)69%XPs}G354vlcAw%TkhzG!rF(y{TAE1LD4rgLdYq7| zUiC-1*}CWS2$ZnXHrK($@?Gg+t^C}f3VzU3w2;QG{q9^Le+n{L2Dd@aFh7rI9~c0B zI&+HF1B5=vt9-uhBdx1;M_?(ns%gL-7L3eGw}VYOl=SSk)>hebe+mSBqMubd?8$y+ zo&w0UFDkx;0Om{n9w(&m6wReW~@@PRuxz+pq7=FaQPq8z!mE%6{l(>GIc?{r;ic zC4=uh$b6mi>A{C@!*!q7C~B&eXzW*66u1)8{sYuFhsSv=bvFCW@#FVY)0RLMik7`A zbFA#i1&)=rd1bV)IaLa3Epf-IjFDkozy>%~-p9dPaf3g>LxUDi^nB=5FR~LA*!?)B z)bS%{@lj(PH=41RuqF@pfWoCyO^Kt?9#roJ50QYhc|hbwe##H>c2U6qG+~*fKoPp~ zjED@BgeOe+17XeFvGV@v=^h+G+QU%9h`=A>ES_OhHdd2b>Ua|WcQ^~C+i6hGhq~#- zAq{T8#V^XmOto}XDvcM|ks929q46f)wM=Sz_f3@cE(xlQ_MML$2`Y#D>*;9J>^muK z(F;p*DzO=6_g0U9HLFp)qWx$#sQ$3{pQJ1&0V$qr0^hE4t1i}{>Z*K#kQeX5gxV^Z zgxE_pgLh)`#4TV}@YZX;@35MsWZccBQ-iac>+9L5xoa1vXc?1;)JpogRh~N9&D|9e ziX@c3y#copzI_{yO3|*0z{qx?TA$OqAJ5Fqse&7dxh#Lh5${Asb|Bbx;1K#g$aiRW*AWB(L=N+9CB4Hgvil6z}?dMTSzMF zPlkcYM=(cjcv1FBY?+M7Tcs5s2nq_mH0ILUds3EX(rTPZ+((+b8x6&I0jyed>tX42 z3TiHu5Ii4QMvaXtgu^5EtNhk%QbQ!&{f5D;O~c;yq~kycm->Rh7**WIvO*Kk!-BBAoSF;n!G~L4X5bspIG*>dV2| z-$g$YPQ+e9R)X;uU-*2mbLMIbpzFNH1CG-qQ?9k^@l7+&72qe-_Pq{$`ueFtig0pL z4=yBSs~)+3noGhg@j7bDO`Do`pwujnwa6&I}Yx0g9SUnBzk_fE|aq8;l; z_lTJtF$Yy`OIo4@bnuX@tcL?PCuwZSTijkz#&E!{@%44EyV*xPLkc`r@ean`!^bv4zv} zm0w~&^~zQaV!hP*8Q`E%wCGdwP{5~RjeGG?MhuUdV@c168)6%^y!%};yhbn;9ce}c z7?gmLP-*@}x3RGik#!Wz^Iy0lNP+>80|s?CU~sm#zyIUcCz@&xK?asmKhg;10usa4 zWu{nzWdITsq~@;!SVIx|vio3E)OSC9?mNFZc0my^s6Y9paqHpcJ4_-J%8f4Xp9#nF zMohFlKw}QpT}j$%2Sp`8(K2X}z?fJNww=S|4X_w=diAMzrSZ@z5HFz3Qx1`3e7U{( z#;~omRhkVmPXy4=er9C<1C(4VND+XgK*(OYB#G73XY!0hl#0dsXvfeh2%U~65-xrz z*7~WX!@SnXqMfbt`^&4EidM?)5VWYEa`DnXIVib2e+ED&=fr(|Ef?NCma1uv(xy~| z$btfDPg}-(q_LgsE~U;!Y=72wz=FP+Yq)(sj7wUeSu&NNAM|bd#XVtg2$BDz<}nDs zNDsq~^wPovBoT7^{%V|==gmMoql(W3-?y0jjRJgHI>@H~@$02a{&{b9zy`2To10g= zp<_B_x43FH6t;uImWu5GWOX$IrEYUQmi_pq?h^+GfE?x`N7qtVnPfnS?9l>??~w=J zftCSvO5c^iV5hpOcl7o?2R-OvXtRuF$qobc$@m)EFdP6D$!7ng=!)#r@^V%6EHE;N z&j`ZpqhbpwC>q+ zOpJ~F>-7M0{-wQ^93swfF7L--|N2@-pZOY#D&Xd1yX2PnYn8sqB2b2ddQ8S{2BLla z^MGn`U2;p;Ld3p3Ks(;E==+zwiV5h z$z2NPF!t0k8`)%>wHHE{v-t2|(hAIVtA!vf9BtaUoA=W0F xNq`IMw?hB-0|&D04m5MjOuQ@j=)|{O*3egZE~Sfx;O7^Jjg=jy`rNg|{{o*q*joSq literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..523900936e2afc9c032828125ac16fe380f29896 GIT binary patch literal 10430 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 AxBvhE literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..69908aedf3328f63504061aacf13b3ed4fab4fe4 GIT binary patch literal 3499 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 IA@a(90j`Fw2mk;8 literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..04580c4483779fefdb43090f5b3c8166ac80c7ef GIT binary patch literal 8492 zcmX|Hdmxkh{~xJV?XX38s^zk%DPa-gjKm}gQPhMkqmZe^3Q5UA%$y{|Ou2PhStr@l zNN#PF5YDLfbzL>uiMiC|*6*{<_xt;U&GS5;%k%!cFR$0@?b<$1*WZ?}T@Hi6eskMR z^Z}oFsvo#I_?>&Z`Wy^qFzH6zc_2pZYr{4F{|G;ry;a`doMHTp=yjPo`m^#J{O#23 z9RJ4$ICj>v?Fpw;>1Mc;Dr$Z zH|zu7*PZ81bEoMKXTJIQkJ1%$oB@$pQHD>D0q~YeI^{4cYHmPd$#F#8Ew21^C6~il z_|u!y)Niqi$Z$}1gjID1o~-JgUT643`i?1m!j;Er%FsL3ChF61<)-%u=4r(bdZ=P$44Huo%NLE`3-gDuCSL`klRGB^;wcEWYRWTpKmdB1B z$F)pim|ia4k=By=puKmcy(OD5`JSS#5h7eqw5-pl?fr3FQENGs z)jS?n{d+TYTTy$XMg4hW#r)s2$GxL1m6+mJ!BzzxR|lq1@CMoB`)E4{G}A51fe;~` zt_o;dFA|=|SRgS|cX`)}rQ>-JxpYc5eT9UtC>dm#=K>SdO4d)*PR}cAMxqG?9&0wl zN2&J*`1%&Ka>M)$o6p9gG*<4|CgF1*_KjcG&J zv<#edJoHf>PN>)qS09<}i_|rKHS+!YG3$aiC$uq*)fhzuR!p&$6l1R<<=+~W_HzLc z`M#I{|0tD?p26pY@Pf?2J8UFM_|TQuPX5*fx2~$p%-_rGM2`;MUo3k-IULXK-gQs& zAsOKidRR;g?5cvLD%^#)RW~T<_wS3PQZDv&|D~T~p8q@k)l0>^Q30277_swXY@#8w zsDj4Uoh~4lPt+PUhUy5ofxfGPinBMjq~V;jgn8v*1?A$OqB*UFDv1kh*o%R>a9rix zM0x@P7aKHSETtauZ5_$(>!p-Vl}?S@d@1oXxoVjDDwtsyN+}-3-(rj(oSnzD?-9QH z^vTCvfBwJm?a&16&++xn4k3wYB|PCKyv*s$_hzVs_n9T%6nM8LQ*k7OgcG7g-w8cR z`}U}7@S2hs|U}`a|adxrH#oT4L3@UQ|~Xw8BtfM++2D z^Fv5IVKApu3q@FXml!xLEs1H1efu+kKecUqIVnd!(~aZ@qYreA;1OkV0i-D-z=M&y zVZOfqACw%fH+K)F@vSPQEwn&j)4yh|3$hd{$|_BF zpqaE@nBwB;ZEM^>?x@?Sd=>BT-=NJ236Xq{clZrV*l7E_E~vkkQfb;B!Iyu_O0~cy z-l0_2Sha#3{+i1r`^)I4wMW-VL&T>DYbttaKk`>JlX_@6#-yCy{v87D270~jF-G8# zhhwAGVfmK)BNeNmY*o5zNVv2&>u>5m_wTPFBV=+xWOcgdT^&c{w63nD=+XE*o*5PU z^nv`jcBU~q)4T4_(h%e_Q#JmH!gx8I~ zfgJi0-U_u;2AEt;v_R~<~duR!>U*oI`kf=T*%$pN8 z`V(r-1#a?q4DNEdr&zD3|FpCiU+x{feIUiqqBb9Q;_>^uF)0NEC=JijXAyTzE}I&;5lK#e#4AuXqQ0hfxM@I3ubq$ee*IX!Sgmbns}* zRji%0$M1TXrBi2^BGLRvwjDDnD$0ajujQ#)d<5S%lI`FyO4aOF3Z>p%Ro>CfTP))5 z2_l&yBK*;zH!vuP&6oTdH#ypyAH^(Em(BIo@TB;=`vtwDROXB08|iqx8-hqh8C3W8 zxf&ZGID7_fYPAbhwaqwXWUH;niypNw+WUcDfp>86X7oYimQPo4Cu(}7dvNjBty*7K zW_4<*U)w~C@y_`)d(nvgq^|BGOM15n1V^2Y(?3dZd3Y zqO6z?t!kWTykXOg>pp>5rFiWoTLw-#_&?>g)XcUXJX{hn1TRr3+}bE}6XOqe(C(AXaxSl#bBP4BjI^AYCZ zPCU&~9h5I<*^} zP6ytteDHFzm=j*H-60eAS-{LrKu)t(u*lDMyg9L-)kNz}NfDKYJ>+&z6WKCWR1a<3 z#{FI~wrpy>Xr~qt$w1B67H)$9z=CV+4{e26?3&*1o$cZs$6lAL)<)C-Q1h)bJD1AR zaS3Cn8PF9M+o=)bsDti2iaeI>Q|QCt7H~M}#inUzpJ&GR7wp~TGc%k5XQ0|p$=jH{ z#n}6tiHllA1{fjylI1N%TJhelHPBzjCf5d;D)vIIvh(CAX!X-TVV!yMN z&kSqQsuef`#z{+k{$p$hEpFQyZB!h#g=4yfX`Erc03;XYJNsV5j#* zNGiX+incQWrE`d2zA!BXRp2;I_X;_bEt{!3s1ri+W6Oq&i8{$U(VJp}G!ltm>e4Vx z1BCI6t)4dQ@q3LUJK4GbRmtsoXkhL3sPQs_sT-B@KU=Qzom`l|Ns&!HzlpKzO?CfS;#pRX&?j*vTIQ+xWn!%C;x3)P=l(k)Wf^9$9h zRf&tO3wc8BFj7v*QemFlj@BC;n38KzTWWd=#+DTqnQno|bz{d2+-U`^%v3Jd&j}u{ z?UV}2HHu;lKq#VFX)ipKvuap082}3*NsSTa_c+Th%bv!pMmdD$e_zxdwT2A6jI16L zL^>1+xJjp9(hAel!+L0vuX>A)F=E*g6&)IG0K#kZDELgl$M1}oL%TR5Z3#b_qZLj09xL#?G2!5Uk1DT#k zKg~=9ZUvjYNKc%uTY4KDl7WV<)8DkDTnoZ|xm}r^gx}%iD`wy%d<#0koWs#n@23UE zZ(_@qBtGES0dCsB-zq#r>K+#Hx0VUC6sE~1w|lIp=Wm_5&5M+DQzI~q$f0SCqjrS@ zHGrbPhVTu@)R)wM_!M6EFc=H-=o%s++QSbouCFw$rNb!_^)u*o&igo9(mJUTz~2L7 z*>e0j?`(G(bVd3O_C>H$i%(GtJ$&^fj3=(^cWkAmedq7MdfPo617^QhzZbwKTB>A5bLNhoa5=BNl zEa#~W;H~=*qDN}cg~IzdVd_gLDFGt;pZfLWy0|NP3^g*s`K|vVq|-nv(g|iEJPK#v z$Zwb0cYGKC2HXZF`ZZhfQIJG6L585i=OF zRk9-yCg3&|+&QrHa;k*}*~)QP1UVC9RyRF{HcV=m9`%nm}{V88^dRL$g41Y3adj$`doccDiJ0Axg zBc%T_H1H?}3LI*@d9DFepc(l^ zuo$>rTAA?nRJ15EA3!0)y&K6e5&6m(plzV|!h!GDc*ybAs5<}& zfoM^MLwb~%#_9ak!1DS}xThHRIBT8%=!^>7)G`5`y?rn%B9Z7zwtamwT6z>^m<8Fcoe#(k!(@G)xil>t~9H3sXCSM$9CSuFJ2&m|kD5l=) zO7#JOSx}>5WqTAXJLGD@m3kXtFexz+-q0hziu=5<;B9jCw37+#($7!^>7g#Ls!_{w z@?L0W_^#;|kl$4+53+t|2Kw^4*Mh35@kjZZu`&aU;blWISU+m)dAo6*)gR@*WQgKpUyIO8oMnA__o9ASE21#M6{;aL&HUsCDb+)Z>-@gS86gp6L zQ+K-`G4ah=<&Xsb*#xc2XynQP6?HCX-PqG}O872P7tpZWkgEr`w0!ygJ>hvKMDFR4 zzmK?br_d9Wvl8!@kTZBAld{sOYjAsuDedHyj`^R5PXYwhp^}#@tW4(n6E5f`S8~2c zB(t-#9wfhMOb7|^VUJC{ zx*mXx$Cba4S@tUxG?phx!Y}d0(j9@gW7Ud334o^SZGFu0CIhC|zwqqw`>E*Hnki&} zOMoWPuk3sNyzO5tZ}eP8r0z1qfF3IPaD4MkAByC2>>Z$Ka^&Tl@G>13K$%5*g+6i9 z;Z@ctP1jS+%*uxW?%>J+<3Qcfzr)+P;~3ODZo>4c8y(|Fs_QP#`@@-y&EmL&J zWcw`!Ugp0pz7c3g4gJmI%N(I4{_Cb3HBc_DQyb~nw6it6D;maa0()FKP$~$0NN4>` zA6C>B6ndJF8L7p? zsa~NK*Y@ccFL307V(ivEA7ih}7SEt2e;}T{=RX75Wr<3V>ij_LpgI%{J_Hmv{y!$- z3cnRot3}tc>q1B|ykBB4j@}yyLhP-iw^s-Oh$5w?{!hkQ2(Rf~^yEoi#xAuuGTs$( zH*6ls-YmXTG>)ITXx^S~Acd()^JUille6UZsKzZ)Iwe-$dJO#ITYE_e!Z)jZEncpY;wq>Ftk9Pd$3_ z)_(^fA_F(AYat}4bdB^EZz@fvx@dsR(+9v7Epe=CIO{@B5K7U_n-~q2La7BJiNmRu zELvF1mpJ>1k3kI4hN*LSG_SjBgpNxFBY?O>%GsS&73M$1_iv?0JhS$rixm3-(amC^ zML`vxhbzK97`biTvv=bLR_0(l(W}6XrndpIENV}M%gEE1V^9pcK;{Cf({V&lu%ufoUS5A<5`fYKyATq^Iuiz9 zE1zLBir}0(%D0CEjOZpK2%+f7$D4&;7*|eH=Wt0_@Lr z?P9!Z4-II+82^X53{+6!An@eE){XA>M56U=IvNwbH9&QZJpV4@od3GHeO1;#KCAxS zLfH4L2BCh<^6RIUaJk*stRLfc7kPD`&;1MlHt7ar?_42mw5Rr49_@}{oUKU3$Q&OI4GD1I-D(w zW9zzzYHC_*&gZhCSZ;9Y#b=&f@zoO1xQWN)`v`&_$obO=Ro$uv#tp6zthx0X-5Zn=72}9gtXU_ITWDmR1~Ww?0#3 zC`0%A_0ZhT+Ua=(_TYpdSq9#1+&7dSS}``JFBh!IZ2A$OqpHUiRiDmsd7fQ!qmfY; zpPgW+!lWQWHW{Y#0yImM9fN1k8CN>6Qv}^3M@W8m_s7|V2qED+P=q~2tjXTUO!H!1 zU5z9=WL5Inrz~=)y7PwOZ*gI7tXn3)%K|MbiV0-iBc^629*3zqJlRHJS*3gm=*T#a z;5C!MCi6d&a%=$QsceoRtj%-<=5*?zDV3Qaq{WE=4|9q1JImr16Qg6F{wIPTmj82H z)b#C}KRnU=g)OL_T_aDhuZ`R$Yg3EyX~zxeV;Abi;sED1zyOu31aulWSWYqarVlI? z3;!5{o~d&s#;jKzPC2*0B3mUnD^{t_rw9Xf{o@Gk;rZXLBd=Vlhc+A+)-`5@c33H6G4-+<^t*O5Pi2mX zo5;QH=It%O_^O6WhF*TT*zP1lu~PU_8Q6cm#?!{*es-sS!45TxCHhD}5Z-DF^N@}F zt!-=A2fP$3D?HGfhVO9ltvoUkv-M=Asu=;4{~+MvGz`l!4Iy&2kI&5XI+OYGFn#^= zclZ1Ed=KXhumB&Ev1Q8vYxC$zFaQr)d2A`mJV`4AbxKUzKtELRnNJxk(s6kOT72uA zkvSp9;Qs3{pg;Gsx$=Q>tp8V=YHZBrzSzfIt4IVbYuMV-ct5P7hWprbg|oqx5Ylul z!5l24Wd&0Ebf0oHD#TR3B!aQ-R4!5L%3fmtdVG-g1g&O4+@yGF7-HkP~!Hq{VG$`70; z2&wVgfZUO%nrxtEB?L#+?S+=?H24Kzymj<5U&WwTqWVg?U6QX0(e6BJC&ftgwp)x; zcz;3tI!9vHNDM*qhLOGA4ZH&&b|?PZd$CbzSZ-%uPp-U-92z=K&`V+9YJXE-gj@2k z87lA;-FSudn8ezxb|L8)%Ls@hi)^52UBI?%_5gaFfV-$(6}^r7z{)EVZIV+#(^t-n z^41B-2?704DuxbMKk{!ExNc(wXdTA}1(WV%tJm8Cp|Qj}uY4p_XW%OeyiD>Z!8z#l zrwM?(tXe_9N^Vh!-34{7D0}RlGmpJx-KKvKZ$n@y42EN`{ zq*Cp?R9nO}W;zZm-AVL`^N9mYdP|Fd!!zBD*LZFSN s`bhX;VxhV^{poH!_%DRPpKAAJLJSZ7adrUw7X-}B#goW&I(p^*0QPrnb^rhX literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png b/companion/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..74e8e26bb2ec2e76ae8e0871913fc36de7142b77 GIT binary patch literal 9469 zcma)ieLU0q-~Zg4TD6$!)Q1+)9VgW|i*Xj^CRr%!Oic)DSS)uW80q$z2Wc{<7`ZCHKBX$Kc5bF`t4eE>fK*|C0cjxM7%$OUnq`4Ef?pg9*hUcF?MA$ zF7r?3AW`DyF-gV6iB_#!>wE6@4vZxfZnOI~Hj4f~e8In6z53xr?3;T>`v2~yZe3qp zC}n3ut0poNB~HtBA>1LRrJ=NQ$E(OLA&uBgBr5286ut^NBP8qI1E*WIa)FOh7^AdD z7`Xm&!h)o1tF+Fmw3XrUIj%@Ih>7-f|F&FRHnU)h6YBL!=yyqd4}OTRVG{^Rgf`*% zVaKsr-GB#+EpMx^e9dh>8Pa#PJz=ps*pXBeNeWRcOpkKq#;=X^_fcRR!Ey~Unuu`K7hPMyW9J*%G&6pH!|Op%s6h?XUe0WEvvL1 z5*cM^oWr0$iNn(y$q4PQWLvm|9z5N=Oe(Fko}9KWWQ9S7_b+6RRKOe8QA>s={grqa zU-M7I9%-H4zw`o&OpSAeI)IpleUKdTAt`IMQ-^vW>W!)w$*_1YdVYA4Leh&v9dj{W zA(a@*guKB7|Dx`6i}RGvQ@4H3%DcN?VtgA7^!rPDzQ$#%rv7eN>J}7~S#^eW>7?q} z(W8#wl}Y}jfbZYb;v>!%+c_SYTKucKTy9EJ-)3KTk1!}RtOXKxQZQp%ItwaS7qa}> z2T67Nf}ROaYrS6m(G}?BzsNJE=Y^10Tf0DJKYA`azg@S$SO+kP>+z7&VMwN)$-pt> zl=)S*<}=?KZ&lLH34@R(=}ASDzTRFBF#hoXvY67aF9>cqa%=IF@>kD0A+gmT5aNBd z8&Oh8);5ou&;O;De@@xEWN>Ci93Br&bvDE*HynX)<5Nonwxf|H9A9}*G!1H<>>Zm| zv8ozZZZCnW<$>#~?-B6d7hG;&vIX2j68PogVfoGB`OU3)QM@W^%hsEz{a_&e%gBG3 z7vSWWk;r-`;WypH`P*IQoL8SlwhDZ{t>e`xSBy2TY)v&U+-{!oN4dSUZlU|-xi(;n zwcJ@e{u*0y5n5%LNg)Yo&xLCYyk`@RRW+Z?oKwI8!RrAwmCSk9_Y6l#a$@ z#_X)apgD6MLaMUm%oDD=@vbh1#~MTPH!Lk~*1ksNpFzGvBfc32YAUVA8*Ot1RI_h- z|4g0I}cx0GWFlVgGvqd4G8R;>r@5!*c8 ztwR{d>@6&AC5Irx>TZYUkIW5>wgTbc)FQ^Q;F^G1Iw`;{dvL5xV2kjG4qieji68}7 zSC3>Se#92hltq-lBAd*XOVkp{WSS**Hjgdfmx>Oz3AkKQ^4Zm1k_+0qRcEv!Ba<+A zg&N!@4tM?Lbq0eGv~gL!U8CIz#~ylb@g^3%_X4LbC}cUa1^FVtoK+*YIWI8S>QP8O zR-s8Qq>vaZMnS~HUDK@X%)@Qsa$U*=a+}2`S<**x+h4UGDgQb)SjS(k z6c)*%J4{1rxbMZ59pn1CxMBXw{b#@^f-{lwp@Yul|I*K`uF(a!UGkUXWzTKv!K^C{ z4{W?)VQvnLV{CAAVuG2-yk$A!zTM}j7R1>si*vGWsRbe zPPJTRSD+$S6erK3&5{`_I-Vya&y0-hBYr;A5VG+`&d5^3zKkB=p==7JMAF`VGLc#Q z^goVRlDO3H+|ZF$Nc;zwSG*D~0immMwQr&oa5SAKdSW9T9rHFF2%wO7iqeO#7sYOU zwGd?#|I-cv;f2M&$qwCozS(y{sJ&^s+ER_uBFMIgQ;!cG!9MU#a7MkxwDb8ozs!T* zFP3RKFYP4-d`OyW)%pZt1}J<<0r_=<31N`_rpkuCVIy!|C7cFYw7scs&EgKHzV#hn z1_x6yV=>A@B@^T7?!!l)1gbm{?zY7XB+o`KIQX8rVu#>bx2<+E8Tk73slcakhrE7r zvKH&IsO#aw5AvF7s@aqYTJrJZ;f)(3JeEkM)6+zGJ;Ow1zbtR36`K;gWX+t1Xq3%h zN>g{>u9_3-JB%~7GOZRwOQG$!yk_u-^L#VM%ouv<)r!Qr}bBe)t|M``uVVI-PzW8t{@p!NI{nAssnU z_gD_4lztXzO`u1Lr3ND!<8Qy2y z2|`N>rJqLQs~SMeA?H2(#l+K}K-|o1895ZF`J7VIU?gsdk16wxZVKexypD8x+1GcQ zf9g`6#u-F=w`|+>0ksW1W|0Y~KM)4I&nZpvKvg#sG8~s(%BiERM;QDZIo^mt#2-CM zBdtx}t_#z_%bAbH6B+`edGQ=HLU(y@^LLcdL24=+H2lb*y3d)XJV;Qme9{=>#taNP1CkLae}kE70r8-H;~qyVO6E4t<4>nR4V0wT)> zThWMA1T*ZX4KZ?6hLQ8d*N~OAwV3vi`G`%`4Sm{Gu<_(akl1Og@tJm&m8iM7-gbdS z4uzyp6ng-OkR0*~mEZNy6CQdGzz2p6vlxGNj}kAf^IB!0j@o}GL|fl8p8PI(qldha8y+V6$KQLsOKi<<{Kh(uI9vnnU)3E3;W~@d&&xJd5#NO;n zu!5)9&)eK#cPR^2Y3+|6@PtBEd;0||k}EV=hYk}@Z&Cn<8Wh|{sA=d4gFxCo08#AL@E^PgJ5x^-f3#mSPr`dE+mtJu8Zd#P!u9#SmFYORi8Q^O5>$<*<iP;u?KGwM4YnTcpgHaxPVQ*0}fV~oYuK=fL1W{&PHznilrrf=KstY#zi zo930Nj&LD_BEA?9*WxeTFHunzsOs7m}-PVO`(%Q@=F642Je4yBMeSi+9>d)}HG+Xx}DCy~pBmo9`Wmi$fhs7n$@ik*T_#aQPHAT1H_jTeWGxOo7UL7(6BrFrg3S;8mDll?`5u+)C{*qS|D_83lz zMl=?1xmxXBBC(Y7Wk?RNkyUG4wl(6^u1iH6DnQ=Hzwah)?qh~Q73$xrpJLo&o3(n6 z1gIvvPjaDvzr5oPaIj&9kDkw3vTiDn_p8~>+VrnS$fUJ>Ov=SeF1=ID>nM}D48FNf za?oBs4p;G{l%^~j7ae{PP-($T&#g3km26~k<&x;|dyyStKxEXnmDp`;%nGgnr}g>s zuVh4Qj$Kk(n$yL6k>3^^E`V6z_)1h5maQAG&DCQBH+QQ)`(4(ROO@7oAl~-@!u4v} z#Uw0>(AIrOPCsOC3epbJq|e+0eEO`d;_s>L4#ekNG3knWW3WSxXu88UxNMF8B!04s z6aWiSY>TCq7(fL$1PC30w5wo4A;5hmfe}oDz1#|<)%QRp+GDV%7_V5q24*drKZE}C zM95=5ML*d4u7+A7q%Cv@(dNnuqj+LBhq`fTu}9{;WhNVzF4G+a&(5~z8u(+yexTz?Nt&hS2@^+x)@P%N7{6w=ZR5x=W63=Z>^ zzji`&o+0R?eGQuE!E;*#J_xTiz`Z2T0Cn7AT7Z-6^Jf#1phC(;7+6>=hYE|@pQA?O zYG`X3$C{n|KklBXP8^ur>cfID>GXz zzYzZNO61UIp=i+ilUT3~Od7@OVj)pmfrJ5eEb`L}&A(z%je%KWnN{rBHeg(gYlu0)bO+H~#0O1}m+~PT94_ z)%Uc*Pu>(8?t!ms0<}Jt`DcJ7nkr|7r zSmjW0+&F3azNDz{D z<6|B6f4aQ6`Mq<)^O(`%2i@IkW(gJF_q2T+OXz^yji=N8B!U|nPtHDpb2$tcV8OSQ z7eZG~r!6sD436xt)l$LrpXdyoIpf0BFzrMlk%uw(-??-J>gXXBn&jSFbz&fik^!&ZpCL?_B|AP3snpt#5SI$y09d4pZhT%G`|XCoIBz zm>SU;#xPQ&z;j=(#ICIVH;{~FhQX|J=WBQQ{|Q4$byq{cr<_c``T+*mBCuV!&WO8= z)5N-eAf)3c7yyDZkH_^hG$N>wO^DuLxX$X+s%k@EtKcAj`UN)MWG8`PeDekv6+1nW zLjYN>u&xH`fE9>VWgM#B179r&I1w+BeL@qj|U;R+(R%S z?aC$o9s<7O4ieQF_U^vG2gHfX7UCbyL{o-iJ(e)_GG<(!2C9z9br=l*!ECsgstmwW zp;olvS1MQ-<>I>&SLVv>b>7;ClIrbV^6Q+m_;0?jIKvsv48~t6&U106;S^wt-F*_Z%q6vmIc?KF_sV7+kaJmVE8!d zs9)?Z9WDooZemj6O{80BRB#P2q{^;G?my-Tp8KCUaGM&o?&b2nf+ZpIGQHk zwPcu7H7`~SnHesBd1Ha-@JH=lQqcmy>!X#z5r;zQ;*7@!^ZU5mkD?BN zj~EF6hGYLE>>#PIFGyjBsN$DaT8}!!D8GIh0!PT9e$-lk{Q|!W)L7%eFC~CeY5-@a z?Po0a^zWgQAtt!o4YCASv-XN3voE#Z;4g|(%BsqtBZ!r`iyBQWAN2P6LURH&GcI4% zuJ^!;EDw@qJCCP7*RJAyK4SK=w-<9 z>e&xeYUJ(DrjVQp3vO-m0K{#&FX`?LZc4+8eMP2*s;);s*!96*!?d4!vkzo(rEue> zNFhzN;XH-7WQ{r%XMW|D;QEVz5)PHLHf1qZ%J`t2>>6S_7Z#*LWFY(8V;N;lO-z`@ zJ{Ix-Osv_n)H6QVv9vw?RvxbNGfqLLSsKosWecpiI&i)luZQ+cbXbtuzpi!vAEcYq=oT8h0<3;tQoN-UjFTMxCC-{-G=r%OZI0chon@Ta&$1Ct~yh!emHtz zspmxwsU!l1aKFHzLa*0L{^o1sLxw+?ha5v&Kbo11>n!)#UZDnHI;5i5(|`W`Q=$2N zI-4YX_gtS%Y&IG233RvNvE2Zq zyUkx!{m-~nr;N*01_*f%EZ!vNxQ6CG7Y-&Ds_(eLVPEHUTwz;TmAM0iZvivBZC-bO)($atGiYk_O4L-X~psMjC@v>x}zn{4*!e4eMM9f=d0t)CcKRV+7g!kY%z?GBqirA)5**ye^JW04a8 z&Vr7+S+GoDl4sx#sMoK8k2~lkQ44-P?cTDE`{xgKtDefXvU!&@m6} zV(}LV`BGxY5(+5*D;*s4fuB)(o-G?$@Ym{^O6$|e@h=GV-&~P3-f{|9LMq_k`MRmI z-17l%AC42UP#NUU@KX#hVtj|?7WoLLDacIXN^^VK7`qt4|~ zJPQj)yiMw#_-j&WfsREoDo!P`Dd*L{sBv%!!-TmkEdO*E45%D&oG-W|sJqk`pHpfZ zB+{yekQ+yR<<5m$E@ffm=@xo$afTgunsIFja}&D#U(RRXFfrcC%ryO7+0>L1wmL(&<-d^OOYUfM!c*7&n;vRSLW3**bs+Z`Pj zSQ-M`c`4Bhs>Ln>nTgvUfHTu=WH1!=S$jf_v&|Y#;C)@c&Z_&a32O4za zix`K^zBjq=t?_ZqLq`(g?c`>f&klvGDbt6e@&6eH_`;V;>ucN>n0Am#_L3Q!tpaU< z*p+)$aQ(+9I(?hR-QKWUe?;*{Z$1gsCS~=0-0HD+?=s-T>h(Ic=f?o}4GG%tzZIIh zd`(<4P+rs09zuC4)u9GZ`EYIKYXWM4>Sjs?;uU}g>OFX#;*b9%K{&!-p16fxE~K4% zleug(ZE|Ab1=^!x8IVx9+|gCF+^@6gy1E9CyN7E5pQcD&Yv1K&hY zw5wDB(b&R4kr5DnF*5rV(g6GxT+EAr*VQQL?C>q1`0DL0>OR!qCr41OP>!WiniAjf1=J=UKFqgk-Rb=taC5v(T7MG=8w=r$dOD>sg~70u9cl>N zRIDiby^&4Ze=g?++fRO-`#vkHfwo^h^k8y}RqN5ph7JJ^h7(b)2**3JRMnW@{qx&eMa z`pgkwaJ))L+f@V5Ml~CT5CfqFH<9zVHNMeJaV;xL%H?j5>FP9R01(;wsy(g))K%`K zCST`%9T*sW8v$-;JrXE2<}5E#k#zJLmn*g`tb8UM?s_ztwikZF5#$Gf6>tk~y=1TM zJ>>q$Z1|0}Kpf!Ja)H)9F;Qa2bX+x3gjEAQ7{p(&xHLZ6bbyWN+E;{gdm?ouTcAb|~Ax+Bwt> zvc{&Sw`Hmg^BV0sz6=kyA8Obrdk-oK33vX>cCq_^(Lga&CL>iW(-o@yiS!?e=^33a z5m@x)d>G^w2TEj519#de0~~yTicQ>nfXW-qv~w`K)2vMf&>r#&b~HAQwy9P<0}-pk zwC_TTQdPF0SfTm6R+bB_8hBrYI(((ao9PPeu|N%%3j%SjV0Oi9M&d@p$o?n5?0e`7 z{~~ZfJ-wX0Vs?*++ERMD>P%K2`zayGW5euOokRw7x#(a8aKm;-9=p6pbnK)nAdSbj?#g_{ zp#o^2ETWouWUeFNfgE!dzNMO)j`au>kH7qq+Cvv;M!ddyD}@jnNIs{|3eFKg!R7mF z>{7L@@A!<1v-z%OZG6WQcg16%hOPpn7ZmmZ4+%7Q66o%#_e4m5`+YZtS+#!e#@%33>kr z!s~7WaNPO-Ymv~2wX+0LfabFw-p25N?Z#lm{qL7`RirTN!^_ZY5?=$VHa}t#DEk>_ z?Tap8ZHoq#abR0Qnnu)7vumedZ6Zvnu zFA_=a1)NDX`}!aOS#&qU3~={ z!u|7W+v#;DrXi$==6h=T#bp zLg6mPpbVj9wj2X>gl6rU$2PfVb+|Gv7*uz8qgB?q_Ju4!I$o7!g@NV-tJY&yBOS;t zP|x?-?wx?wfk{vQgbtYD39z+b0wAD86aXl}^Sf%!>AF5fX5o!H^Xt%vlcA|UJ0z0s zv48~>G>$UfU>*7j1lRp)Fo3cy0fN`bPG)X%Uv%+F>)I^A|G^546!%+E|yBM zE(!nB2hw)|U}vDEk2ii08SV0sqgXSe&z8BxIQ;PqZkUd8%SIzw(SK{!%EojY*GX3` zHVFM+jVK|!|J{Fr{|3m*k5$<&b~QU;@fYP{5v3zSE6+fRWDu+MG1zEw2Ymveg1^iIOJi+Ev8Jsjzw99wFR8xP5%k z@G?!QYX{(KIQ->buG+5u2FUP(1Fy^W>p(4SzmR6iJaOq{OJ^$s+#uSNJtLV$SK;UC_AKbjTUElRx>z+&d%nX+btrp_p z;aO_5hiu8i!w*05^Wga4U*AF=zTn|uEjJ?T9XQMT2^exta_th(*YCdx3W(N(ABu~h5v5j{ia z|F@qS$s{uR$8gvG|M&m5!+-rCj7k+w8kYQL&Eg+FR|s85eb+j`&$4Bq|H#Eg}1s|4Q!{rdQG zNANrJ(>EO+oXneZ^*ev1;Q6Y3g?CySFJ1Vf^@#MK8_nR@7JODbbxEWx^2^P7u!&TY z=>ddp*J)q{-LJYL!~f8JNbQ%0u_A3nsH!QM>@jv_{!`|=;8T*y4fkLD z!e1C4S~HvUCWxwXVTOEv!J`MlA#y}pCEE3FTg9xh$>ZuTh@|$`Dfyn% z+A#H|YGmrlxJ(0%qNUPMJ;<3}2p=-qx^{`&MC(5Cb5#NXj@BkhrLx-3jZ6i<3t~+T zOu-2ka`c^|+x&SFv+K_gW94d9P2(+%wwiR3(OE+DVOP~rDgpL`<4H4WYesfO6Z~GH z-*5B(Wk!xYb~F2uXQjYX+w_Gt7B?Iak* z9!->QxMQ5FYDyye-G!Z8HR>5lYRw)|^JG61QQ6%=pklvk)wL{?D%Z5dG)`_+a9s8x z_{G0q;iQjMXA0O;rafapHJ4N_Ty=%=Py zz#hH@o|WRV)EP_ccMI|oc+hX#9FI2Y#0*j;BSa<_ri~9gC_uZI3|^2S$lb({S?rRM zXX0`4P5V5S5;G2(g;81lKj3I(G>^Vb5up`(6$OrL`P;kH`hI5FLTO@n7|-83;m0Q< zOBOC5JRW(*RQr|r>WlW*I&p7r@9+J{6$dZkd0r1Rc=N!Yg)Fb(g&RKet(-Fr7O*Pg zPcPdl-@0|%TH#J~45d4849eM&r0n6TYWH4oSqI&$7e}Oxb03pRyNO%Hsg}m%g$q_K zSxCI#DtG2vO85Op@pr?+H01b0nA6r&T^T$pRsER#KImI@E_-2UH(XREBUdH2do>(7 z0!(@|N@YhY-P67=09DDVbsu>E7Uvg7jzl^LD5AJA`Jy>=V)}PZ}**(dg%R`&il7qt@5^<9GgUW@bruY zncy&6=mlpAJQDo}y`7@f55QiHV{gw~Sv|8m3dg#3$DL2QWl69?!%Oax_C1Z_Q^Cuf z>%u-wnGSmAomlkfrk|?jc6rlIelj@{B9vuN&)wyR(<_|ohAfQNHJws_VYKyOrU5_a z3t6sZNhpIQI*5L0WXcqGn>|@QSSRkYC7GSf=5eD%8yRMHDsMx(y8*l7EPFU^+6lHq z0l#($*Vnm=`TYZnnIx<_ztZ^&y?R7VCIXxoZEf$U&e_2i{tIAdTUV`#J3-SUbG|@S zq+0Z8GU??IVd_habLCbYzs0a!hrE!|I=2!t=o>hqzrB<`Yig-Oyl;xHL@4^bRWXL{ ziJ?^1gY|fVc2&7Q+rRQ~fm8HZcjH{;y>Wv}kk5A{WtTm-b-DF8Mcf%hlDpkXY?VEO z-jl)mt@hHctGK7elstoFE-At?SJ1EdSDi@Q(LlW+OKiAfbG+2r<~W((uMXSIt&E#I zRKSOk!#(8?Ln^zqb^_p;+N;?rIX`Exz~}-5M&~|hBIN+OXEvov)iau~8H>W$V{RsS zWeXW;_-o4BY>waE$m0iRa!V|qZC%*j0`9fH=L$7?_bWF)&DALvs4NS#p}+pKAy)-J zIFruz9M!!DuS#oFO+$~t6Y*eb2x(6+OsYk6Q9%;ji+oJAd3R^~=lv|bUP9#cGw1}}T@-5M20-?x--MKz@R!pUV?)90@uw51RaYDUi z3BWZ8)^YfEomGFrvm*h{H(!<~@J>weMYJf7@sb~&5E)YQ_Rvu^&G z5&2Au?6QSiP!GU6AKrA(v?QRQ)|YUt=~%K{ErWG{O!E7?_}Q^rym;r6c0H<|eRMou z>do<^MeA2aJx6XAvpWa5@a%3l$mTLyKHI9Z6s~YFy1ExPRZW-Ut0akASEpRvox{V8 zzcMiCP2_R+o{n0~IZ8X+%d~<@L!Pa5*VYDVjsh{R=_LXMIKuV4opPpe88_?1`?|NA z_LT#4<{aoj{_&p^)L2LpCo{|aU2Gszd|DNE{FVwp;ew2cJ!I~kk^1OkbWgjU@ikhj zMrxfbHi>1ad^)zZZB&Iy4K{?$n?)DpC0Lb3tGvCmDh_swnTEl53ReIO;IT%<;eurL zw__-Jn~S%~mz8(ehEs9-q%$&CJ{kV-0i7xqa?UAL%@mUcB436qLs4l3 z*t0S9ukpuI*#&EypM!Ck&Ul8;e(4P7vVJeMH8rn(4F^Oi$bv5>n=}BzQbS==9$91R z?Tso8**1mN>@j+M=cxkU0;LvXa;Y_#T+>*H>~~)O{_s@m@bJdeX!Pv)>zLe2jAg#l zl4=xBI$mW<>tTzTKbqo6AAyjfm02#pGp<>{z6pOWJWfR(HqCwRPdVZ_owiY*=py&- z{4PqB*LVJhA_IcgAeCOAUcJOekO&iZw%V9~VwH1U=N5U1D`pCDMX+B<6Y`JqbLV|< z7;d4c{=R>~Ea#JB!<}w1phXP391_{vwvS$X7YwNyZB+71v>tH;a}xKY1CiM_2fMaL zgc^Rp@{N4EA?#%90wSeSl*+nt!tP+gb+B?M)kOYXXQwj656i}lcG<~NG_HVM6HM#t zzKH+!&u4lry8(G7b3&ZV5mUr7`j$a(d^r6;NaoEV@i<#M@Mc2Q->Rm^OB6%1Z8qP? z2is8LZS&*$pn&T0)rPMo($ zuu6>?J%0ycscMlBnKOA#syf(y(~W#_S;_1F*{-xZtyGdZao^M4Ud^=Rs><7IXQi5p zH?(YMH{_Z~2~1RI(?P`ZUU%fChrW-ty*Yvy!ct2TheiRtCs4)H{W0Q@9!~9 zjk&wAv|Bpk;NCE*L(ZJ{TU>g2Y^#oTYcU|OgAAc*)F(BjvS4DoqHkC%=JA8CpFfwV{~@w-9_FMD?%|1=xEr_POQ8hKNwX ze0Fw0l9rT>og3tNK}Z}9wtpZ?W&UOuGbjk((H(*&EFl_>`1il?k7LSuET(M-!UDn2 za!JLyt2i$KFnXc0rAL(VHb|^DwWKhw#4hF@-7A^>FwSq<}&F0O+4C&wh{Ru%l#PS zA!knr6#K$&TevZEz04prMvvSM&I^o%3k%}AGr#m#B8MPoYty<;?kFo?-;!5w@T~Yq z?fGiA#4*1UW#I743=+AW*l;Mp%4*|x@p*4%j6Sz*J-*)~s`xI1Po#TdxqI)t!OYF! zDTn?T>~XYF&i*7+88}?+KCvUo)-K+~sz*u7#9pn<|C~;FIS)ZwMSw^#_GEt?HGo?? zZgRr&n#)2&{XDiOnbI~k7w5s@AN|kax5D97ABv1lT=A8Vd^T?`;TY}{l*JsOL|SlG z3RdjAo3lS30#KV59&%Epq4;jziA#dpz(Jn^;APZimuc=yDx=vcH$$-VCT4pk{sgmF zyhk{iX(^pyXw{RSlmw|V5;-;YnI74eXEC~|J@fwZYtsLLLm`cOEn2X%J@f)cWn&1R z=x#2~5h*GE^_EkP*u7Ydy?Pah+(l(Qo)KOz-cp>Gw@z~RzYeW*1Lc;3$ctq7UmqMC zPt&ol4pf`y8x#V6*M>OIHtD?U?bQshLHhS&YXGMitWxECy2B7Jz+*v=hewo_R5(V0 zzP3zlNgGt}89HiaUNSyHLj{KSwg24A>l@=obsS4+C0N*e1%UpVrJSE<+aUg(XFhm2 z-R`vGCGHmQYkvRm!10b-A(qfB)-5KTF%7PtI`5V|wo2S5vu?^6{pd8;osY4p4anD+ zOey4JL2&#wr)U=&s3t|Ei3Tc)mw{1HS?fPcKw5UOx$bgt>W9wxNxzA&{qMa)l*s(# z(lr9aUeiAM#Cd}LqXo&S$43V3z>?IfsmRsAkn9y-+3cPVl&bRbr@%bi1mRksDBzk{ z+UT#&Tp%q(;-ne!vC;FYX`A(N_g7-BZ|903_VhXd;^bb_lGOHf;CJ{?jdKA`3TdO#NRR7)!6<~f=@>oQ{y4aQ7!Md;c}Ck zpDl{XQ=8G3$%>z+7vzM87?wmSBhdP*+>ij01@|1q#-&lTSkZWJQ| zIJ3Ut*TiTmrT=X;xvn>3y*zwkdL3qAh%T!ZaoL~DpquS0J=xr}H3%$Z@Xu4Cja*Bx z!ji+&Ep|?46S|7~HxL+cp=A;ZXsCrTTYcT@F*a1IiYPQo1=~|XmSgn+8U8Qr;76N# zySXSC%17Xx3*d1p(d8bC!9NMwd0JAyTCsZ_M68- z-R9yaRR~t{M@M5Ia3z!kGMvE-^%-?RtK!;@??2jC)!6bl2DRaeZIqu>r-+Odp^-It$@=pqzCZyo;JR&9D2 z{l0pBo{NpO%I+^s$d+`k(U~d%24kPJrtm;yOA8yktNy0njwDoWk_DkW$z*&wAN=lc zx#W$tl`h}naRl>*pZ87 z8P`CPw)ttnled-gi|^j6LC(|Gt_wTm>|R72_$SZS!9ECGqHVrZ@UK7%6A-8h|1PW7 zot+4`6q*`E(QIS27hh!|MD{j|{{AuhE<|kBdiicKNXbM>S*i8xuf}sW)>dV8Gh$K2 zBU9rev+_{y*@;pI#71gAeDKHdPA$JyQX+!L1n5Fklbjt!e{o$CWJ4yM>k3FU^4?=# z=;hT6LE&mLIbPEa_(A6U^?u@|xUcW1OO;oV!bokq?(C15s#buC0U?2m3a6s=`6n(- zU!s;7V0#CI{5%qpcHPA)VZ~2T=j8U41A-ol@rZ+hBz07$#;2fmrqo(WH+TNH=*!2-{Itcv-0P&7^|M9Um~z>lAMU<;FbHPwTM?SsD3CCP=! zp{(usc^|sEn0UUQa>SBXewt;-JesS~Ex$Usf%r0Re8_QjGD}$rUv(VzvY+c{P9a8H zwRTRWL*64uWNAsQao)teSR3n#itp2bi!*wRNF1SaQt-#&ZwwR~Qe5euxh3n(!8a(gl#8QV#eSI&>y(;^i%z;+AYd);1s(LWNH<>x{d!b() z{8k4csoncj-E-AXQ>_7&^*RqlbZ5`IM6X)HU-}y_~{o;*OA}tLKUIuTUSA~j~b9CR} zB_HmCzSqIx!LF74Z!7!kejik*kv;vRhW!5hd-(4fyu=2=sw>6SgC}=L27aaoSN6*{ z;gJr<@PIw`l~-0()z3UvT_wDoD!d!i;~icjb%Q5i`C+lb*FS}4UN<#e`u&kiHZwCr zOM>Q%mk5oEivuC~4x92NcSNnCf^if6hMz2G9>#i8FW%!((GQMzZMpNaBhu0o8I^{< zzWe=Nphs5Ny&f3ws<2y|KO7J^wdVJ1a&j`#zX#|3ElpWed)xZNJ%>uDY=a{3-RwRj zb^)^?`Mvb=cJ8CYpKC8&xWIWCftOM85*Y%Pedk?XQGw`xDcC+RP_RaJw!P`d7Ih7c zRZFmqnVXZ%%&+)PL(Th>@UGl5Mddg;#+L0#Re};}aNQxQNmY$Qx$Lg<)sJQ_J8ey| z?MS=X?)}ZMcjD%8YJkA+gB`-36(T|7(RIRwNdQt?hT-ED_+lD#Bu;{`OP@_ zQ5CD0pr+!S&O(MWSGLaP z>U?_b|BR?1=|}8;);geF1HJeg=U0tQ1%G8t-B1hIuojP|;LjO@JW?B63X3$HkeC_+_NZZr{(0M%7 zp}LU=$(ISMoS#El?TzdH+$h!Fg4vQa)e5jNmkyT*WP~&Pr^m($Ve9S~fFr_%wpd03 znLe7p38=?TeX0=?h}|I{4?pYGCyPZboBE~$cr?Q`mgW-J+HLpl(FtM$HHiB3)vHMK zWIePkRj#DkVSy_AS_z~}sUiWN#2FN=ue-^?@<+hOp!-nEC7Bv#?#D~;2xKgP)CGAu zwbYuM&L(}44pTw%Kq}@zGerTC$2w5#ky6i_UdAVV25bKO^4cO!#Z?2;VD83)!o}`9 zGw2a?jZi}gVp8pUNdG_sp3gynsmavj0iE!Zo8Jkph`FZ|@a_vn1ybt83kyS1%sc_- zInPC**0Zs8u{rwhO{SI7?B)b=_U-u9OF#|{e@sHsPzL;J1Y;J zr+Mj}0)jqL?M?esH)5Kv1|}7-pbItgJ!aG~_}0#zqf$`@tDH-LhD2FPQ!JtkASr&y zT`%96E5MMd2T`fNya06+gs(&F44wMtx+Rz*vKBQK&bD$SelMC$!aH+x&UbRPbagE( z=&UvxfP`B74BQofV1x{Zy^H1PnBu!UhwMUGAJ*fm{uY1NYHHJ?H17~+R2n{nML9}d?>>Gn_V8S{T9WD9ClY-x$^-hlMgRD(o$5(u=mcJnH{f6$;eC|dzRH8#r4|MN^^+x)1g5{v_K zBj!B!iLQ4@oap%{${PIz_(9~;)cJFD5Ba(M45a;o?hh?A)X#YRU566{sy})j^cZ%} zJx>*BkqvijJvy#2Z0!#x+dH;{tepZzEYL|y3xNwk?FsE01#F0rr7}mP&grDKW~a+8 zcRraocKQJbJtg~%U2GENE~&UD%BP3tfKqg2ch3FJd7z5Ge>;rb9@ZF0WIA`KFl?uP zy_>)w_s+UEcjMiSq{cg*{gi%8+e^J>c|uFaH1;-XU2zh#++(wi zEKGRLN+tVx_KnrNdSjysQ8wIasbYh|r+NGR2QIJ3E3qOtu{8UAyD>~`p+yYE{Q?#} zxa8GcYY!$}TsAcpmEJt!SBe2T+Z)p>ph!dzyfaE=hV5AM?06?s@hn9}yml7dp_RG# z%Pw+Tn+~X~Rqp>P`mQF4E)9USioadDWO_l=Mig|Xy!O;o6sSewq-@jx`mv{7a%?W}k;9o<~CdHx1HUVEuPMvesr z`w*xY?59_(N7sO<4Dm<|OiMkEHL3&V#C>S1e5RuY*rQHpI=S1@u9scJoZ;gg_tQQ; z0a&hV`#4%Z?5TWt5j8cGkFgx|ET9eZaY^y*?e6mLRAqymqb*OMJ|1fQgrmOAf^_6+ z1=dhD)5&>>10qDzT;Q!ky(qLZPz>7!X{8vJ0aCbI_u!1ogNy<$w@5CXWl( za;qE;Ctt#`Xw*Mi;?k@a$F}akS}v~FvW*fURSeUE%T8G5Lq!zR3T<{!Zao$wKxUbC z*iOHbV#4x(iEYird`CQaGa55VoU>fQwMBk7GJ=)Q^(9j%chtQ}Klqdj zfAewOAH~P0^0U|dv!v3WC27#MiE@I5t){Sh;xkZ=7c*bq*lYzJ`xr?d&Bet?rel>A zmGkTa(B6@@`L9|SL6PoF<73QVfE^ul$PTEBL(*LH<@=lv&#-vT?SypR%|G$!aAe~f zBz(Ep1pV3q3LnJ^I@R%DNqhSs9o^ZRphN$>Ln?)WAJ{Pvh~t%qMgl_0rEy*l* zJ|Z91&3wUCoxh1c6ghY>?Fv^o<50Lnr}B~ts2ual-X@ibV8TQ+VP^?amZ~J@RHgs) zD5mF>*7>H^7AD<1ZPO^XNmRA0TZ{*!EH9_%G~HPWH{+)$0u!IB1=_H@SV*2zldd7^ z1vw;~IupxvC^lsb^U-h=adS5dG55cS!)UIcjoYQF@^#M3xIPd8^_HSz;n(Oyj@y~6;g!@kJ5ZDJS7Y26#2Qj{s zQ3EV$@EJ1->MmCPZl_A97?s^0nO=rxoY$()y^)+MiA^k!f(`cdf2M&b{|E-~Qu zdxYAVbcdr*bUt`6u@w{`)K!NKgz(7rTit_ec}W;mqeF`yM;)x!{PJq}ZpI&&B+MOys#&WbdIkX35s2!C-?=+S1{l5vK1tp$0P)G3XrWc@)Dr3aYfW}8-Z8i zP5~R_KIW)FG(jYenHe%O>a-)U5VcBnqJGdcQ#S-+Qc}Kw<~t4Y7!27-$PpggSKn`Z z)D_co(a0GlUOQPh!KzSf0vCmew)qxIN^3UiqU`PbPp?RjH8s zQV6JytxgsvXuF{-oL)^R+-T^2IJ5UAI)zuQq4YD>c%;0&8LwV{S=_-)kl zoBhoc$+Y+@a$?f|od4K^f`jR`nMhwnTOFOqU{kO)rBHbgaz(`n1{$!+xFhVl4)~U% zK&%+iW<7F4ifX*&OVjA@qfE!D zap_4}UdG5-B&5L+u27*rs|Pj178jf8-=ok(mn3=k2mBm*`xfh>zj48O2OuO{3W@CN zY0WXe;bIde9Nqo-%a?HK5j9NmR@sf8z8cCp1Ema<>+la$D(SnPmw#oZ6*d>c3=Goz z-$JF2N@zwt%pZUbdsMT`SWyeeXqwJ+OQ49RoO@z&O3y?jxQuMCckr@d-h4PNxCdXP}Wke4ywYogRM8;Z$-sj$%TWI>oy31~M|HuPFV9fM^b?t;8uJL_v@wHMk;$6$^|8>C8t#8Q~+`t->?;PmMWQB6m&Y1!_lVL@mFfS9wXMTqkpsRC%hy8E7e!hUu9es?E>m+L?BBEO$o4Inyg_5rjc zzqZ`uG)m3ttUZBeFxCioxjrb>3n5!wnt}8 z4dGW~`6SW`*dP@{;saplX!))Kvzl%G_X{&_9XcVoIr3%&wfOm!X02R zgX?3Q>Eqwl@Jg(L|BTdv00tg=5uDIpseD(|EDZfd}3ZWZ!7#trw@PwvNoi-A~+ZD6VxrF{YehQ@TK zIWTDeXbW8|==S+1)lAdygpR#8Q7O>o|57iyuYB0)cg>f_OAq$lf3oSznl9s$3Pt&u zDLXp$9sf8xn_ZH#W{0VfUqs50oqJY{_&QPET~@BYRxxhk_dXo&ceSweca3bQ|dR{MXqnqBl~&V<`0I<-jrMP_1FW|sCsDmb69swu3jCG?LF40qSjm>+RYgsGs=?CBZK0j1txR!R^5_V%_2X6Wk&Sfbtr5oH~ z8%A{#DYdSdol!Ab_N7f@_ETpFjYf(w%eBm1=94@cRlkfQgzMPr8r|jr!I|;tofLZZn9Y!o{vnPQcL-qnK^D0d*lq< zRn6?Q6db|_XzbotexFU7fhC1IsPa-CB#*9KxzHy9KRR(cei?_Fm_5z;bh5Il;cKz7 zw#F^yxrM|GLsiL`t1&T`oi6liFx%U7ymuT-HM$Qi|03SZ zynPprnpqZWc|r1;%Fi!fd~v)xm+712O#b?{2geIbDY$G+GR@h41+COxBkrshv)(ka zGk13~{>iIX(3fIeT$aA_^V=t9N05!yTV0Uci#u9$Xti_EPRyfnmyyXe@s=M(YC=q6 z`75_IY!U-7?r>IYxn#NStvYk_ChPQ-#-R>G4>+N0TaudhU$wlfB6a5M@6o#jJug!% zKQuLInMT6!4Bs7-;3?071DE={#y)oDYye|{OGSV0D#P*W#@C6;I{{25WoY#Rd5?6Ll%wN!75XUhwyEE7BJl&R-0zJ%)ZtcRt z!Z2y{<_!-)ALr_twhNcOQZLjY;=^-r7-s)YxRPNT`$BNiz>y+ZT34jVHW_{xtlp>? zCn9y+R%y<-6$L%%+ROEqL@of^6asD$aUG)vVXj4~&LR&4AGh}CqNsY9Xtc-40F-#p zz%WEN8vM9e=3ZvKlY6wl@GGuaAh?eE3Q%VFS+{)AQh=Y?` z-*ND6$kVf0ni{thj4nv5a=ucOuDwQBuy%;YM=UDKSD5o`QOCB5LxLO5IYvW_pLzmDA{If`K1}{`~mn%^Q}Rd;}>1|HP??U)z_D zlf25guY6bXnUT`?Wu-83-q|@ycW^ee&42e!7Ma3fy-Xcgg|;G~^p$E(4ig}JV9za+ zoYg+P8+j?^fC2==X0nGs?;7UsPoEx)OIH59bpmpT-+j8|_Yf`m|dj z7mX^P7IWSo+myvmVC2iW{OI!@Ro+{)nE4yPC)-_b3ZjL!;_YDvYtzmPsWQA2FATVS zc4r=j)5OrxkzovBB^Gh|IM|7kJ{1g`W&DL0aVp^F1MsWqeRtSGy-qcagvO~(qGyU>l3M1r}Sy{KxPFv-KZtL{vo2>(jWbltQYHV#f zd}T@P#`cA5$`y56CB=1aBGE-HS&y%xnGs0D91+|6PY0Y0Te4IdF8m}lzh|+u(XNwP zSFmgd>C9TR#+)m|CmRlZ(MN72hD{tvWHqDI9A+<$`Qg)16G%{EQ841jIS*lQGqm}4yShp9U$dYY4-gy$ziK~8S>H_BP z6D|Zpk9Ar6+N#cXRm3XAg$1#+L?(;sHNXG$YdxUj6LF7d0qs&%2{Uk6?ylG3I((0C zcYUc_h|_@`*a;9vO3FwPtjxfGUT3ZFy~Su*PDlI($fhV{e0V9s{H&&Yw!b~(WF6i4 z2SW+d)N~jU7P0pl{_Xo?4x-EFAN=YIyah(sk#xM|0iX6cK2E6y^Pp0cdS`9|NjokM2m?VCBR;ub$B@HyYlx=n!~?c@mGdC*~E$Z1N5)qU^(Lg_WLQ z1X+@`Rt2D}+|?DYdpV?x7~{Hi(IR&Ra_39zV z%-jwE@WCK+JFJ2sW7^yuoH|}|MjuDM|L`twG;Je3j$8`l$E)4O#)~MBq>#tXJ?hrn zqkv3_kO5ULs<&kEqEB$d5lTqAWPk;w{i_@{Ee*I0CO|LKUBo`4d?Op;Q7{AB-^q%e zhC>~lvLy3p-vRL`_0b6#R+y@3B}C)ADX5q!oQe+Z0HaBlyxJ+lPdsD?Owc@ z7Q+_&N#r)WoXK>&H~%RX_NlkOfA8(_)DzKbCg(20B4Qb*4%e~Yl6znA$T9KBqwqm} z92LEX1KSKHpgUk-i7dr8JuWQwA!%?a4t19aD-sWwaT<5 zyb-V><02j!Hh`caM>V?;0t0_)!lx^|`%(M@V%Rb(ewm*)Mh-``Ghl=rxrqV{?U(7R zVu%O7KJY_pe;%11g`S@IUp(4N+s=6?k^kPxunqgVG2&Ek^|t}pM6f2ja7fvTPD=Jg zJBh@T#WL%$A>GNXonu4bSQz$D)COgOMiZ$My>PZ3{# z5^`Q*+i7=_c{qYZo8tMpYfUE>vNPe zp1`z8$O7}&+ZXDYhw@CHXq)J2CSJhndkE0gP+&9AY{Lokyd6oVQBD`!Zrr%8BIf7K zy~)FeZ^C&GE>CwH{*QTdk*|><7ni((*Mm6kTaR}RoeFhpcnSRYD@tM)aWWBI%@=~V z^G;?Zk9J!lhb!ajH}CPhu{YeUcIeHoUy$87CIB`|BNvb>?{5JD*dJs0;gmWlqNSx- zLvS*SpLK(N|By@@)G-~?+*%|tzKOvIL&Nh-7(oWed?Ck_P5Gn zdpkC-Bh{GM7Zw(*Ca=Hj1J%JeULTm#_<-zHlnmEH8UwmD2dvUpeP=Mn?I&_B73@an zE%!(iM`Rj+vDt(@5 zA|EFTi?eS(Jr%R~`@>brJ$I6m+C{SB!I@l@Od}!d5@?>4QHvMQ1!W?-g$T$>>5k;k zU;*ZND;fcd2tN@7aT%sLnuvO5xI$?)K9WNXIA>#H7xq;z_q6(2=?i5b;B%BkZ*%@?ee3<>`iJe2Vnf(pInv^l?Ck z1_JAviv2XZV3R9dHM?vQh(N!&Ry{Z}FufNSh65OZ&ox^0u=Dd55->=$w?8aCqWyNy zt@FROEP!dxeNsBl;6m3jf7jOw`5m;B2Z98S+gY04xQ-O#QC2+XMb}lz3wo%sC`kg< z0g@Pxe~YC#RDyu(9yGpg6f6A%LM3KzsHBB`Apjmst@H!sbcr@7t*sqL%#aZ!?{eCY zBgu#^0^0JGjQd^~qDX$}Rfy`(J)x2eNUM6ych<|N??jb=I62A8A61&fE|fm3IkSAJlbN;cgH0OAO?hg{fu#QU?SKx=u@+vB>6;#&Y>xU+tvRM$+4tGI4! zC~PvJmf_NlZXrK~Zfl4#S(npie+ffiZTM5NDtRb%q&y59hf-)V0uKs7jDG0Pb`8fK z4+xGTV7oh+4^_mtr7Ws|IU9gt#Kb@zbdDZ|+5rl6xP~L1ACeagr$ObSB1X7lQfi&v zKVP?QOESg0`k+ZOBye=`+`8*){DzBo)^hzVz_rXne?G$=d3LHi-tt1g8K0vM#{u-v2;O2tW=G!RLZoo+%po_nY(cKDaKTU~{h`%TEJ}zjN}tB3 zYeRD%;OeH?b~nR@m*vBFR3akKwBT2a18v8wF95Jg0xAW5#&tHEOd-uzJ{?sCT812g6e?-kS?bv*bD>+PG!yD+P-P%_ zQmJlGbIBRunOq;*1VO?@fJk|gNGlx1Km{0M0Os~>0Og=15Exhgr-*S|c`nt(<}w1D zUCYx2;q}?R02Kbi8CYRsl4EPUh)B%XY1DbUTL@`7aDvK?d80|j^JuSkRwjzpA2MEa zSxozzy+{U8@48xg;9~@Q2-W$7VK*NVQ*)J;Sg`?8Cwk?o$hAZ**&(}2gnq9 zh^kB-q~H0Cb%M?8y#WFvrAZ=>=kMli1n77zKvXfx559qhlJ^q5Wd4H!w!WQXU9fy-EWSBkgbthViI)CSq1w zZmtdM~XTVs%yX$;mdE5E6VlfZ!K7nW)&-kYA64GF;Q3s7pCLc z2N!pSNIK&*4-SMsWEU9Rjb)gd+iY68{sKNjSpkxa0DU~hY+%EL%T9+y zmm}}v<;JyVU)R`b(IMpGcWH2<{zV;MKU0RQ4AU_D2}0z?fFE%xGMQ}NaPp@au#c51 zX1P9WOhRL2AblQ7bex2DWi~3e|)^c z!(fZ)|C-$X`t@t{9Ixu&rD`FMtI%V-9czN?%_Y{Z#mT?}Bh>M;H4A`sI~2*ClXZEU zY?xN)SVNiJZZr@YY}|aTva0&QgU9AU)01N#KZ3Z%Bf61y_=!dg&U@e?uK|m`k%;rz zvR0VHX^z07hp4GJ&K8~;U8%*3euO8TsdF57NSJL;QsW~R8YK!>%~E`Q!*%+G{bP@% zr)jFIi!XT}5O_tWr^icuZD_{2bo;}OJISDPq{AP5{rGVqVPSX}keAK&xW`k4G7*K2 zwX^qOOC`%@-fGXJfmA9}m!$T#b#~p1Al0EXJRGjWtD=WBI>zo{d#H);=`dfq@N{L> z?lky+uu(?rt1lAkp@d*l!gUN(Qd}>|`gzB(L z*}lTF&#UA?uNSnu&q^eZwoSBV^GZj6QQm!D-|`&VGb{mkr5V&-hC;*^HPdkn9i(5`IMpx>;JXw&K-G35FV}}Yn&$+%iv8Kh*060$$I)p`70G#WFY<5@8vDs4^m9@RcRN^!OOQ zACvRhrYPx$1=neeyv{CA<0)2_h%tQU1HvMs1k5ruUNal6gDS^rQ2lhbOUCp9o_Rpc zzFwd2a;NG>U@gVU0@Lxn)ldNJ6LnTxM@_wrP%l5PY+O(Y zKM_>idnhT!eLu_j=?QBvMsJtp<-w$15OmhQe4<$+?ADKYo;y3jk>q1z2la1OGuNs=BJjr78xC>YfhP89 zwUa8=TsiHb#8GMBt_iUV_?|X&>Sp$W4)cv-E4jotL!l6u&B?xibnQN`!j)0$LNml; z8Z*D2<qgo6v*xaec#O#xXyKFUa6IU8Q|34}LBGXG(l+Iyo)3GzLXa-eq=4H*WG;O`S|8qj&@BVmK|E#@cE~w~DmIkmUh2x!ol@V^c{CyGTosboYYLLGp*;$tFAB`xPDQE>)j@Vw8z00kBb)DR>)MN>QNtWNX`V0N!-^U#oYf`)W1uWO-R6|W8>>d)B^xtd!y zaPlwCpH&2%Rh$b9b$f4Q*Q!cvu;OFUfng`Lc46k-wOHoG7$As&N;gs$IeR~xOK@@T z3t%}%V{WB|nrr44A=A?iETS9m(d~f=%CuN^3}aLQDm7|wF8+c_cdyXYHMyo^TUTHC zp(+6|ydmq;7Sl-M>+tnnG=x?Ifm)^X0eIH>2GmiY2B$!i67_}u4bpvistpwbES4!di(aqYY5mZym+Tt)nMZo1xa9jMQp}tH3hHXG&GS!#lmM z{~k+e&n?mVI|V&+$672y{vVLljSclG0!u;_p;wX5hPwdHEzo+0M25#(>_zK{Oh6IOLWE(#~wcV#j+KX zdu~NH%KrCE(9K`v4CzN*AD7k4Sa04b<7SBD0^{p#6D=(#s;YksypxH*M;G~5bt6rZ z9J3b*Dj+#YIiG~A1C0^+2$)#P*^#u{Ltye6KS#E2xEolqO~M7Q9#tCmJe0$xotwn= zj%Z6#kvB#;#Xn*tD~1zIff{1fm6DSR1*cgphE+b2ss;VXR5W8y#5 z^$O|2ch4jt(BY)ObGo~M_72;13`2I}CKAag-{7MAZhgWcaxKrlpFNPU98lmk_!aY3 zcOH<=X3B^U$inqbuT*JBaL+K5ae;UI=?t3Otf`UYd+(9Ff?sLdj zdv4wN#N!t=FAq>94d$^m@^6>i?hWv{RHIvaG(be^EJbj+{VT0N%^%bJNu2eisP8-v zmK@o0sY@fn0oZh{tk|CpgjdIfR(B#R1r1bhL=Lc&TefCQdn5)F9YXtsi!shJhJ*NU z57I2&hdwaw98F`Fb>~5i-n$Le3opi2L!L&_sv;Rv-skcA0PZ%Hf(DIAgSoJ9bfX4K ztZf2yQGi$neoU^pf5_f``+ew@f^w0C=i{*V+=8l=2U-d=s4~Z)p{Sf-+Ia%{h|;|Z zG>~o>IY=!4?lDcZ%u*4Xw-h`8UK>Ci<5!-aN;2n zkneDp-`A5=KFkGIXvA`ZWPcAEOs`9fc#5dW?*mq}GHVzd(3MN~wzs!GH^RtKR!Fzw z7BIk}hOf+B_;}phRqUVp3KB|L@j&3~>+siyth*>Xl0fn;l`>F)8f@~#*vJ0LkVP^i zT>wHZ#?ZYGq)YL$?AZR{IOMwjoVq=;DD8D@>@6P~$TUZ2&%@XSf`JyP|T_EPDYN=^&)_k(Cd-1>LHLJxI+KXrdCW2 z1^M-M+2p&J7+WQ9)(NG{P2ay?vt0MJS)=BV^5#t@I9{>{^v)nHrQ1a}KEU(A_O~OO zOYKNfLSPH`95Y{Gqg+3Pb>N@%3Z1#`@~Npwkaith^a5(xPmT}jLQD6I|2dnWNxzTD z3mCQYHNC3o;zcF1@j5i4<67b#D~G1Da?EGT%J~?zig1rGuLJkV2bC!_Ii^iRXUZMas9PjsNV>)7 zJ?6QJodrmluor7b1t>&xz}NjegIKBJGf)>V?h^%c!T@d~%dp|y zVW_qb9$d=u=HpakyE9z1B$0XdW@uJDAkl)=q44aQ>Nrth^u(`BnFdt-u9M$-`^ko?5ogR;Yc>)-_ zg6|dR^S8sJrUIx=pb0@!;YTCO-oTli`L9*c{BOyQ+_yooGkndwvQo8hZTDc!&Ym0;1HW5qZ%3O_v8;GAiHp zbe2+)4}sn7l@qw9?aUR^4|Ov{(~jmjwzx2fjW-&^7iaVL`-ALXZ17PT{Xf(vR)AbSSx%hURIbVwQme-N2K8$=f&p$O_d!?onW zlYE75^ow|?Gt;!p^>mAYO>yBh6B|X!WUSZKxCOGdpZ9;}h+vk2aTO-4kX|kY+&QSc z4_;bxPz&p!dD@Z1ubl2UlRTPa8m?12w8d0Vy0_k`sI>gaRd^p(=UD_^nj)=Fotvu? zuLKopPO;|dWrIz{q8L)tv*o|hX+2AUL%ct?aMG-=9K3`#!(Lge1xAxrB3I6XvRZO} zz$%J9pe(i$9(GnsAKCuQ53S``RD}1KzVU~iCZt$_>8B@L7|_N9@DcSaIt1D-3>n>O z7l{JaR0S}~oj{vg3W@iCGQbTuvT&gg!0-H*pRI=xT%a5c?+C1&rk#`#K%2IUczkW9lYzVNq&lm z*<1-E3at#ZH5e#?Gyru>3`9Z2;74eE*}oV&4zip@GHORcCy|q)+yZR~yN6DEg)fi$ zUIgk0J;A|OCkr45K*YowfP(K|)vzgk1AN~OXhbo4aNhv|U=Cw$r3kHd7s)1VI`6fZl5QVWyw6zXf)11}h8Y(t2F~8FHvk{

p$Nf`sWhN9ZlZ}5n9H171I?`d6Jxm!1n;ow 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 J?wX%|{(mrMfIa{K literal 0 HcmV?d00001 diff --git a/companion/targets/widget/Info.plist b/companion/targets/widget/Info.plist new file mode 100644 index 0000000000..5510804d0e --- /dev/null +++ b/companion/targets/widget/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + \ No newline at end of file diff --git a/companion/targets/widget/expo-target.config.js b/companion/targets/widget/expo-target.config.js new file mode 100644 index 0000000000..290dd3e41a --- /dev/null +++ b/companion/targets/widget/expo-target.config.js @@ -0,0 +1,9 @@ +/** @type {import('@bacons/apple-targets/app.plugin').ConfigFunction} */ +module.exports = () => ({ + type: "widget", + name: "UpcomingBookings", + icon: "../../assets/icon.png", + entitlements: { + "com.apple.security.application-groups": ["group.com.cal.companion"], + }, +}); diff --git a/companion/targets/widget/generated.entitlements b/companion/targets/widget/generated.entitlements new file mode 100644 index 0000000000..935884dc88 --- /dev/null +++ b/companion/targets/widget/generated.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.com.cal.companion + + + \ No newline at end of file diff --git a/companion/targets/widget/index.swift b/companion/targets/widget/index.swift new file mode 100644 index 0000000000..93caa87500 --- /dev/null +++ b/companion/targets/widget/index.swift @@ -0,0 +1,9 @@ +import WidgetKit +import SwiftUI + +@main +struct exportWidgets: WidgetBundle { + var body: some Widget { + UpcomingBookingsWidget() + } +} diff --git a/companion/targets/widget/widgets.swift b/companion/targets/widget/widgets.swift new file mode 100644 index 0000000000..56e00d58fa --- /dev/null +++ b/companion/targets/widget/widgets.swift @@ -0,0 +1,431 @@ +import WidgetKit +import SwiftUI + +// MARK: - Data Models + +struct BookingData: Codable, Identifiable { + let id: String + let title: String + let date: String + let startTime: String + let endTime: String + let startTimeISO: String? // For countdown calculation + let attendeeName: String? + let hostName: String? + let location: String? + let hasVideoCall: Bool? + + // Calculate minutes until meeting starts + var minutesUntilStart: Int? { + guard let isoString = startTimeISO else { return nil } + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + + // Try with fractional seconds first, then without + var startDate = formatter.date(from: isoString) + if startDate == nil { + formatter.formatOptions = [.withInternetDateTime] + startDate = formatter.date(from: isoString) + } + + guard let start = startDate else { return nil } + let minutes = Int(start.timeIntervalSinceNow / 60) + return max(0, minutes) + } + + // Check if meeting is happening now + var isHappeningNow: Bool { + guard let minutes = minutesUntilStart else { return false } + return minutes <= 0 + } + + // Check if meeting is starting soon (within 30 min) + var isStartingSoon: Bool { + guard let minutes = minutesUntilStart else { return false } + return minutes > 0 && minutes <= 30 + } +} + +struct WidgetData: Codable { + let bookings: [BookingData] + let lastUpdated: String? +} + +// MARK: - Timeline Provider + +struct Provider: TimelineProvider { + func placeholder(in context: Context) -> BookingEntry { + BookingEntry(date: Date(), bookings: [ + BookingData(id: "1", title: "Team Meeting", date: "Mon, Feb 3", startTime: "10:00 AM", endTime: "11:00 AM", startTimeISO: nil, attendeeName: "John Doe", hostName: "You", location: nil, hasVideoCall: true) + ]) + } + + func getSnapshot(in context: Context, completion: @escaping (BookingEntry) -> Void) { + let entry = BookingEntry(date: Date(), bookings: loadBookings()) + completion(entry) + } + + func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { + let bookings = loadBookings() + let entry = BookingEntry(date: Date(), bookings: bookings) + // Refresh every 5 minutes for more accurate countdowns + let nextUpdate = Calendar.current.date(byAdding: .minute, value: 5, to: Date())! + let timeline = Timeline(entries: [entry], policy: .after(nextUpdate)) + completion(timeline) + } + + private func loadBookings() -> [BookingData] { + guard let userDefaults = UserDefaults(suiteName: "group.com.cal.companion") else { + return [] + } + + if let jsonString = userDefaults.string(forKey: "widgetBookings"), + let data = jsonString.data(using: .utf8), + let widgetData = try? JSONDecoder().decode(WidgetData.self, from: data) { + return widgetData.bookings + } + + if let data = userDefaults.data(forKey: "widgetBookings"), + let widgetData = try? JSONDecoder().decode(WidgetData.self, from: data) { + return widgetData.bookings + } + + return [] + } +} + +struct BookingEntry: TimelineEntry { + let date: Date + let bookings: [BookingData] +} + +// MARK: - Booking Row View + +struct BookingRowView: View { + let booking: BookingData + + var body: some View { + HStack(spacing: 8) { + // Left accent bar (color based on urgency) + RoundedRectangle(cornerRadius: 2) + .fill(accentColor) + .frame(width: 3) + + VStack(alignment: .leading, spacing: 2) { + // Title row with video icon + HStack(spacing: 4) { + Text(booking.title) + .font(.system(size: 13, weight: .semibold)) + .foregroundColor(.primary) + .lineLimit(1) + + if booking.hasVideoCall == true { + Image(systemName: "video.fill") + .font(.system(size: 10)) + .foregroundColor(.blue) + } + } + + // Date and time with countdown + HStack(spacing: 4) { + Text("\(booking.date) • \(booking.startTime)") + .font(.system(size: 11)) + .foregroundColor(.secondary) + + if let countdown = countdownText { + Text("•") + .font(.system(size: 11)) + .foregroundColor(.secondary) + Text(countdown) + .font(.system(size: 11, weight: .medium)) + .foregroundColor(countdownColor) + } + } + + // Attendee info + if let attendee = booking.attendeeName { + HStack(spacing: 4) { + // Attendee initial circle + Circle() + .fill(Color.accentColor.opacity(0.2)) + .frame(width: 16, height: 16) + .overlay( + Text(String(attendee.prefix(1)).uppercased()) + .font(.system(size: 9, weight: .semibold)) + .foregroundColor(.accentColor) + ) + Text(attendee) + .font(.system(size: 11)) + .foregroundColor(.secondary) + .lineLimit(1) + } + } + } + } + .padding(.vertical, 4) + } + + private var accentColor: Color { + if booking.isHappeningNow { + return .green + } else if booking.isStartingSoon { + return .orange + } + return .accentColor + } + + private var countdownText: String? { + guard let minutes = booking.minutesUntilStart else { return nil } + if minutes <= 0 { + return "Now" + } else if minutes < 60 { + return "In \(minutes)m" + } else if minutes < 1440 { + let hours = minutes / 60 + return "In \(hours)h" + } + return nil + } + + private var countdownColor: Color { + guard let minutes = booking.minutesUntilStart else { return .secondary } + if minutes <= 0 { + return .green + } else if minutes <= 30 { + return .orange + } + return .secondary + } +} + +// MARK: - Widget Entry View + +struct UpcomingBookingsWidgetEntryView: View { + var entry: Provider.Entry + @Environment(\.widgetFamily) var family + + var body: some View { + ZStack { + // Subtle gradient background + LinearGradient( + gradient: Gradient(colors: [ + Color.accentColor.opacity(0.05), + Color.clear + ]), + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + + VStack(alignment: .leading, spacing: 0) { + // Header + HStack { + Image(systemName: "calendar") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.accentColor) + Text("Upcoming") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.primary) + Spacer() + } + .padding(.bottom, 8) + + if entry.bookings.isEmpty { + Spacer() + VStack(spacing: 4) { + Image(systemName: "calendar.badge.checkmark") + .font(.system(size: 24)) + .foregroundColor(.secondary) + Text("No upcoming bookings") + .font(.system(size: 12)) + .foregroundColor(.secondary) + } + .frame(maxWidth: .infinity) + Spacer() + } else { + if family == .systemMedium { + // Horizontal layout for medium widget + HStack(alignment: .top, spacing: 12) { + ForEach(entry.bookings.prefix(2)) { booking in + MediumBookingCard(booking: booking) + } + } + Spacer(minLength: 0) + } else { + // Vertical layout for small and large widgets + let maxBookings = family == .systemSmall ? 2 : 6 + ForEach(entry.bookings.prefix(maxBookings)) { booking in + Link(destination: URL(string: "calcom://(tabs)/(bookings)/booking-detail?uid=\(booking.id)")!) { + BookingRowView(booking: booking) + } + if booking.id != entry.bookings.prefix(maxBookings).last?.id { + Divider() + } + } + Spacer(minLength: 0) + } + } + } + .padding(12) + } + .widgetURL(URL(string: "calcom://(tabs)/(bookings)")) + } +} + +// MARK: - Medium Widget Card + +struct MediumBookingCard: View { + let booking: BookingData + + var body: some View { + Link(destination: URL(string: "calcom://(tabs)/(bookings)/booking-detail?uid=\(booking.id)")!) { + HStack(spacing: 6) { + // Left accent bar + RoundedRectangle(cornerRadius: 2) + .fill(accentColor) + .frame(width: 3) + + VStack(alignment: .leading, spacing: 3) { + // Title with video icon + HStack(spacing: 3) { + Text(booking.title) + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.primary) + .lineLimit(1) + + if booking.hasVideoCall == true { + Image(systemName: "video.fill") + .font(.system(size: 8)) + .foregroundColor(.blue) + } + } + + // Date + HStack(spacing: 3) { + Image(systemName: "calendar") + .font(.system(size: 9)) + .foregroundColor(.secondary) + Text(booking.date) + .font(.system(size: 10)) + .foregroundColor(.secondary) + } + + // Time with countdown + HStack(spacing: 3) { + Image(systemName: "clock") + .font(.system(size: 9)) + .foregroundColor(.secondary) + Text(booking.startTime) + .font(.system(size: 10)) + .foregroundColor(.secondary) + + if let countdown = countdownText { + Text("• \(countdown)") + .font(.system(size: 10, weight: .medium)) + .foregroundColor(countdownColor) + } + } + + // Attendee + if let attendee = booking.attendeeName { + HStack(spacing: 3) { + Circle() + .fill(Color.accentColor.opacity(0.2)) + .frame(width: 14, height: 14) + .overlay( + Text(String(attendee.prefix(1)).uppercased()) + .font(.system(size: 8, weight: .semibold)) + .foregroundColor(.accentColor) + ) + Text(attendee) + .font(.system(size: 10)) + .foregroundColor(.secondary) + .lineLimit(1) + } + } + } + } + .frame(maxWidth: .infinity, alignment: .leading) + } + } + + private var accentColor: Color { + if booking.isHappeningNow { + return .green + } else if booking.isStartingSoon { + return .orange + } + return .accentColor + } + + private var countdownText: String? { + guard let minutes = booking.minutesUntilStart else { return nil } + if minutes <= 0 { + return "Now" + } else if minutes < 60 { + return "In \(minutes)m" + } else if minutes < 1440 { + let hours = minutes / 60 + return "In \(hours)h" + } + return nil + } + + private var countdownColor: Color { + guard let minutes = booking.minutesUntilStart else { return .secondary } + if minutes <= 0 { + return .green + } else if minutes <= 30 { + return .orange + } + return .secondary + } +} + +// MARK: - Widget Configuration + +struct UpcomingBookingsWidget: Widget { + let kind: String = "UpcomingBookingsWidget" + + var body: some WidgetConfiguration { + StaticConfiguration(kind: kind, provider: Provider()) { entry in + UpcomingBookingsWidgetEntryView(entry: entry) + .containerBackground(.fill.tertiary, for: .widget) + } + .configurationDisplayName("Upcoming Bookings") + .description("View your upcoming Cal.com bookings at a glance.") + .supportedFamilies([.systemSmall, .systemMedium, .systemLarge]) + } +} + +// MARK: - Previews + +#Preview(as: .systemSmall) { + UpcomingBookingsWidget() +} timeline: { + BookingEntry(date: .now, bookings: [ + BookingData(id: "1", title: "Team Standup", date: "Mon, Feb 3", startTime: "10:00 AM", endTime: "10:30 AM", startTimeISO: ISO8601DateFormatter().string(from: Date().addingTimeInterval(1800)), attendeeName: "John Doe", hostName: "You", location: nil, hasVideoCall: true), + BookingData(id: "2", title: "Product Review", date: "Mon, Feb 3", startTime: "2:00 PM", endTime: "3:00 PM", startTimeISO: nil, attendeeName: "Jane Smith", hostName: "You", location: nil, hasVideoCall: false) + ]) + BookingEntry(date: .now, bookings: []) +} + +#Preview(as: .systemMedium) { + UpcomingBookingsWidget() +} timeline: { + BookingEntry(date: .now, bookings: [ + BookingData(id: "1", title: "Team Standup", date: "Mon, Feb 3", startTime: "10:00 AM", endTime: "10:30 AM", startTimeISO: ISO8601DateFormatter().string(from: Date().addingTimeInterval(600)), attendeeName: "John Doe", hostName: "You", location: nil, hasVideoCall: true), + BookingData(id: "2", title: "Product Review", date: "Mon, Feb 3", startTime: "2:00 PM", endTime: "3:00 PM", startTimeISO: nil, attendeeName: "Jane Smith", hostName: "You", location: "Zoom", hasVideoCall: true) + ]) +} + +#Preview(as: .systemLarge) { + UpcomingBookingsWidget() +} timeline: { + BookingEntry(date: .now, bookings: [ + BookingData(id: "1", title: "Team Standup", date: "Mon, Feb 3", startTime: "10:00 AM", endTime: "10:30 AM", startTimeISO: nil, attendeeName: "John Doe", hostName: "You", location: nil, hasVideoCall: true), + BookingData(id: "2", title: "Product Review", date: "Mon, Feb 3", startTime: "2:00 PM", endTime: "3:00 PM", startTimeISO: nil, attendeeName: "Jane Smith", hostName: "You", location: nil, hasVideoCall: false), + BookingData(id: "3", title: "Client Call", date: "Tue, Feb 4", startTime: "4:00 PM", endTime: "5:00 PM", startTimeISO: nil, attendeeName: "Bob Wilson", hostName: "You", location: nil, hasVideoCall: true), + BookingData(id: "4", title: "Interview", date: "Tue, Feb 4", startTime: "5:30 PM", endTime: "6:00 PM", startTimeISO: nil, attendeeName: "Alice Johnson", hostName: "You", location: nil, hasVideoCall: false), + BookingData(id: "5", title: "Wrap Up", date: "Wed, Feb 5", startTime: "6:00 PM", endTime: "6:15 PM", startTimeISO: nil, attendeeName: "Team", hostName: "You", location: nil, hasVideoCall: false) + ]) +} diff --git a/companion/utils/widgetStorage.android.ts b/companion/utils/widgetStorage.android.ts new file mode 100644 index 0000000000..f346e6f1f9 --- /dev/null +++ b/companion/utils/widgetStorage.android.ts @@ -0,0 +1,53 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { requestWidgetUpdate } from "react-native-android-widget"; +import { UpcomingBookingsWidget } from "@/widgets/UpcomingBookingsWidget"; +import { + type BookingInput, + type WidgetData, + ANDROID_WIDGET_STORAGE_KEY, + transformBookingsToWidgetData, +} from "./widgetStorage.shared"; + +async function updateAndroidWidget(widgetData: WidgetData): Promise { + await AsyncStorage.setItem(ANDROID_WIDGET_STORAGE_KEY, JSON.stringify(widgetData)); + + try { + await requestWidgetUpdate({ + widgetName: "UpcomingBookingsWidget", + renderWidget: () => UpcomingBookingsWidget({ bookings: widgetData.bookings }), + widgetNotFound: () => { + console.warn("Widget not found on home screen"); + }, + }); + } catch (error) { + console.warn("Failed to request Android widget update:", error); + } +} + +export async function updateWidgetBookings(bookings: BookingInput[]): Promise { + if (__DEV__) { + console.log("[Widget Debug] updateWidgetBookings called with", bookings.length, "bookings"); + } + + try { + const widgetData = transformBookingsToWidgetData(bookings); + await updateAndroidWidget(widgetData); + } catch (error) { + console.warn("Failed to update widget bookings:", error); + } +} + +export async function clearWidgetBookings(): Promise { + try { + const emptyData: WidgetData = { + bookings: [], + lastUpdated: new Date().toISOString(), + }; + await updateAndroidWidget(emptyData); + } catch (error) { + console.warn("Failed to clear widget bookings:", error); + } +} + +// Re-export shared utilities +export * from "./widgetStorage.shared"; diff --git a/companion/utils/widgetStorage.ios.ts b/companion/utils/widgetStorage.ios.ts new file mode 100644 index 0000000000..d145cb2892 --- /dev/null +++ b/companion/utils/widgetStorage.ios.ts @@ -0,0 +1,54 @@ +import { ExtensionStorage } from "@bacons/apple-targets"; +import { + type BookingInput, + type WidgetData, + APP_GROUP_IDENTIFIER, + WIDGET_BOOKINGS_KEY, + transformBookingsToWidgetData, +} from "./widgetStorage.shared"; + +const iosStorage = new ExtensionStorage(APP_GROUP_IDENTIFIER); + +async function updateIOSWidget(widgetData: WidgetData): Promise { + // biome-ignore lint/suspicious/noExplicitAny: ExtensionStorage.set() expects any for the value parameter + iosStorage.set(WIDGET_BOOKINGS_KEY, widgetData as any); + if (__DEV__) { + console.log("[Widget Debug] Data written to ExtensionStorage with key:", WIDGET_BOOKINGS_KEY); + } + + ExtensionStorage.reloadWidget(); + if (__DEV__) { + console.log("[Widget Debug] ExtensionStorage.reloadWidget() called"); + } +} + +export async function updateWidgetBookings(bookings: BookingInput[]): Promise { + if (__DEV__) { + console.log("[Widget Debug] updateWidgetBookings called with", bookings.length, "bookings"); + } + + try { + const widgetData = transformBookingsToWidgetData(bookings); + if (__DEV__) { + console.log("[Widget Debug] Platform is iOS, calling updateIOSWidget"); + } + await updateIOSWidget(widgetData); + } catch (error) { + console.warn("Failed to update widget bookings:", error); + } +} + +export async function clearWidgetBookings(): Promise { + try { + const emptyData: WidgetData = { + bookings: [], + lastUpdated: new Date().toISOString(), + }; + await updateIOSWidget(emptyData); + } catch (error) { + console.warn("Failed to clear widget bookings:", error); + } +} + +// Re-export shared utilities +export * from "./widgetStorage.shared"; diff --git a/companion/utils/widgetStorage.shared.ts b/companion/utils/widgetStorage.shared.ts new file mode 100644 index 0000000000..3ba9f656ae --- /dev/null +++ b/companion/utils/widgetStorage.shared.ts @@ -0,0 +1,106 @@ +import { AppState, type AppStateStatus } from "react-native"; + +export const APP_GROUP_IDENTIFIER = "group.com.cal.companion"; +export const WIDGET_BOOKINGS_KEY = "widgetBookings"; +export const ANDROID_WIDGET_STORAGE_KEY = "android_widget_bookings"; + +export interface WidgetBookingData { + id: string; + title: string; + date: string; + startTime: string; + endTime: string; + startTimeISO: string; + attendeeName: string | null; + hostName: string | null; + location: string | null; + hasVideoCall: boolean; +} + +export interface WidgetData { + bookings: WidgetBookingData[]; + lastUpdated: string | null; +} + +export function formatTime(dateString: string): string { + const date = new Date(dateString); + return date.toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + }); +} + +export function formatDate(dateString: string): string { + const date = new Date(dateString); + return date.toLocaleDateString("en-US", { + weekday: "short", + month: "short", + day: "numeric", + }); +} + +export interface BookingInput { + id: number; + uid: string; + title: string; + startTime?: string; + endTime?: string; + start?: string; + end?: string; + attendees?: Array<{ name: string; email: string }>; + hosts?: Array<{ name?: string; email?: string }>; + user?: { name?: string; email?: string }; + location?: string; +} + +export function transformBookingsToWidgetData(bookings: BookingInput[]): WidgetData { + const widgetBookings: WidgetBookingData[] = bookings.slice(0, 5).map((booking) => { + const startTimeStr = booking.startTime || booking.start || ""; + const endTimeStr = booking.endTime || booking.end || ""; + const hostName = booking.hosts?.[0]?.name || booking.user?.name || null; + const locationLower = (booking.location || "").toLowerCase(); + const hasVideoCall = + locationLower.includes("zoom") || + locationLower.includes("meet") || + locationLower.includes("teams") || + locationLower.includes("webex") || + locationLower.includes("cal video"); + + return { + id: booking.uid || String(booking.id), + title: booking.title, + date: formatDate(startTimeStr), + startTime: formatTime(startTimeStr), + endTime: formatTime(endTimeStr), + startTimeISO: startTimeStr, + attendeeName: booking.attendees?.[0]?.name || null, + hostName: hostName, + location: booking.location || null, + hasVideoCall: hasVideoCall, + }; + }); + + return { + bookings: widgetBookings, + lastUpdated: new Date().toISOString(), + }; +} + +export function setupWidgetRefreshOnAppStateChange( + fetchAndUpdateBookings: () => Promise +): () => void { + const handleAppStateChange = (nextAppState: AppStateStatus) => { + if (nextAppState === "background" || nextAppState === "inactive") { + fetchAndUpdateBookings().catch((error) => { + console.warn("Failed to refresh widget on app state change:", error); + }); + } + }; + + const subscription = AppState.addEventListener("change", handleAppStateChange); + + return () => { + subscription.remove(); + }; +} diff --git a/companion/utils/widgetStorage.ts b/companion/utils/widgetStorage.ts new file mode 100644 index 0000000000..1dc6d7f12b --- /dev/null +++ b/companion/utils/widgetStorage.ts @@ -0,0 +1,26 @@ +// This file serves as the base implementation for platforms without specific extensions. +// Metro bundler will prefer widgetStorage.ios.ts or widgetStorage.android.ts when available. + +import type { BookingInput } from "./widgetStorage.shared"; + +// Re-export shared types and utilities for consumers +export { + type WidgetBookingData, + type WidgetData, + type BookingInput, + setupWidgetRefreshOnAppStateChange, + formatTime, + formatDate, + transformBookingsToWidgetData, + APP_GROUP_IDENTIFIER, + WIDGET_BOOKINGS_KEY, + ANDROID_WIDGET_STORAGE_KEY, +} from "./widgetStorage.shared"; + +export async function updateWidgetBookings(_bookings: BookingInput[]): Promise { + console.warn("Widget updates are not supported on this platform"); +} + +export async function clearWidgetBookings(): Promise { + console.warn("Widget clearing is not supported on this platform"); +} diff --git a/companion/widgets/UpcomingBookingsWidget.tsx b/companion/widgets/UpcomingBookingsWidget.tsx new file mode 100644 index 0000000000..0df344eb95 --- /dev/null +++ b/companion/widgets/UpcomingBookingsWidget.tsx @@ -0,0 +1,246 @@ +"use no memo"; +import { FlexWidget, TextWidget } from "react-native-android-widget"; + +interface BookingData { + id: string; + title: string; + date: string; + startTime: string; + endTime: string; + startTimeISO?: string; + attendeeName: string | null; + hostName?: string | null; + location?: string | null; + hasVideoCall?: boolean; +} + +interface WidgetProps { + bookings: BookingData[]; +} + +// Get accent color based on start time proximity - returns HexColor type +function getAccentColor(startTimeISO?: string): `#${string}` { + if (!startTimeISO) return "#007AFF"; + try { + const startDate = new Date(startTimeISO); + const now = new Date(); + const minutes = Math.floor((startDate.getTime() - now.getTime()) / 60000); + if (minutes <= 0) return "#007AFF"; // Blue - already started or past + if (minutes <= 30) return "#FF9500"; // Orange - starting soon + return "#007AFF"; + } catch { + return "#007AFF"; + } +} + +// Get first initial from name +function getInitial(name: string | null): string { + if (!name) return ""; + return name.charAt(0).toUpperCase(); +} + +function BookingItem({ booking }: { booking: BookingData }) { + const accentColor = getAccentColor(booking.startTimeISO); + + return ( + + {/* Left accent bar */} + + + {/* Content */} + + {/* Title row with video icon */} + + + {booking.hasVideoCall && ( + + )} + + + {/* Date and time with countdown */} + + + + + {/* Attendee info with initial circle */} + {booking.attendeeName && ( + + {/* Initial circle */} + + + + + + )} + + + ); +} + +export function UpcomingBookingsWidget({ bookings }: WidgetProps) { + return ( + + {/* Header with calendar icon */} + + + + + + {bookings.length === 0 ? ( + + + + + ) : ( + + {bookings.slice(0, 4).map((booking) => ( + + ))} + + )} + + ); +} diff --git a/companion/widgets/index.ts b/companion/widgets/index.ts new file mode 100644 index 0000000000..63f3b9b6b5 --- /dev/null +++ b/companion/widgets/index.ts @@ -0,0 +1,2 @@ +export { UpcomingBookingsWidget } from "./UpcomingBookingsWidget"; +export { widgetTaskHandler } from "./widgetTaskHandler"; diff --git a/companion/widgets/widgetTaskHandler.tsx b/companion/widgets/widgetTaskHandler.tsx new file mode 100644 index 0000000000..85d227c64b --- /dev/null +++ b/companion/widgets/widgetTaskHandler.tsx @@ -0,0 +1,55 @@ +"use no memo"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import type { WidgetTaskHandlerProps } from "react-native-android-widget"; +import { UpcomingBookingsWidget } from "./UpcomingBookingsWidget"; + +const WIDGET_STORAGE_KEY = "android_widget_bookings"; + +interface BookingData { + id: string; + title: string; + date: string; + startTime: string; + endTime: string; + startTimeISO?: string; + attendeeName: string | null; + hostName?: string | null; + location?: string | null; + hasVideoCall?: boolean; +} + +async function getStoredBookings(): Promise { + try { + const data = await AsyncStorage.getItem(WIDGET_STORAGE_KEY); + if (data) { + const parsed = JSON.parse(data); + return parsed.bookings || []; + } + } catch (error) { + console.warn("Failed to get stored bookings for widget:", error); + } + return []; +} + +export async function widgetTaskHandler(props: WidgetTaskHandlerProps) { + switch (props.widgetAction) { + case "WIDGET_ADDED": + case "WIDGET_UPDATE": + case "WIDGET_RESIZED": { + const bookings = await getStoredBookings(); + props.renderWidget(); + break; + } + + case "WIDGET_CLICK": { + break; + } + + case "WIDGET_DELETED": { + break; + } + + default: + break; + } +}