feat: dual address auto-switch, custom icon, notifications, image support
- Add local/remote address with automatic failover (try local first, fall back to remote)
- Replace default Expo icon with custom PAILot teal airplane icon (all variants)
- Add local notification system (ObjC native module + ChatContext integration)
- Add Wake-on-LAN as fire-and-forget (never blocks connection)
- Add image send/receive with camera and photo library picker
- Add image caption modal (WhatsApp-style full-screen preview)
- Add session drawer, theme context, and dark/light mode cycling
- Add message persistence and per-session message storage
10 files added
25 files modified
| .. | .. |
|---|
| 1 | +--- |
|---|
| 2 | +pai: |
|---|
| 3 | + slug: "pailot" |
|---|
| 4 | + registered: "2026-03-05" |
|---|
| 5 | + last_indexed: null |
|---|
| 6 | + status: active |
|---|
| 7 | +--- |
|---|
| 8 | + |
|---|
| 9 | +# pailot |
|---|
| 10 | + |
|---|
| 11 | +<!-- Everything below the YAML frontmatter is yours — PAI never modifies content here. --> |
|---|
| 12 | +<!-- Use this file for project notes, decisions, preferences, or anything you want. --> |
|---|
| 13 | +<!-- PAI only reads and updates the `pai:` block in the frontmatter above. --> |
|---|
| .. | .. |
|---|
| 1 | +# PAILot TODO |
|---|
| 2 | + |
|---|
| 3 | +## Bugs |
|---|
| 4 | + |
|---|
| 5 | +- [ ] **Auto-scroll hijacks reading position** — `MessageList.tsx` fires `scrollToEnd` on every `onContentSizeChange` and on `messages.length` change. If you're scrolled up reading older messages, new incoming messages yank you to the bottom. Fix: only auto-scroll when already near the bottom (track scroll offset, threshold ~100px). |
|---|
| 6 | +- [ ] **Text not selectable in message bubbles** — `MessageBubble.tsx` uses plain `<Text>` without `selectable={true}`. Cannot long-press to select/copy text from AI responses or own messages. |
|---|
| 7 | + |
|---|
| 8 | +## UX Improvements |
|---|
| 9 | + |
|---|
| 10 | +- [ ] **Show session name on each message** — Currently each bubble only shows the time (e.g. "13:42"). Since PAILot runs parallel sessions on one screen, each message should also display which session it came from or went to (e.g. "13:42 · whazaa" or "13:42 · AIBroker"). Requires: add `sessionId`/`sessionName` to the `Message` type, have the gateway include session info with each message, render it in `MessageBubble.tsx` next to the timestamp. |
|---|
| 11 | + |
|---|
| 12 | +## Features |
|---|
| 13 | + |
|---|
| 14 | +- [ ] **Multimodal upload (send images/photos/video/audio from phone)** — The app can *receive* images and voice, but there's no UI to *send* media from the phone to the AI session. Needs: image picker / camera access, new `WsOutgoing` type for images/files, gateway handler to route media to the active session, and backend support to process multimodal input. |
|---|
| 15 | +- [ ] **Relay-based connectivity** — PAILot currently only works on the local network (WebSocket to `localhost:8765`). For use outside home network: self-hosted relay on a VPS with encrypted tunnel (Tailscale, cloudflared), or APNs push relay. See AIBroker `PLAN-adapter-architecture.md` sections on relay. |
|---|
| 16 | +- [ ] **Session lifecycle from mobile** — List named PAI sessions, see which are running, launch/stop/switch from the phone. "Remote desktop for AI sessions." See AIBroker TODO. |
|---|
| 17 | + |
|---|
| 18 | +--- |
|---|
| 19 | + |
|---|
| 20 | +*Created: 2026-03-05* |
|---|
| .. | .. |
|---|
| 5 | 5 | "version": "1.0.0", |
|---|
| 6 | 6 | "orientation": "portrait", |
|---|
| 7 | 7 | "icon": "./assets/icon.png", |
|---|
| 8 | | - "userInterfaceStyle": "dark", |
|---|
| 8 | + "userInterfaceStyle": "automatic", |
|---|
| 9 | 9 | "newArchEnabled": true, |
|---|
| 10 | 10 | "scheme": "pailot", |
|---|
| 11 | 11 | "splash": { |
|---|
| .. | .. |
|---|
| 19 | 19 | "appleTeamId": "7KU642K5ZL", |
|---|
| 20 | 20 | "infoPlist": { |
|---|
| 21 | 21 | "NSMicrophoneUsageDescription": "PAILot needs microphone access for voice input.", |
|---|
| 22 | | - "NSSpeechRecognitionUsageDescription": "PAILot uses speech recognition to convert your voice to text.", |
|---|
| 22 | + "NSPhotoLibraryUsageDescription": "PAILot needs photo library access to send images.", |
|---|
| 23 | + "NSCameraUsageDescription": "PAILot needs camera access to take photos.", |
|---|
| 23 | 24 | "UIBackgroundModes": [ |
|---|
| 24 | 25 | "audio" |
|---|
| 25 | 26 | ] |
|---|
| .. | .. |
|---|
| 34 | 35 | }, |
|---|
| 35 | 36 | "package": "org.mnsoft.pailot", |
|---|
| 36 | 37 | "permissions": [ |
|---|
| 37 | | - "RECORD_AUDIO" |
|---|
| 38 | + "RECORD_AUDIO", |
|---|
| 39 | + "READ_MEDIA_IMAGES", |
|---|
| 40 | + "CAMERA" |
|---|
| 38 | 41 | ] |
|---|
| 39 | 42 | }, |
|---|
| 40 | 43 | "web": { |
|---|
| .. | .. |
|---|
| 49 | 52 | "microphonePermission": "PAILot needs microphone access for voice input." |
|---|
| 50 | 53 | } |
|---|
| 51 | 54 | ], |
|---|
| 55 | + "expo-secure-store", |
|---|
| 52 | 56 | [ |
|---|
| 53 | | - "expo-speech-recognition", |
|---|
| 57 | + "expo-image-picker", |
|---|
| 54 | 58 | { |
|---|
| 55 | | - "microphonePermission": "PAILot needs microphone access for voice input.", |
|---|
| 56 | | - "speechRecognitionPermission": "PAILot uses speech recognition to convert your voice to text." |
|---|
| 59 | + "photosPermission": "PAILot needs photo library access to send images.", |
|---|
| 60 | + "cameraPermission": "PAILot needs camera access to take photos." |
|---|
| 57 | 61 | } |
|---|
| 58 | | - ], |
|---|
| 59 | | - "expo-secure-store" |
|---|
| 62 | + ] |
|---|
| 60 | 63 | ] |
|---|
| 61 | 64 | } |
|---|
| 62 | 65 | } |
|---|
| .. | .. |
|---|
| 2 | 2 | import { Stack } from "expo-router"; |
|---|
| 3 | 3 | import { ConnectionProvider } from "../contexts/ConnectionContext"; |
|---|
| 4 | 4 | import { ChatProvider } from "../contexts/ChatContext"; |
|---|
| 5 | +import { ThemeProvider, useTheme } from "../contexts/ThemeContext"; |
|---|
| 5 | 6 | import { StatusBar } from "expo-status-bar"; |
|---|
| 7 | + |
|---|
| 8 | +function InnerLayout() { |
|---|
| 9 | + const { isDark, colors } = useTheme(); |
|---|
| 10 | + return ( |
|---|
| 11 | + <> |
|---|
| 12 | + <StatusBar style={isDark ? "light" : "dark"} backgroundColor={colors.bg} /> |
|---|
| 13 | + <Stack |
|---|
| 14 | + screenOptions={{ |
|---|
| 15 | + headerShown: false, |
|---|
| 16 | + contentStyle: { backgroundColor: colors.bg }, |
|---|
| 17 | + animation: "slide_from_right", |
|---|
| 18 | + }} |
|---|
| 19 | + /> |
|---|
| 20 | + </> |
|---|
| 21 | + ); |
|---|
| 22 | +} |
|---|
| 6 | 23 | |
|---|
| 7 | 24 | export default function RootLayout() { |
|---|
| 8 | 25 | return ( |
|---|
| 9 | | - <ConnectionProvider> |
|---|
| 10 | | - <ChatProvider> |
|---|
| 11 | | - <StatusBar style="light" backgroundColor="#0A0A0F" /> |
|---|
| 12 | | - <Stack |
|---|
| 13 | | - screenOptions={{ |
|---|
| 14 | | - headerShown: false, |
|---|
| 15 | | - contentStyle: { backgroundColor: "#0A0A0F" }, |
|---|
| 16 | | - animation: "slide_from_right", |
|---|
| 17 | | - }} |
|---|
| 18 | | - /> |
|---|
| 19 | | - </ChatProvider> |
|---|
| 20 | | - </ConnectionProvider> |
|---|
| 26 | + <ThemeProvider> |
|---|
| 27 | + <ConnectionProvider> |
|---|
| 28 | + <ChatProvider> |
|---|
| 29 | + <InnerLayout /> |
|---|
| 30 | + </ChatProvider> |
|---|
| 31 | + </ConnectionProvider> |
|---|
| 32 | + </ThemeProvider> |
|---|
| 21 | 33 | ); |
|---|
| 22 | 34 | } |
|---|
| .. | .. |
|---|
| 1 | | -import React, { useCallback, useState } from "react"; |
|---|
| 2 | | -import { Pressable, Text, View } from "react-native"; |
|---|
| 1 | +import React, { useCallback, useEffect, useRef, useState } from "react"; |
|---|
| 2 | +import { ActionSheetIOS, Alert, KeyboardAvoidingView, Platform, Pressable, Text, View } from "react-native"; |
|---|
| 3 | 3 | import { SafeAreaView } from "react-native-safe-area-context"; |
|---|
| 4 | 4 | import { router } from "expo-router"; |
|---|
| 5 | 5 | import { useChat } from "../contexts/ChatContext"; |
|---|
| 6 | 6 | import { useConnection } from "../contexts/ConnectionContext"; |
|---|
| 7 | +import { useTheme } from "../contexts/ThemeContext"; |
|---|
| 7 | 8 | import { MessageList } from "../components/chat/MessageList"; |
|---|
| 8 | 9 | import { InputBar } from "../components/chat/InputBar"; |
|---|
| 9 | 10 | import { CommandBar, TextModeCommandBar } from "../components/chat/CommandBar"; |
|---|
| 11 | +import { ImageCaptionModal } from "../components/chat/ImageCaptionModal"; |
|---|
| 10 | 12 | import { StatusDot } from "../components/ui/StatusDot"; |
|---|
| 11 | | -import { SessionPicker } from "../components/SessionPicker"; |
|---|
| 12 | | -import { playAudio } from "../services/audio"; |
|---|
| 13 | +import { SessionDrawer } from "../components/SessionDrawer"; |
|---|
| 14 | +import { playAudio, stopPlayback, isPlaying, onPlayingChange } from "../services/audio"; |
|---|
| 15 | + |
|---|
| 16 | +interface StagedImage { |
|---|
| 17 | + base64: string; |
|---|
| 18 | + uri: string; |
|---|
| 19 | + mimeType: string; |
|---|
| 20 | +} |
|---|
| 13 | 21 | |
|---|
| 14 | 22 | export default function ChatScreen() { |
|---|
| 15 | | - const { messages, sendTextMessage, clearMessages, requestScreenshot } = |
|---|
| 23 | + const { messages, sendTextMessage, sendVoiceMessage, sendImageMessage, clearMessages, requestScreenshot, sessions } = |
|---|
| 16 | 24 | useChat(); |
|---|
| 17 | 25 | const { status } = useConnection(); |
|---|
| 26 | + const { colors, mode, cycleMode } = useTheme(); |
|---|
| 27 | + const themeIcon = mode === "dark" ? "🌙" : mode === "light" ? "☀️" : "📱"; |
|---|
| 28 | + const activeSessionName = sessions.find((s) => s.isActive)?.name ?? "PAILot"; |
|---|
| 18 | 29 | const [isTextMode, setIsTextMode] = useState(false); |
|---|
| 19 | 30 | const [showSessions, setShowSessions] = useState(false); |
|---|
| 31 | + const [audioPlaying, setAudioPlaying] = useState(false); |
|---|
| 32 | + const [stagedImage, setStagedImage] = useState<StagedImage | null>(null); |
|---|
| 20 | 33 | |
|---|
| 21 | | - const handleSessions = useCallback(() => { |
|---|
| 22 | | - setShowSessions(true); |
|---|
| 34 | + useEffect(() => { |
|---|
| 35 | + return onPlayingChange(setAudioPlaying); |
|---|
| 23 | 36 | }, []); |
|---|
| 24 | 37 | |
|---|
| 25 | 38 | const handleScreenshot = useCallback(() => { |
|---|
| 26 | 39 | requestScreenshot(); |
|---|
| 27 | | - router.push("/navigate"); |
|---|
| 28 | 40 | }, [requestScreenshot]); |
|---|
| 29 | 41 | |
|---|
| 30 | 42 | const handleHelp = useCallback(() => { |
|---|
| .. | .. |
|---|
| 39 | 51 | clearMessages(); |
|---|
| 40 | 52 | }, [clearMessages]); |
|---|
| 41 | 53 | |
|---|
| 54 | + // Resolve a picked asset into a StagedImage |
|---|
| 55 | + const stageAsset = useCallback(async (asset: { base64?: string | null; uri: string; mimeType?: string | null }) => { |
|---|
| 56 | + const mimeType = asset.mimeType ?? (asset.uri.endsWith(".png") ? "image/png" : "image/jpeg"); |
|---|
| 57 | + let base64 = asset.base64 ?? ""; |
|---|
| 58 | + if (!base64 && asset.uri) { |
|---|
| 59 | + const { readAsStringAsync } = await import("expo-file-system/legacy"); |
|---|
| 60 | + base64 = await readAsStringAsync(asset.uri, { encoding: "base64" }); |
|---|
| 61 | + } |
|---|
| 62 | + if (base64) { |
|---|
| 63 | + setStagedImage({ base64, uri: asset.uri, mimeType }); |
|---|
| 64 | + } |
|---|
| 65 | + }, []); |
|---|
| 66 | + |
|---|
| 67 | + const pickFromLibrary = useCallback(async () => { |
|---|
| 68 | + try { |
|---|
| 69 | + const ImagePicker = await import("expo-image-picker"); |
|---|
| 70 | + const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); |
|---|
| 71 | + if (status !== "granted") { |
|---|
| 72 | + Alert.alert("Permission needed", "Please allow photo library access in Settings."); |
|---|
| 73 | + return; |
|---|
| 74 | + } |
|---|
| 75 | + const result = await ImagePicker.launchImageLibraryAsync({ |
|---|
| 76 | + mediaTypes: ["images"], |
|---|
| 77 | + quality: 0.7, |
|---|
| 78 | + base64: true, |
|---|
| 79 | + }); |
|---|
| 80 | + if (result.canceled || !result.assets?.[0]) return; |
|---|
| 81 | + await stageAsset(result.assets[0]); |
|---|
| 82 | + } catch (err: any) { |
|---|
| 83 | + Alert.alert("Image Error", err?.message ?? String(err)); |
|---|
| 84 | + } |
|---|
| 85 | + }, [stageAsset]); |
|---|
| 86 | + |
|---|
| 87 | + const pickFromCamera = useCallback(async () => { |
|---|
| 88 | + try { |
|---|
| 89 | + const ImagePicker = await import("expo-image-picker"); |
|---|
| 90 | + const { status } = await ImagePicker.requestCameraPermissionsAsync(); |
|---|
| 91 | + if (status !== "granted") { |
|---|
| 92 | + Alert.alert("Permission needed", "Please allow camera access in Settings."); |
|---|
| 93 | + return; |
|---|
| 94 | + } |
|---|
| 95 | + const result = await ImagePicker.launchCameraAsync({ |
|---|
| 96 | + quality: 0.7, |
|---|
| 97 | + base64: true, |
|---|
| 98 | + }); |
|---|
| 99 | + if (result.canceled || !result.assets?.[0]) return; |
|---|
| 100 | + await stageAsset(result.assets[0]); |
|---|
| 101 | + } catch (err: any) { |
|---|
| 102 | + Alert.alert("Camera Error", err?.message ?? String(err)); |
|---|
| 103 | + } |
|---|
| 104 | + }, [stageAsset]); |
|---|
| 105 | + |
|---|
| 106 | + const handlePickImage = useCallback(() => { |
|---|
| 107 | + if (Platform.OS === "ios") { |
|---|
| 108 | + ActionSheetIOS.showActionSheetWithOptions( |
|---|
| 109 | + { |
|---|
| 110 | + options: ["Cancel", "Take Photo", "Choose from Library"], |
|---|
| 111 | + cancelButtonIndex: 0, |
|---|
| 112 | + }, |
|---|
| 113 | + (index) => { |
|---|
| 114 | + if (index === 1) pickFromCamera(); |
|---|
| 115 | + else if (index === 2) pickFromLibrary(); |
|---|
| 116 | + }, |
|---|
| 117 | + ); |
|---|
| 118 | + } else { |
|---|
| 119 | + // Android: just open library (camera is accessible from there) |
|---|
| 120 | + pickFromLibrary(); |
|---|
| 121 | + } |
|---|
| 122 | + }, [pickFromCamera, pickFromLibrary]); |
|---|
| 123 | + |
|---|
| 124 | + const handleImageSend = useCallback( |
|---|
| 125 | + (caption: string) => { |
|---|
| 126 | + if (!stagedImage) return; |
|---|
| 127 | + sendImageMessage(stagedImage.base64, caption, stagedImage.mimeType); |
|---|
| 128 | + setStagedImage(null); |
|---|
| 129 | + }, |
|---|
| 130 | + [stagedImage, sendImageMessage], |
|---|
| 131 | + ); |
|---|
| 132 | + |
|---|
| 42 | 133 | const handleReplay = useCallback(() => { |
|---|
| 134 | + if (isPlaying()) { |
|---|
| 135 | + stopPlayback(); |
|---|
| 136 | + return; |
|---|
| 137 | + } |
|---|
| 43 | 138 | for (let i = messages.length - 1; i >= 0; i--) { |
|---|
| 44 | 139 | const msg = messages[i]; |
|---|
| 45 | 140 | if (msg.role === "assistant") { |
|---|
| .. | .. |
|---|
| 52 | 147 | }, [messages]); |
|---|
| 53 | 148 | |
|---|
| 54 | 149 | return ( |
|---|
| 55 | | - <SafeAreaView style={{ flex: 1, backgroundColor: "#0A0A0F" }} edges={["top", "bottom"]}> |
|---|
| 150 | + <SafeAreaView style={{ flex: 1, backgroundColor: colors.bg }} edges={["top", "bottom"]}> |
|---|
| 151 | + <KeyboardAvoidingView |
|---|
| 152 | + style={{ flex: 1 }} |
|---|
| 153 | + behavior={Platform.OS === "ios" ? "padding" : undefined} |
|---|
| 154 | + keyboardVerticalOffset={0} |
|---|
| 155 | + > |
|---|
| 56 | 156 | {/* Header */} |
|---|
| 57 | 157 | <View |
|---|
| 58 | 158 | style={{ |
|---|
| .. | .. |
|---|
| 62 | 162 | paddingHorizontal: 16, |
|---|
| 63 | 163 | paddingVertical: 12, |
|---|
| 64 | 164 | borderBottomWidth: 1, |
|---|
| 65 | | - borderBottomColor: "#2E2E45", |
|---|
| 165 | + borderBottomColor: colors.border, |
|---|
| 66 | 166 | }} |
|---|
| 67 | 167 | > |
|---|
| 68 | | - <View style={{ flexDirection: "row", alignItems: "center", gap: 10 }}> |
|---|
| 69 | | - <Text |
|---|
| 70 | | - style={{ |
|---|
| 71 | | - color: "#E8E8F0", |
|---|
| 72 | | - fontSize: 22, |
|---|
| 73 | | - fontWeight: "800", |
|---|
| 74 | | - letterSpacing: -0.5, |
|---|
| 75 | | - }} |
|---|
| 168 | + <View style={{ flexDirection: "row", alignItems: "center", flex: 1, gap: 10 }}> |
|---|
| 169 | + <Pressable |
|---|
| 170 | + onPress={() => setShowSessions(true)} |
|---|
| 171 | + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 172 | + style={({ pressed }) => ({ |
|---|
| 173 | + width: 36, |
|---|
| 174 | + height: 36, |
|---|
| 175 | + alignItems: "center", |
|---|
| 176 | + justifyContent: "center", |
|---|
| 177 | + borderRadius: 18, |
|---|
| 178 | + backgroundColor: pressed ? colors.bgTertiary : colors.bgTertiary + "80", |
|---|
| 179 | + })} |
|---|
| 76 | 180 | > |
|---|
| 77 | | - PAILot |
|---|
| 78 | | - </Text> |
|---|
| 79 | | - <StatusDot status={status} size={8} /> |
|---|
| 181 | + <Text style={{ color: colors.textSecondary, fontSize: 18 }}>☰</Text> |
|---|
| 182 | + </Pressable> |
|---|
| 183 | + <Pressable |
|---|
| 184 | + onPress={() => setShowSessions(true)} |
|---|
| 185 | + style={{ flexDirection: "row", alignItems: "center", gap: 8, flex: 1 }} |
|---|
| 186 | + hitSlop={{ top: 6, bottom: 6, left: 0, right: 6 }} |
|---|
| 187 | + > |
|---|
| 188 | + <Text |
|---|
| 189 | + style={{ |
|---|
| 190 | + color: colors.text, |
|---|
| 191 | + fontSize: 22, |
|---|
| 192 | + fontWeight: "800", |
|---|
| 193 | + letterSpacing: -0.5, |
|---|
| 194 | + flexShrink: 1, |
|---|
| 195 | + }} |
|---|
| 196 | + numberOfLines={1} |
|---|
| 197 | + > |
|---|
| 198 | + {activeSessionName} |
|---|
| 199 | + </Text> |
|---|
| 200 | + <StatusDot status={status} size={8} /> |
|---|
| 201 | + </Pressable> |
|---|
| 80 | 202 | </View> |
|---|
| 81 | 203 | |
|---|
| 82 | | - <Pressable |
|---|
| 83 | | - onPress={() => router.push("/settings")} |
|---|
| 84 | | - hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }} |
|---|
| 85 | | - style={{ |
|---|
| 86 | | - width: 36, |
|---|
| 87 | | - height: 36, |
|---|
| 88 | | - alignItems: "center", |
|---|
| 89 | | - justifyContent: "center", |
|---|
| 90 | | - borderRadius: 18, |
|---|
| 91 | | - backgroundColor: "#1E1E2E", |
|---|
| 92 | | - }} |
|---|
| 93 | | - > |
|---|
| 94 | | - <Text style={{ fontSize: 15 }}>⚙️</Text> |
|---|
| 95 | | - </Pressable> |
|---|
| 204 | + <View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}> |
|---|
| 205 | + <Pressable |
|---|
| 206 | + onPress={cycleMode} |
|---|
| 207 | + hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }} |
|---|
| 208 | + style={({ pressed }) => ({ |
|---|
| 209 | + width: 36, |
|---|
| 210 | + height: 36, |
|---|
| 211 | + alignItems: "center", |
|---|
| 212 | + justifyContent: "center", |
|---|
| 213 | + borderRadius: 18, |
|---|
| 214 | + backgroundColor: pressed ? colors.bgTertiary : colors.bgTertiary + "80", |
|---|
| 215 | + })} |
|---|
| 216 | + > |
|---|
| 217 | + <Text style={{ fontSize: 15 }}>{themeIcon}</Text> |
|---|
| 218 | + </Pressable> |
|---|
| 219 | + <Pressable |
|---|
| 220 | + onPress={() => router.push("/settings")} |
|---|
| 221 | + hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }} |
|---|
| 222 | + style={{ |
|---|
| 223 | + width: 36, |
|---|
| 224 | + height: 36, |
|---|
| 225 | + alignItems: "center", |
|---|
| 226 | + justifyContent: "center", |
|---|
| 227 | + borderRadius: 18, |
|---|
| 228 | + backgroundColor: colors.bgTertiary, |
|---|
| 229 | + }} |
|---|
| 230 | + > |
|---|
| 231 | + <Text style={{ fontSize: 15 }}>⚙️</Text> |
|---|
| 232 | + </Pressable> |
|---|
| 233 | + </View> |
|---|
| 96 | 234 | </View> |
|---|
| 97 | 235 | |
|---|
| 98 | 236 | {/* Message list */} |
|---|
| .. | .. |
|---|
| 104 | 242 | width: 80, |
|---|
| 105 | 243 | height: 80, |
|---|
| 106 | 244 | borderRadius: 40, |
|---|
| 107 | | - backgroundColor: "#1E1E2E", |
|---|
| 245 | + backgroundColor: colors.bgTertiary, |
|---|
| 108 | 246 | alignItems: "center", |
|---|
| 109 | 247 | justifyContent: "center", |
|---|
| 110 | 248 | borderWidth: 1, |
|---|
| 111 | | - borderColor: "#2E2E45", |
|---|
| 249 | + borderColor: colors.border, |
|---|
| 112 | 250 | }} |
|---|
| 113 | 251 | > |
|---|
| 114 | 252 | <Text style={{ fontSize: 36 }}>🛩</Text> |
|---|
| 115 | 253 | </View> |
|---|
| 116 | 254 | <View style={{ alignItems: "center", gap: 6 }}> |
|---|
| 117 | | - <Text style={{ color: "#E8E8F0", fontSize: 20, fontWeight: "700" }}> |
|---|
| 255 | + <Text style={{ color: colors.text, fontSize: 20, fontWeight: "700" }}> |
|---|
| 118 | 256 | PAILot |
|---|
| 119 | 257 | </Text> |
|---|
| 120 | 258 | <Text |
|---|
| 121 | 259 | style={{ |
|---|
| 122 | | - color: "#5A5A78", |
|---|
| 260 | + color: colors.textMuted, |
|---|
| 123 | 261 | fontSize: 14, |
|---|
| 124 | 262 | textAlign: "center", |
|---|
| 125 | 263 | paddingHorizontal: 40, |
|---|
| .. | .. |
|---|
| 138 | 276 | {/* Command bar */} |
|---|
| 139 | 277 | {isTextMode ? ( |
|---|
| 140 | 278 | <TextModeCommandBar |
|---|
| 141 | | - onSessions={handleSessions} |
|---|
| 142 | 279 | onScreenshot={handleScreenshot} |
|---|
| 143 | 280 | onNavigate={handleNavigate} |
|---|
| 281 | + onPhoto={handlePickImage} |
|---|
| 282 | + onHelp={handleHelp} |
|---|
| 144 | 283 | onClear={handleClear} |
|---|
| 145 | 284 | /> |
|---|
| 146 | 285 | ) : ( |
|---|
| 147 | 286 | <CommandBar |
|---|
| 148 | | - onSessions={handleSessions} |
|---|
| 149 | 287 | onScreenshot={handleScreenshot} |
|---|
| 150 | | - onHelp={handleHelp} |
|---|
| 288 | + onNavigate={handleNavigate} |
|---|
| 289 | + onPhoto={handlePickImage} |
|---|
| 290 | + onClear={handleClear} |
|---|
| 151 | 291 | /> |
|---|
| 152 | 292 | )} |
|---|
| 153 | 293 | |
|---|
| 154 | 294 | {/* Input bar */} |
|---|
| 155 | 295 | <InputBar |
|---|
| 156 | 296 | onSendText={sendTextMessage} |
|---|
| 297 | + onVoiceRecorded={sendVoiceMessage} |
|---|
| 157 | 298 | onReplay={handleReplay} |
|---|
| 158 | 299 | isTextMode={isTextMode} |
|---|
| 159 | 300 | onToggleMode={() => setIsTextMode((v) => !v)} |
|---|
| 301 | + audioPlaying={audioPlaying} |
|---|
| 160 | 302 | /> |
|---|
| 161 | 303 | |
|---|
| 162 | | - {/* Session picker modal */} |
|---|
| 163 | | - <SessionPicker |
|---|
| 164 | | - visible={showSessions} |
|---|
| 165 | | - onClose={() => setShowSessions(false)} |
|---|
| 166 | | - /> |
|---|
| 304 | + </KeyboardAvoidingView> |
|---|
| 305 | + |
|---|
| 306 | + {/* Image caption modal — WhatsApp-style full-screen preview */} |
|---|
| 307 | + <ImageCaptionModal |
|---|
| 308 | + visible={!!stagedImage} |
|---|
| 309 | + imageUri={stagedImage ? `data:${stagedImage.mimeType};base64,${stagedImage.base64}` : ""} |
|---|
| 310 | + onSend={handleImageSend} |
|---|
| 311 | + onCancel={() => setStagedImage(null)} |
|---|
| 312 | + /> |
|---|
| 313 | + |
|---|
| 314 | + {/* Session drawer — absolute overlay outside KAV */} |
|---|
| 315 | + <SessionDrawer |
|---|
| 316 | + visible={showSessions} |
|---|
| 317 | + onClose={() => setShowSessions(false)} |
|---|
| 318 | + /> |
|---|
| 167 | 319 | </SafeAreaView> |
|---|
| 168 | 320 | ); |
|---|
| 169 | 321 | } |
|---|
| .. | .. |
|---|
| 9 | 9 | label: string; |
|---|
| 10 | 10 | key: string; |
|---|
| 11 | 11 | icon?: string; |
|---|
| 12 | | - wide?: boolean; |
|---|
| 12 | + flex?: number; |
|---|
| 13 | 13 | } |
|---|
| 14 | 14 | |
|---|
| 15 | | -const NAV_BUTTONS: NavButton[][] = [ |
|---|
| 15 | +const NAV_ROWS: NavButton[][] = [ |
|---|
| 16 | + // Row 1: Vi motion |
|---|
| 16 | 17 | [ |
|---|
| 17 | | - { label: "Esc", key: "escape" }, |
|---|
| 18 | | - { label: "Tab", key: "tab" }, |
|---|
| 19 | | - { label: "Enter", key: "enter" }, |
|---|
| 20 | | - { label: "Ctrl-C", key: "ctrl-c" }, |
|---|
| 18 | + { label: "0", key: "0" }, |
|---|
| 19 | + { label: "k", key: "k", icon: "↑" }, |
|---|
| 20 | + { label: "G", key: "G" }, |
|---|
| 21 | + { label: "dd", key: "dd" }, |
|---|
| 21 | 22 | ], |
|---|
| 23 | + // Row 2: Arrow keys |
|---|
| 22 | 24 | [ |
|---|
| 23 | | - { label: "", key: "left", icon: "←" }, |
|---|
| 24 | | - { label: "", key: "up", icon: "↑" }, |
|---|
| 25 | | - { label: "", key: "down", icon: "↓" }, |
|---|
| 26 | | - { label: "", key: "right", icon: "→" }, |
|---|
| 25 | + { label: "h", key: "h", icon: "←" }, |
|---|
| 26 | + { label: "j", key: "j", icon: "↓" }, |
|---|
| 27 | + { label: "l", key: "l", icon: "→" }, |
|---|
| 28 | + { label: "Esc", key: "escape" }, |
|---|
| 29 | + ], |
|---|
| 30 | + // Row 3: Action keys |
|---|
| 31 | + [ |
|---|
| 32 | + { label: "Tab", key: "tab" }, |
|---|
| 33 | + { label: "Enter", key: "enter", flex: 2 }, |
|---|
| 34 | + { label: "^C", key: "ctrl-c" }, |
|---|
| 27 | 35 | ], |
|---|
| 28 | 36 | ]; |
|---|
| 29 | 37 | |
|---|
| .. | .. |
|---|
| 119 | 127 | {/* Navigation buttons */} |
|---|
| 120 | 128 | <View |
|---|
| 121 | 129 | style={{ |
|---|
| 122 | | - paddingHorizontal: 12, |
|---|
| 123 | | - paddingBottom: 8, |
|---|
| 124 | | - gap: 8, |
|---|
| 130 | + paddingHorizontal: 16, |
|---|
| 131 | + paddingBottom: 12, |
|---|
| 132 | + gap: 10, |
|---|
| 125 | 133 | }} |
|---|
| 126 | 134 | > |
|---|
| 127 | | - {NAV_BUTTONS.map((row, rowIdx) => ( |
|---|
| 135 | + {NAV_ROWS.map((row, rowIdx) => ( |
|---|
| 128 | 136 | <View |
|---|
| 129 | 137 | key={rowIdx} |
|---|
| 130 | 138 | style={{ |
|---|
| 131 | 139 | flexDirection: "row", |
|---|
| 132 | | - gap: 8, |
|---|
| 133 | | - justifyContent: "center", |
|---|
| 140 | + gap: 10, |
|---|
| 134 | 141 | }} |
|---|
| 135 | 142 | > |
|---|
| 136 | 143 | {row.map((btn) => ( |
|---|
| .. | .. |
|---|
| 138 | 145 | key={btn.key} |
|---|
| 139 | 146 | onPress={() => handleNavPress(btn.key)} |
|---|
| 140 | 147 | style={({ pressed }) => ({ |
|---|
| 141 | | - flex: btn.wide ? 2 : 1, |
|---|
| 142 | | - height: 52, |
|---|
| 148 | + flex: btn.flex ?? 1, |
|---|
| 149 | + height: 56, |
|---|
| 143 | 150 | borderRadius: 14, |
|---|
| 144 | 151 | alignItems: "center", |
|---|
| 145 | 152 | justifyContent: "center", |
|---|
| 146 | 153 | backgroundColor: pressed ? "#4A9EFF" : "#1E1E2E", |
|---|
| 147 | | - borderWidth: 1, |
|---|
| 154 | + borderWidth: 1.5, |
|---|
| 148 | 155 | borderColor: pressed ? "#4A9EFF" : "#2E2E45", |
|---|
| 149 | 156 | })} |
|---|
| 150 | 157 | > |
|---|
| 151 | | - <Text |
|---|
| 152 | | - style={{ |
|---|
| 153 | | - color: "#E8E8F0", |
|---|
| 154 | | - fontSize: btn.icon ? 22 : 15, |
|---|
| 155 | | - fontWeight: "700", |
|---|
| 156 | | - }} |
|---|
| 157 | | - > |
|---|
| 158 | | - {btn.icon ?? btn.label} |
|---|
| 159 | | - </Text> |
|---|
| 158 | + {btn.icon ? ( |
|---|
| 159 | + <View style={{ alignItems: "center" }}> |
|---|
| 160 | + <Text style={{ color: "#E8E8F0", fontSize: 20, fontWeight: "700" }}> |
|---|
| 161 | + {btn.icon} |
|---|
| 162 | + </Text> |
|---|
| 163 | + <Text style={{ color: "#5A5A78", fontSize: 10, marginTop: 1 }}> |
|---|
| 164 | + {btn.label} |
|---|
| 165 | + </Text> |
|---|
| 166 | + </View> |
|---|
| 167 | + ) : ( |
|---|
| 168 | + <Text style={{ color: "#E8E8F0", fontSize: 16, fontWeight: "700" }}> |
|---|
| 169 | + {btn.label} |
|---|
| 170 | + </Text> |
|---|
| 171 | + )} |
|---|
| 160 | 172 | </Pressable> |
|---|
| 161 | 173 | ))} |
|---|
| 162 | 174 | </View> |
|---|
| .. | .. |
|---|
| 1 | 1 | import React, { useCallback, useState } from "react"; |
|---|
| 2 | 2 | import { |
|---|
| 3 | + Alert, |
|---|
| 3 | 4 | Keyboard, |
|---|
| 4 | 5 | KeyboardAvoidingView, |
|---|
| 5 | 6 | Platform, |
|---|
| .. | .. |
|---|
| 13 | 14 | import { SafeAreaView } from "react-native-safe-area-context"; |
|---|
| 14 | 15 | import { router } from "expo-router"; |
|---|
| 15 | 16 | import { useConnection } from "../contexts/ConnectionContext"; |
|---|
| 17 | +import { useTheme } from "../contexts/ThemeContext"; |
|---|
| 16 | 18 | import { StatusDot } from "../components/ui/StatusDot"; |
|---|
| 17 | 19 | import { ServerConfig } from "../types"; |
|---|
| 20 | +import { sendWol, isValidMac } from "../services/wol"; |
|---|
| 21 | +import { wsClient } from "../services/websocket"; |
|---|
| 18 | 22 | |
|---|
| 19 | 23 | export default function SettingsScreen() { |
|---|
| 20 | 24 | const { serverConfig, status, connect, disconnect, saveServerConfig } = |
|---|
| 21 | 25 | useConnection(); |
|---|
| 26 | + const { colors } = useTheme(); |
|---|
| 22 | 27 | |
|---|
| 23 | | - const [host, setHost] = useState(serverConfig?.host ?? "192.168.1.100"); |
|---|
| 28 | + const [host, setHost] = useState(serverConfig?.host ?? ""); |
|---|
| 29 | + const [localHost, setLocalHost] = useState(serverConfig?.localHost ?? ""); |
|---|
| 24 | 30 | const [port, setPort] = useState( |
|---|
| 25 | 31 | serverConfig?.port ? String(serverConfig.port) : "8765" |
|---|
| 26 | 32 | ); |
|---|
| 33 | + const [macAddress, setMacAddress] = useState(serverConfig?.macAddress ?? ""); |
|---|
| 27 | 34 | const [saved, setSaved] = useState(false); |
|---|
| 35 | + const [waking, setWaking] = useState(false); |
|---|
| 28 | 36 | |
|---|
| 29 | 37 | const handleSave = useCallback(async () => { |
|---|
| 30 | 38 | const trimmedHost = host.trim(); |
|---|
| 31 | 39 | const portNum = parseInt(port.trim(), 10); |
|---|
| 32 | 40 | |
|---|
| 33 | | - if (!trimmedHost || isNaN(portNum) || portNum < 1 || portNum > 65535) { |
|---|
| 41 | + const trimmedLocal = localHost.trim(); |
|---|
| 42 | + if ((!trimmedHost && !trimmedLocal) || isNaN(portNum) || portNum < 1 || portNum > 65535) { |
|---|
| 34 | 43 | return; |
|---|
| 35 | 44 | } |
|---|
| 36 | 45 | |
|---|
| 37 | | - const config: ServerConfig = { host: trimmedHost, port: portNum }; |
|---|
| 46 | + const trimmedMac = macAddress.trim(); |
|---|
| 47 | + const effectiveHost = trimmedHost || trimmedLocal; |
|---|
| 48 | + const config: ServerConfig = { |
|---|
| 49 | + host: effectiveHost, |
|---|
| 50 | + port: portNum, |
|---|
| 51 | + ...(trimmedLocal && trimmedHost ? { localHost: trimmedLocal } : {}), |
|---|
| 52 | + ...(trimmedMac ? { macAddress: trimmedMac } : {}), |
|---|
| 53 | + }; |
|---|
| 38 | 54 | await saveServerConfig(config); |
|---|
| 39 | 55 | setSaved(true); |
|---|
| 40 | 56 | setTimeout(() => setSaved(false), 2000); |
|---|
| 41 | | - }, [host, port, saveServerConfig]); |
|---|
| 57 | + }, [host, localHost, port, macAddress, saveServerConfig]); |
|---|
| 42 | 58 | |
|---|
| 43 | 59 | const handleConnect = useCallback(() => { |
|---|
| 44 | 60 | if (status === "connected" || status === "connecting") { |
|---|
| .. | .. |
|---|
| 48 | 64 | } |
|---|
| 49 | 65 | }, [status, connect, disconnect]); |
|---|
| 50 | 66 | |
|---|
| 51 | | - const isFormValid = host.trim().length > 0 && parseInt(port, 10) > 0; |
|---|
| 67 | + const handleWake = useCallback(async () => { |
|---|
| 68 | + const mac = macAddress.trim() || serverConfig?.macAddress; |
|---|
| 69 | + if (!mac || !isValidMac(mac)) { |
|---|
| 70 | + Alert.alert("Invalid MAC", "Enter a valid MAC address (e.g. 6a:8a:e7:b3:8e:5c)"); |
|---|
| 71 | + return; |
|---|
| 72 | + } |
|---|
| 73 | + setWaking(true); |
|---|
| 74 | + try { |
|---|
| 75 | + await sendWol(mac, host.trim() || serverConfig?.host); |
|---|
| 76 | + Alert.alert("WoL Sent", "Magic packet sent. The Mac should wake in a few seconds."); |
|---|
| 77 | + } catch (err) { |
|---|
| 78 | + Alert.alert("WoL Failed", err instanceof Error ? err.message : String(err)); |
|---|
| 79 | + } finally { |
|---|
| 80 | + setWaking(false); |
|---|
| 81 | + } |
|---|
| 82 | + }, [macAddress, host, serverConfig]); |
|---|
| 83 | + |
|---|
| 84 | + const isFormValid = (host.trim().length > 0 || localHost.trim().length > 0) && parseInt(port, 10) > 0; |
|---|
| 52 | 85 | |
|---|
| 53 | 86 | return ( |
|---|
| 54 | | - <SafeAreaView className="flex-1 bg-pai-bg" edges={["top", "bottom"]}> |
|---|
| 87 | + <SafeAreaView style={{ flex: 1, backgroundColor: colors.bg }} edges={["top", "bottom"]}> |
|---|
| 55 | 88 | <KeyboardAvoidingView |
|---|
| 56 | | - className="flex-1" |
|---|
| 89 | + style={{ flex: 1 }} |
|---|
| 57 | 90 | behavior={Platform.OS === "ios" ? "padding" : "height"} |
|---|
| 58 | 91 | > |
|---|
| 59 | 92 | <TouchableWithoutFeedback onPress={Keyboard.dismiss}> |
|---|
| 60 | 93 | <ScrollView |
|---|
| 61 | | - className="flex-1" |
|---|
| 94 | + style={{ flex: 1 }} |
|---|
| 62 | 95 | contentContainerStyle={{ paddingBottom: 32 }} |
|---|
| 63 | 96 | keyboardShouldPersistTaps="handled" |
|---|
| 64 | 97 | > |
|---|
| .. | .. |
|---|
| 70 | 103 | paddingHorizontal: 16, |
|---|
| 71 | 104 | paddingVertical: 12, |
|---|
| 72 | 105 | borderBottomWidth: 1, |
|---|
| 73 | | - borderBottomColor: "#2E2E45", |
|---|
| 106 | + borderBottomColor: colors.border, |
|---|
| 74 | 107 | }} |
|---|
| 75 | 108 | > |
|---|
| 76 | 109 | <Pressable |
|---|
| .. | .. |
|---|
| 82 | 115 | alignItems: "center", |
|---|
| 83 | 116 | justifyContent: "center", |
|---|
| 84 | 117 | borderRadius: 18, |
|---|
| 85 | | - backgroundColor: "#1E1E2E", |
|---|
| 118 | + backgroundColor: colors.bgTertiary, |
|---|
| 86 | 119 | marginRight: 12, |
|---|
| 87 | 120 | }} |
|---|
| 88 | 121 | > |
|---|
| 89 | | - <Text style={{ color: "#E8E8F0", fontSize: 16 }}>←</Text> |
|---|
| 122 | + <Text style={{ color: colors.text, fontSize: 16 }}>{"\u2190"}</Text> |
|---|
| 90 | 123 | </Pressable> |
|---|
| 91 | | - <Text style={{ color: "#E8E8F0", fontSize: 22, fontWeight: "800", letterSpacing: -0.5 }}> |
|---|
| 124 | + <Text style={{ color: colors.text, fontSize: 22, fontWeight: "800", letterSpacing: -0.5 }}> |
|---|
| 92 | 125 | Settings |
|---|
| 93 | 126 | </Text> |
|---|
| 94 | 127 | </View> |
|---|
| 95 | 128 | |
|---|
| 96 | | - <View className="px-4 mt-6"> |
|---|
| 129 | + <View style={{ paddingHorizontal: 16, marginTop: 24 }}> |
|---|
| 97 | 130 | {/* Connection status card */} |
|---|
| 98 | | - <View className="bg-pai-surface rounded-2xl p-4 mb-6"> |
|---|
| 99 | | - <Text className="text-pai-text-secondary text-xs font-medium uppercase tracking-widest mb-3"> |
|---|
| 131 | + <View |
|---|
| 132 | + style={{ |
|---|
| 133 | + backgroundColor: colors.bgTertiary, |
|---|
| 134 | + borderRadius: 16, |
|---|
| 135 | + padding: 16, |
|---|
| 136 | + marginBottom: 24, |
|---|
| 137 | + }} |
|---|
| 138 | + > |
|---|
| 139 | + <Text |
|---|
| 140 | + style={{ |
|---|
| 141 | + color: colors.textSecondary, |
|---|
| 142 | + fontSize: 11, |
|---|
| 143 | + fontWeight: "500", |
|---|
| 144 | + textTransform: "uppercase", |
|---|
| 145 | + letterSpacing: 1.5, |
|---|
| 146 | + marginBottom: 12, |
|---|
| 147 | + }} |
|---|
| 148 | + > |
|---|
| 100 | 149 | Connection Status |
|---|
| 101 | 150 | </Text> |
|---|
| 102 | | - <View className="flex-row items-center gap-3"> |
|---|
| 151 | + <View style={{ flexDirection: "row", alignItems: "center", gap: 12 }}> |
|---|
| 103 | 152 | <StatusDot status={status} size={12} /> |
|---|
| 104 | | - <Text className="text-pai-text text-base font-medium"> |
|---|
| 153 | + <Text style={{ color: colors.text, fontSize: 16, fontWeight: "500" }}> |
|---|
| 105 | 154 | {status === "connected" |
|---|
| 106 | 155 | ? "Connected" |
|---|
| 107 | 156 | : status === "connecting" |
|---|
| .. | .. |
|---|
| 110 | 159 | </Text> |
|---|
| 111 | 160 | </View> |
|---|
| 112 | 161 | {serverConfig && ( |
|---|
| 113 | | - <Text className="text-pai-text-muted text-sm mt-2"> |
|---|
| 114 | | - ws://{serverConfig.host}:{serverConfig.port} |
|---|
| 162 | + <Text style={{ color: colors.textMuted, fontSize: 14, marginTop: 8 }}> |
|---|
| 163 | + {wsClient.currentUrl || `ws://${serverConfig.host}:${serverConfig.port}`} |
|---|
| 115 | 164 | </Text> |
|---|
| 116 | 165 | )} |
|---|
| 117 | 166 | </View> |
|---|
| 118 | 167 | |
|---|
| 119 | 168 | {/* Server config */} |
|---|
| 120 | | - <Text className="text-pai-text-secondary text-xs font-medium uppercase tracking-widest mb-3"> |
|---|
| 169 | + <Text |
|---|
| 170 | + style={{ |
|---|
| 171 | + color: colors.textSecondary, |
|---|
| 172 | + fontSize: 11, |
|---|
| 173 | + fontWeight: "500", |
|---|
| 174 | + textTransform: "uppercase", |
|---|
| 175 | + letterSpacing: 1.5, |
|---|
| 176 | + marginBottom: 12, |
|---|
| 177 | + }} |
|---|
| 178 | + > |
|---|
| 121 | 179 | Server Configuration |
|---|
| 122 | 180 | </Text> |
|---|
| 123 | 181 | |
|---|
| 124 | | - <View className="bg-pai-surface rounded-2xl overflow-hidden mb-4"> |
|---|
| 125 | | - {/* Host */} |
|---|
| 126 | | - <View className="px-4 py-3 border-b border-pai-border"> |
|---|
| 127 | | - <Text className="text-pai-text-muted text-xs mb-1"> |
|---|
| 128 | | - Host / IP Address |
|---|
| 182 | + <View |
|---|
| 183 | + style={{ |
|---|
| 184 | + backgroundColor: colors.bgTertiary, |
|---|
| 185 | + borderRadius: 16, |
|---|
| 186 | + overflow: "hidden", |
|---|
| 187 | + marginBottom: 16, |
|---|
| 188 | + }} |
|---|
| 189 | + > |
|---|
| 190 | + {/* Local Host (preferred when on same network) */} |
|---|
| 191 | + <View |
|---|
| 192 | + style={{ |
|---|
| 193 | + paddingHorizontal: 16, |
|---|
| 194 | + paddingVertical: 12, |
|---|
| 195 | + borderBottomWidth: 1, |
|---|
| 196 | + borderBottomColor: colors.border, |
|---|
| 197 | + }} |
|---|
| 198 | + > |
|---|
| 199 | + <Text style={{ color: colors.textMuted, fontSize: 11, marginBottom: 4 }}> |
|---|
| 200 | + Local Address (optional) |
|---|
| 201 | + </Text> |
|---|
| 202 | + <TextInput |
|---|
| 203 | + value={localHost} |
|---|
| 204 | + onChangeText={setLocalHost} |
|---|
| 205 | + placeholder="192.168.1.100" |
|---|
| 206 | + placeholderTextColor={colors.textMuted} |
|---|
| 207 | + autoCapitalize="none" |
|---|
| 208 | + autoCorrect={false} |
|---|
| 209 | + keyboardType="url" |
|---|
| 210 | + style={{ color: colors.text, fontSize: 16, padding: 0 }} |
|---|
| 211 | + /> |
|---|
| 212 | + </View> |
|---|
| 213 | + |
|---|
| 214 | + {/* Remote Host (fallback / external) */} |
|---|
| 215 | + <View |
|---|
| 216 | + style={{ |
|---|
| 217 | + paddingHorizontal: 16, |
|---|
| 218 | + paddingVertical: 12, |
|---|
| 219 | + borderBottomWidth: 1, |
|---|
| 220 | + borderBottomColor: colors.border, |
|---|
| 221 | + }} |
|---|
| 222 | + > |
|---|
| 223 | + <Text style={{ color: colors.textMuted, fontSize: 11, marginBottom: 4 }}> |
|---|
| 224 | + Remote Address |
|---|
| 129 | 225 | </Text> |
|---|
| 130 | 226 | <TextInput |
|---|
| 131 | 227 | value={host} |
|---|
| 132 | 228 | onChangeText={setHost} |
|---|
| 133 | | - placeholder="192.168.1.100" |
|---|
| 134 | | - placeholderTextColor="#5A5A78" |
|---|
| 229 | + placeholder="myhost.example.com" |
|---|
| 230 | + placeholderTextColor={colors.textMuted} |
|---|
| 135 | 231 | autoCapitalize="none" |
|---|
| 136 | 232 | autoCorrect={false} |
|---|
| 137 | 233 | keyboardType="url" |
|---|
| 138 | | - style={{ color: "#E8E8F0", fontSize: 16, padding: 0 }} |
|---|
| 234 | + style={{ color: colors.text, fontSize: 16, padding: 0 }} |
|---|
| 139 | 235 | /> |
|---|
| 140 | 236 | </View> |
|---|
| 141 | 237 | |
|---|
| 142 | 238 | {/* Port */} |
|---|
| 143 | | - <View className="px-4 py-3"> |
|---|
| 144 | | - <Text className="text-pai-text-muted text-xs mb-1"> |
|---|
| 239 | + <View |
|---|
| 240 | + style={{ |
|---|
| 241 | + paddingHorizontal: 16, |
|---|
| 242 | + paddingVertical: 12, |
|---|
| 243 | + borderBottomWidth: 1, |
|---|
| 244 | + borderBottomColor: colors.border, |
|---|
| 245 | + }} |
|---|
| 246 | + > |
|---|
| 247 | + <Text style={{ color: colors.textMuted, fontSize: 11, marginBottom: 4 }}> |
|---|
| 145 | 248 | Port |
|---|
| 146 | 249 | </Text> |
|---|
| 147 | 250 | <TextInput |
|---|
| 148 | 251 | value={port} |
|---|
| 149 | 252 | onChangeText={setPort} |
|---|
| 150 | 253 | placeholder="8765" |
|---|
| 151 | | - placeholderTextColor="#5A5A78" |
|---|
| 254 | + placeholderTextColor={colors.textMuted} |
|---|
| 152 | 255 | keyboardType="number-pad" |
|---|
| 153 | | - style={{ color: "#E8E8F0", fontSize: 16, padding: 0 }} |
|---|
| 256 | + style={{ color: colors.text, fontSize: 16, padding: 0 }} |
|---|
| 257 | + /> |
|---|
| 258 | + </View> |
|---|
| 259 | + |
|---|
| 260 | + {/* MAC Address for Wake-on-LAN */} |
|---|
| 261 | + <View style={{ paddingHorizontal: 16, paddingVertical: 12 }}> |
|---|
| 262 | + <Text style={{ color: colors.textMuted, fontSize: 11, marginBottom: 4 }}> |
|---|
| 263 | + MAC Address (Wake-on-LAN) |
|---|
| 264 | + </Text> |
|---|
| 265 | + <TextInput |
|---|
| 266 | + value={macAddress} |
|---|
| 267 | + onChangeText={setMacAddress} |
|---|
| 268 | + placeholder="6a:8a:e7:b3:8e:5c" |
|---|
| 269 | + placeholderTextColor={colors.textMuted} |
|---|
| 270 | + autoCapitalize="none" |
|---|
| 271 | + autoCorrect={false} |
|---|
| 272 | + style={{ color: colors.text, fontSize: 16, padding: 0 }} |
|---|
| 154 | 273 | /> |
|---|
| 155 | 274 | </View> |
|---|
| 156 | 275 | </View> |
|---|
| .. | .. |
|---|
| 159 | 278 | <Pressable |
|---|
| 160 | 279 | onPress={handleSave} |
|---|
| 161 | 280 | disabled={!isFormValid} |
|---|
| 162 | | - className={`rounded-2xl py-4 items-center mb-3 ${ |
|---|
| 163 | | - isFormValid ? "bg-pai-accent" : "bg-pai-surface" |
|---|
| 164 | | - }`} |
|---|
| 281 | + style={{ |
|---|
| 282 | + borderRadius: 16, |
|---|
| 283 | + paddingVertical: 16, |
|---|
| 284 | + alignItems: "center", |
|---|
| 285 | + marginBottom: 12, |
|---|
| 286 | + backgroundColor: isFormValid ? colors.accent : colors.bgTertiary, |
|---|
| 287 | + }} |
|---|
| 165 | 288 | > |
|---|
| 166 | 289 | <Text |
|---|
| 167 | | - className={`text-base font-semibold ${ |
|---|
| 168 | | - isFormValid ? "text-white" : "text-pai-text-muted" |
|---|
| 169 | | - }`} |
|---|
| 290 | + style={{ |
|---|
| 291 | + fontSize: 16, |
|---|
| 292 | + fontWeight: "600", |
|---|
| 293 | + color: isFormValid ? "#FFF" : colors.textMuted, |
|---|
| 294 | + }} |
|---|
| 170 | 295 | > |
|---|
| 171 | 296 | {saved ? "Saved!" : "Save Configuration"} |
|---|
| 297 | + </Text> |
|---|
| 298 | + </Pressable> |
|---|
| 299 | + |
|---|
| 300 | + {/* Wake-on-LAN button */} |
|---|
| 301 | + <Pressable |
|---|
| 302 | + onPress={handleWake} |
|---|
| 303 | + disabled={waking || (!macAddress.trim() && !serverConfig?.macAddress)} |
|---|
| 304 | + style={{ |
|---|
| 305 | + borderRadius: 16, |
|---|
| 306 | + paddingVertical: 16, |
|---|
| 307 | + alignItems: "center", |
|---|
| 308 | + marginBottom: 12, |
|---|
| 309 | + backgroundColor: |
|---|
| 310 | + macAddress.trim() || serverConfig?.macAddress |
|---|
| 311 | + ? "#FF950033" |
|---|
| 312 | + : colors.bgTertiary, |
|---|
| 313 | + }} |
|---|
| 314 | + > |
|---|
| 315 | + <Text |
|---|
| 316 | + style={{ |
|---|
| 317 | + fontSize: 16, |
|---|
| 318 | + fontWeight: "600", |
|---|
| 319 | + color: |
|---|
| 320 | + macAddress.trim() || serverConfig?.macAddress |
|---|
| 321 | + ? "#FF9500" |
|---|
| 322 | + : colors.textMuted, |
|---|
| 323 | + }} |
|---|
| 324 | + > |
|---|
| 325 | + {waking ? "Sending..." : "Wake Mac (WoL)"} |
|---|
| 172 | 326 | </Text> |
|---|
| 173 | 327 | </Pressable> |
|---|
| 174 | 328 | |
|---|
| .. | .. |
|---|
| 176 | 330 | <Pressable |
|---|
| 177 | 331 | onPress={handleConnect} |
|---|
| 178 | 332 | disabled={!serverConfig} |
|---|
| 179 | | - className={`rounded-2xl py-4 items-center ${ |
|---|
| 180 | | - status === "connected" |
|---|
| 181 | | - ? "bg-pai-error/20" |
|---|
| 182 | | - : "bg-pai-success/20" |
|---|
| 183 | | - }`} |
|---|
| 333 | + style={{ |
|---|
| 334 | + borderRadius: 16, |
|---|
| 335 | + paddingVertical: 16, |
|---|
| 336 | + alignItems: "center", |
|---|
| 337 | + backgroundColor: |
|---|
| 338 | + status === "connected" |
|---|
| 339 | + ? colors.danger + "33" |
|---|
| 340 | + : "#2ED57333", |
|---|
| 341 | + }} |
|---|
| 184 | 342 | > |
|---|
| 185 | 343 | <Text |
|---|
| 186 | | - className={`text-base font-semibold ${ |
|---|
| 187 | | - status === "connected" |
|---|
| 188 | | - ? "text-pai-error" |
|---|
| 189 | | - : "text-pai-success" |
|---|
| 190 | | - }`} |
|---|
| 344 | + style={{ |
|---|
| 345 | + fontSize: 16, |
|---|
| 346 | + fontWeight: "600", |
|---|
| 347 | + color: status === "connected" ? colors.danger : "#2ED573", |
|---|
| 348 | + }} |
|---|
| 191 | 349 | > |
|---|
| 192 | 350 | {status === "connected" |
|---|
| 193 | 351 | ? "Disconnect" |
|---|
| .. | .. |
|---|
| 1 | +{ |
|---|
| 2 | + "lockfileVersion": 1, |
|---|
| 3 | + "configVersion": 0, |
|---|
| 4 | + "workspaces": { |
|---|
| 5 | + "": { |
|---|
| 6 | + "name": "pailot", |
|---|
| 7 | + "dependencies": { |
|---|
| 8 | + "@react-navigation/bottom-tabs": "^7.15.3", |
|---|
| 9 | + "@react-navigation/native": "^7.1.31", |
|---|
| 10 | + "expo": "~55.0.4", |
|---|
| 11 | + "expo-audio": "^55.0.8", |
|---|
| 12 | + "expo-constants": "~55.0.7", |
|---|
| 13 | + "expo-file-system": "~55.0.10", |
|---|
| 14 | + "expo-haptics": "~55.0.8", |
|---|
| 15 | + "expo-image-picker": "~55.0.11", |
|---|
| 16 | + "expo-linking": "~55.0.7", |
|---|
| 17 | + "expo-router": "~55.0.3", |
|---|
| 18 | + "expo-secure-store": "~55.0.8", |
|---|
| 19 | + "expo-sharing": "~55.0.11", |
|---|
| 20 | + "expo-splash-screen": "~55.0.10", |
|---|
| 21 | + "expo-status-bar": "~55.0.4", |
|---|
| 22 | + "expo-system-ui": "~55.0.9", |
|---|
| 23 | + "expo-web-browser": "~55.0.9", |
|---|
| 24 | + "nativewind": "^4", |
|---|
| 25 | + "react": "19.2.0", |
|---|
| 26 | + "react-dom": "^19.2.4", |
|---|
| 27 | + "react-native": "0.83.2", |
|---|
| 28 | + "react-native-draggable-flatlist": "^4.0.3", |
|---|
| 29 | + "react-native-gesture-handler": "~2.30.0", |
|---|
| 30 | + "react-native-reanimated": "4.2.1", |
|---|
| 31 | + "react-native-safe-area-context": "~5.6.2", |
|---|
| 32 | + "react-native-screens": "~4.23.0", |
|---|
| 33 | + "react-native-svg": "15.15.3", |
|---|
| 34 | + "react-native-udp": "^4.1.7", |
|---|
| 35 | + "react-native-web": "^0.21.0", |
|---|
| 36 | + "react-native-worklets": "0.7.2", |
|---|
| 37 | + }, |
|---|
| 38 | + "devDependencies": { |
|---|
| 39 | + "@types/react": "~19.2.2", |
|---|
| 40 | + "babel-plugin-module-resolver": "^5.0.2", |
|---|
| 41 | + "babel-preset-expo": "^55.0.10", |
|---|
| 42 | + "tailwindcss": "^3.4.19", |
|---|
| 43 | + "typescript": "~5.9.2", |
|---|
| 44 | + }, |
|---|
| 45 | + }, |
|---|
| 46 | + }, |
|---|
| 47 | + "packages": { |
|---|
| 48 | + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], |
|---|
| 49 | + |
|---|
| 50 | + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], |
|---|
| 51 | + |
|---|
| 52 | + "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], |
|---|
| 53 | + |
|---|
| 54 | + "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], |
|---|
| 55 | + |
|---|
| 56 | + "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], |
|---|
| 57 | + |
|---|
| 58 | + "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], |
|---|
| 59 | + |
|---|
| 60 | + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], |
|---|
| 61 | + |
|---|
| 62 | + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="], |
|---|
| 63 | + |
|---|
| 64 | + "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw=="], |
|---|
| 65 | + |
|---|
| 66 | + "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.6", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA=="], |
|---|
| 67 | + |
|---|
| 68 | + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], |
|---|
| 69 | + |
|---|
| 70 | + "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="], |
|---|
| 71 | + |
|---|
| 72 | + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], |
|---|
| 73 | + |
|---|
| 74 | + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], |
|---|
| 75 | + |
|---|
| 76 | + "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], |
|---|
| 77 | + |
|---|
| 78 | + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], |
|---|
| 79 | + |
|---|
| 80 | + "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA=="], |
|---|
| 81 | + |
|---|
| 82 | + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="], |
|---|
| 83 | + |
|---|
| 84 | + "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], |
|---|
| 85 | + |
|---|
| 86 | + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], |
|---|
| 87 | + |
|---|
| 88 | + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], |
|---|
| 89 | + |
|---|
| 90 | + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], |
|---|
| 91 | + |
|---|
| 92 | + "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ=="], |
|---|
| 93 | + |
|---|
| 94 | + "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], |
|---|
| 95 | + |
|---|
| 96 | + "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], |
|---|
| 97 | + |
|---|
| 98 | + "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.29.0", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-decorators": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA=="], |
|---|
| 99 | + |
|---|
| 100 | + "@babel/plugin-proposal-export-default-from": ["@babel/plugin-proposal-export-default-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw=="], |
|---|
| 101 | + |
|---|
| 102 | + "@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="], |
|---|
| 103 | + |
|---|
| 104 | + "@babel/plugin-syntax-bigint": ["@babel/plugin-syntax-bigint@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg=="], |
|---|
| 105 | + |
|---|
| 106 | + "@babel/plugin-syntax-class-properties": ["@babel/plugin-syntax-class-properties@7.12.13", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA=="], |
|---|
| 107 | + |
|---|
| 108 | + "@babel/plugin-syntax-class-static-block": ["@babel/plugin-syntax-class-static-block@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw=="], |
|---|
| 109 | + |
|---|
| 110 | + "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA=="], |
|---|
| 111 | + |
|---|
| 112 | + "@babel/plugin-syntax-dynamic-import": ["@babel/plugin-syntax-dynamic-import@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ=="], |
|---|
| 113 | + |
|---|
| 114 | + "@babel/plugin-syntax-export-default-from": ["@babel/plugin-syntax-export-default-from@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ=="], |
|---|
| 115 | + |
|---|
| 116 | + "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew=="], |
|---|
| 117 | + |
|---|
| 118 | + "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="], |
|---|
| 119 | + |
|---|
| 120 | + "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], |
|---|
| 121 | + |
|---|
| 122 | + "@babel/plugin-syntax-json-strings": ["@babel/plugin-syntax-json-strings@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA=="], |
|---|
| 123 | + |
|---|
| 124 | + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="], |
|---|
| 125 | + |
|---|
| 126 | + "@babel/plugin-syntax-logical-assignment-operators": ["@babel/plugin-syntax-logical-assignment-operators@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="], |
|---|
| 127 | + |
|---|
| 128 | + "@babel/plugin-syntax-nullish-coalescing-operator": ["@babel/plugin-syntax-nullish-coalescing-operator@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ=="], |
|---|
| 129 | + |
|---|
| 130 | + "@babel/plugin-syntax-numeric-separator": ["@babel/plugin-syntax-numeric-separator@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug=="], |
|---|
| 131 | + |
|---|
| 132 | + "@babel/plugin-syntax-object-rest-spread": ["@babel/plugin-syntax-object-rest-spread@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA=="], |
|---|
| 133 | + |
|---|
| 134 | + "@babel/plugin-syntax-optional-catch-binding": ["@babel/plugin-syntax-optional-catch-binding@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q=="], |
|---|
| 135 | + |
|---|
| 136 | + "@babel/plugin-syntax-optional-chaining": ["@babel/plugin-syntax-optional-chaining@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg=="], |
|---|
| 137 | + |
|---|
| 138 | + "@babel/plugin-syntax-private-property-in-object": ["@babel/plugin-syntax-private-property-in-object@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg=="], |
|---|
| 139 | + |
|---|
| 140 | + "@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="], |
|---|
| 141 | + |
|---|
| 142 | + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="], |
|---|
| 143 | + |
|---|
| 144 | + "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="], |
|---|
| 145 | + |
|---|
| 146 | + "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.29.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w=="], |
|---|
| 147 | + |
|---|
| 148 | + "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g=="], |
|---|
| 149 | + |
|---|
| 150 | + "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw=="], |
|---|
| 151 | + |
|---|
| 152 | + "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.27.1", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA=="], |
|---|
| 153 | + |
|---|
| 154 | + "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ=="], |
|---|
| 155 | + |
|---|
| 156 | + "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.4", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.28.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA=="], |
|---|
| 157 | + |
|---|
| 158 | + "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/template": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ=="], |
|---|
| 159 | + |
|---|
| 160 | + "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw=="], |
|---|
| 161 | + |
|---|
| 162 | + "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ=="], |
|---|
| 163 | + |
|---|
| 164 | + "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-syntax-flow": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg=="], |
|---|
| 165 | + |
|---|
| 166 | + "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.27.1", "", { "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-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw=="], |
|---|
| 167 | + |
|---|
| 168 | + "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.27.1", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ=="], |
|---|
| 169 | + |
|---|
| 170 | + "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA=="], |
|---|
| 171 | + |
|---|
| 172 | + "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A=="], |
|---|
| 173 | + |
|---|
| 174 | + "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], |
|---|
| 175 | + |
|---|
| 176 | + "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ=="], |
|---|
| 177 | + |
|---|
| 178 | + "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA=="], |
|---|
| 179 | + |
|---|
| 180 | + "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w=="], |
|---|
| 181 | + |
|---|
| 182 | + "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.28.6", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA=="], |
|---|
| 183 | + |
|---|
| 184 | + "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ=="], |
|---|
| 185 | + |
|---|
| 186 | + "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.27.1", "", { "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-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg=="], |
|---|
| 187 | + |
|---|
| 188 | + "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg=="], |
|---|
| 189 | + |
|---|
| 190 | + "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg=="], |
|---|
| 191 | + |
|---|
| 192 | + "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA=="], |
|---|
| 193 | + |
|---|
| 194 | + "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.28.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA=="], |
|---|
| 195 | + |
|---|
| 196 | + "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-jsx": "^7.28.6", "@babel/types": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow=="], |
|---|
| 197 | + |
|---|
| 198 | + "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.27.1", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q=="], |
|---|
| 199 | + |
|---|
| 200 | + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], |
|---|
| 201 | + |
|---|
| 202 | + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], |
|---|
| 203 | + |
|---|
| 204 | + "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA=="], |
|---|
| 205 | + |
|---|
| 206 | + "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog=="], |
|---|
| 207 | + |
|---|
| 208 | + "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w=="], |
|---|
| 209 | + |
|---|
| 210 | + "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ=="], |
|---|
| 211 | + |
|---|
| 212 | + "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA=="], |
|---|
| 213 | + |
|---|
| 214 | + "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g=="], |
|---|
| 215 | + |
|---|
| 216 | + "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg=="], |
|---|
| 217 | + |
|---|
| 218 | + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="], |
|---|
| 219 | + |
|---|
| 220 | + "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="], |
|---|
| 221 | + |
|---|
| 222 | + "@babel/preset-react": ["@babel/preset-react@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ=="], |
|---|
| 223 | + |
|---|
| 224 | + "@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="], |
|---|
| 225 | + |
|---|
| 226 | + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], |
|---|
| 227 | + |
|---|
| 228 | + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], |
|---|
| 229 | + |
|---|
| 230 | + "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], |
|---|
| 231 | + |
|---|
| 232 | + "@babel/traverse--for-generate-function-map": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], |
|---|
| 233 | + |
|---|
| 234 | + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], |
|---|
| 235 | + |
|---|
| 236 | + "@egjs/hammerjs": ["@egjs/hammerjs@2.0.17", "", { "dependencies": { "@types/hammerjs": "^2.0.36" } }, "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A=="], |
|---|
| 237 | + |
|---|
| 238 | + "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.24", "", {}, "sha512-1bJ63Yv2Bn8SN2MjrlbwLwUhnC8COOeejd15H88WjCtw5iNErqEPaBnpvmYyqciVYwudGo5drUIdY9C/5yPGbg=="], |
|---|
| 239 | + |
|---|
| 240 | + "@expo/cli": ["@expo/cli@55.0.14", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.8", "@expo/config-plugins": "~55.0.6", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.1", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@expo/log-box": "55.0.7", "@expo/metro": "~54.2.0", "@expo/metro-config": "~55.0.9", "@expo/osascript": "^2.4.2", "@expo/package-manager": "^1.10.3", "@expo/plist": "^0.5.2", "@expo/prebuild-config": "^55.0.8", "@expo/require-utils": "^55.0.2", "@expo/router-server": "^55.0.9", "@expo/schema-utils": "^55.0.2", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.2", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.3", "expo-server": "^55.0.6", "fetch-nodeshim": "^0.4.6", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.0", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "bin": { "expo-internal": "build/bin/cli" } }, "sha512-glXPSjjLCIz+KX/ezqLTGIF9eTE1lexiCxunvB3loRZNnGeBDGW3eF++cuPKudW26jeC6bqZkcqBG7Lp0Sp9qg=="], |
|---|
| 241 | + |
|---|
| 242 | + "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="], |
|---|
| 243 | + |
|---|
| 244 | + "@expo/config": ["@expo/config@55.0.8", "", { "dependencies": { "@expo/config-plugins": "~55.0.6", "@expo/config-types": "^55.0.5", "@expo/json-file": "^10.0.12", "@expo/require-utils": "^55.0.2", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-D7RYYHfErCgEllGxNwdYdkgzLna7zkzUECBV3snbUpf7RvIpB5l1LpCgzuVoc5KVew5h7N1Tn4LnT/tBSUZsQg=="], |
|---|
| 245 | + |
|---|
| 246 | + "@expo/config-plugins": ["@expo/config-plugins@55.0.6", "", { "dependencies": { "@expo/config-types": "^55.0.5", "@expo/json-file": "~10.0.12", "@expo/plist": "^0.5.2", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-cIox6FjZlFaaX40rbQ3DvP9e87S5X85H9uw+BAxJE5timkMhuByy3GAlOsj1h96EyzSiol7Q6YIGgY1Jiz4M+A=="], |
|---|
| 247 | + |
|---|
| 248 | + "@expo/config-types": ["@expo/config-types@55.0.5", "", {}, "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg=="], |
|---|
| 249 | + |
|---|
| 250 | + "@expo/devcert": ["@expo/devcert@1.2.1", "", { "dependencies": { "@expo/sudo-prompt": "^9.3.1", "debug": "^3.1.0" } }, "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA=="], |
|---|
| 251 | + |
|---|
| 252 | + "@expo/devtools": ["@expo/devtools@55.0.2", "", { "dependencies": { "chalk": "^4.1.2" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4VsFn9MUriocyuhyA+ycJP3TJhUsOFHDc270l9h3LhNpXMf6wvIdGcA0QzXkZtORXmlDybWXRP2KT1k36HcQkA=="], |
|---|
| 253 | + |
|---|
| 254 | + "@expo/dom-webview": ["@expo/dom-webview@55.0.3", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-bY4/rfcZ0f43DvOtMn8/kmPlmo01tex5hRoc5hKbwBwQjqWQuQt0ACwu7akR9IHI4j0WNG48eL6cZB6dZUFrzg=="], |
|---|
| 255 | + |
|---|
| 256 | + "@expo/env": ["@expo/env@2.1.1", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-rVvHC4I6xlPcg+mAO09ydUi2Wjv1ZytpLmHOSzvXzBAz9mMrJggqCe4s4dubjJvi/Ino/xQCLhbaLCnTtLpikg=="], |
|---|
| 257 | + |
|---|
| 258 | + "@expo/fingerprint": ["@expo/fingerprint@0.16.5", "", { "dependencies": { "@expo/env": "^2.0.11", "@expo/spawn-async": "^1.7.2", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-mLrcymtgkW9IJ/G1e8MH1Xt2VIb1MOS86ePY0ePcnV3nVyJqm7gfa/AXD1Hk+eZXvf8XhioYz6QZaamBdEzR3A=="], |
|---|
| 259 | + |
|---|
| 260 | + "@expo/image-utils": ["@expo/image-utils@0.8.12", "", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-3KguH7kyKqq7pNwLb9j6BBdD/bjmNwXZG/HPWT6GWIXbwrvAJt2JNyYTP5agWJ8jbbuys1yuCzmkX+TU6rmI7A=="], |
|---|
| 261 | + |
|---|
| 262 | + "@expo/json-file": ["@expo/json-file@10.0.12", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-inbDycp1rMAelAofg7h/mMzIe+Owx6F7pur3XdQ3EPTy00tme+4P6FWgHKUcjN8dBSrnbRNpSyh5/shzHyVCyQ=="], |
|---|
| 263 | + |
|---|
| 264 | + "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@55.0.6", "", { "dependencies": { "@expo/config": "~55.0.8", "chalk": "^4.1.2" } }, "sha512-4kfdv48sKzokijMqi07fINYA9/XprshmPgSLf8i69XgzIv2YdRyBbb70SzrufB7PDneFoltz8N83icW8gOOj1g=="], |
|---|
| 265 | + |
|---|
| 266 | + "@expo/log-box": ["@expo/log-box@55.0.7", "", { "dependencies": { "@expo/dom-webview": "^55.0.3", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "@expo/dom-webview": "^55.0.3", "expo": "*", "react": "*", "react-native": "*" } }, "sha512-m7V1k2vlMp4NOj3fopjOg4zl/ANXyTRF3HMTMep2GZAKsPiDzgOQ41nm8CaU50/HlDIGXlCObss07gOn20UpHQ=="], |
|---|
| 267 | + |
|---|
| 268 | + "@expo/metro": ["@expo/metro@54.2.0", "", { "dependencies": { "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-minify-terser": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3" } }, "sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w=="], |
|---|
| 269 | + |
|---|
| 270 | + "@expo/metro-config": ["@expo/metro-config@55.0.9", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~55.0.8", "@expo/env": "~2.1.1", "@expo/json-file": "~10.0.12", "@expo/metro": "~54.2.0", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "~8.4.32", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-ZJFEfat/+dLUhFyFFWrzMjAqAwwUaJ3RD42QNqR7jh+RVYkAf6XYLynb5qrKJTHI1EcOx4KoO1717yXYYRFDBA=="], |
|---|
| 271 | + |
|---|
| 272 | + "@expo/metro-runtime": ["@expo/metro-runtime@55.0.6", "", { "dependencies": { "@expo/log-box": "55.0.7", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" } }, "sha512-l8VvgKN9md+URjeQDB+DnHVmvpcWI6zFLH6yv7GTv4sfRDKyaZ5zDXYjTP1phYdgW6ea2NrRtCGNIxylWhsgtg=="], |
|---|
| 273 | + |
|---|
| 274 | + "@expo/osascript": ["@expo/osascript@2.4.2", "", { "dependencies": { "@expo/spawn-async": "^1.7.2" } }, "sha512-/XP7PSYF2hzOZzqfjgkoWtllyeTN8dW3aM4P6YgKcmmPikKL5FdoyQhti4eh6RK5a5VrUXJTOlTNIpIHsfB5Iw=="], |
|---|
| 275 | + |
|---|
| 276 | + "@expo/package-manager": ["@expo/package-manager@1.10.3", "", { "dependencies": { "@expo/json-file": "^10.0.12", "@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-ZuXiK/9fCrIuLjPSe1VYmfp0Sa85kCMwd8QQpgyi5ufppYKRtLBg14QOgUqj8ZMbJTxE0xqzd0XR7kOs3vAK9A=="], |
|---|
| 277 | + |
|---|
| 278 | + "@expo/plist": ["@expo/plist@0.5.2", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g=="], |
|---|
| 279 | + |
|---|
| 280 | + "@expo/prebuild-config": ["@expo/prebuild-config@55.0.8", "", { "dependencies": { "@expo/config": "~55.0.8", "@expo/config-plugins": "~55.0.6", "@expo/config-types": "^55.0.5", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@react-native/normalize-colors": "0.83.2", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-VJNJiOmmZgyDnR7JMmc3B8Z0ZepZ17I8Wtw+wAH/2+UCUsFg588XU+bwgYcFGw+is28kwGjY46z43kfufpxOnA=="], |
|---|
| 281 | + |
|---|
| 282 | + "@expo/require-utils": ["@expo/require-utils@55.0.2", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0" } }, "sha512-dV5oCShQ1umKBKagMMT4B/N+SREsQe3lU4Zgmko5AO0rxKV0tynZT6xXs+e2JxuqT4Rz997atg7pki0BnZb4uw=="], |
|---|
| 283 | + |
|---|
| 284 | + "@expo/router-server": ["@expo/router-server@55.0.9", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^55.0.6", "expo": "*", "expo-constants": "^55.0.7", "expo-font": "^55.0.4", "expo-router": "*", "expo-server": "^55.0.6", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "react-server-dom-webpack"] }, "sha512-LcCFi+P1qfZOsw0DO4JwNKRxtWt4u2bjTYj0PUe4WVf9NVG/NfUetAXYRbBS6P+gupfM6SC+/bdzdqCWQh7j8g=="], |
|---|
| 285 | + |
|---|
| 286 | + "@expo/schema-utils": ["@expo/schema-utils@55.0.2", "", {}, "sha512-QZ5WKbJOWkCrMq0/kfhV9ry8te/OaS34YgLVpG8u9y2gix96TlpRTbxM/YATjNcUR2s4fiQmPCOxkGtog4i37g=="], |
|---|
| 287 | + |
|---|
| 288 | + "@expo/sdk-runtime-versions": ["@expo/sdk-runtime-versions@1.0.0", "", {}, "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ=="], |
|---|
| 289 | + |
|---|
| 290 | + "@expo/spawn-async": ["@expo/spawn-async@1.7.2", "", { "dependencies": { "cross-spawn": "^7.0.3" } }, "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew=="], |
|---|
| 291 | + |
|---|
| 292 | + "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="], |
|---|
| 293 | + |
|---|
| 294 | + "@expo/vector-icons": ["@expo/vector-icons@15.1.1", "", { "peerDependencies": { "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } }, "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw=="], |
|---|
| 295 | + |
|---|
| 296 | + "@expo/ws-tunnel": ["@expo/ws-tunnel@1.0.6", "", {}, "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q=="], |
|---|
| 297 | + |
|---|
| 298 | + "@expo/xcpretty": ["@expo/xcpretty@4.4.1", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-KZNxZvnGCtiM2aYYZ6Wz0Ix5r47dAvpNLApFtZWnSoERzAdOMzVBOPysBoM0JlF6FKWZ8GPqgn6qt3dV/8Zlpg=="], |
|---|
| 299 | + |
|---|
| 300 | + "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], |
|---|
| 301 | + |
|---|
| 302 | + "@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="], |
|---|
| 303 | + |
|---|
| 304 | + "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="], |
|---|
| 305 | + |
|---|
| 306 | + "@jest/create-cache-key-function": ["@jest/create-cache-key-function@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3" } }, "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA=="], |
|---|
| 307 | + |
|---|
| 308 | + "@jest/environment": ["@jest/environment@29.7.0", "", { "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0" } }, "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw=="], |
|---|
| 309 | + |
|---|
| 310 | + "@jest/fake-timers": ["@jest/fake-timers@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", "jest-message-util": "^29.7.0", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ=="], |
|---|
| 311 | + |
|---|
| 312 | + "@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="], |
|---|
| 313 | + |
|---|
| 314 | + "@jest/transform": ["@jest/transform@29.7.0", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.7.0", "jest-regex-util": "^29.6.3", "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.2" } }, "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw=="], |
|---|
| 315 | + |
|---|
| 316 | + "@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="], |
|---|
| 317 | + |
|---|
| 318 | + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], |
|---|
| 319 | + |
|---|
| 320 | + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], |
|---|
| 321 | + |
|---|
| 322 | + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], |
|---|
| 323 | + |
|---|
| 324 | + "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], |
|---|
| 325 | + |
|---|
| 326 | + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], |
|---|
| 327 | + |
|---|
| 328 | + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], |
|---|
| 329 | + |
|---|
| 330 | + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], |
|---|
| 331 | + |
|---|
| 332 | + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], |
|---|
| 333 | + |
|---|
| 334 | + "@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=="], |
|---|
| 335 | + |
|---|
| 336 | + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], |
|---|
| 337 | + |
|---|
| 338 | + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], |
|---|
| 339 | + |
|---|
| 340 | + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], |
|---|
| 341 | + |
|---|
| 342 | + "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], |
|---|
| 343 | + |
|---|
| 344 | + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="], |
|---|
| 345 | + |
|---|
| 346 | + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], |
|---|
| 347 | + |
|---|
| 348 | + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="], |
|---|
| 349 | + |
|---|
| 350 | + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], |
|---|
| 351 | + |
|---|
| 352 | + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], |
|---|
| 353 | + |
|---|
| 354 | + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], |
|---|
| 355 | + |
|---|
| 356 | + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="], |
|---|
| 357 | + |
|---|
| 358 | + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], |
|---|
| 359 | + |
|---|
| 360 | + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], |
|---|
| 361 | + |
|---|
| 362 | + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="], |
|---|
| 363 | + |
|---|
| 364 | + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], |
|---|
| 365 | + |
|---|
| 366 | + "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="], |
|---|
| 367 | + |
|---|
| 368 | + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], |
|---|
| 369 | + |
|---|
| 370 | + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], |
|---|
| 371 | + |
|---|
| 372 | + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], |
|---|
| 373 | + |
|---|
| 374 | + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], |
|---|
| 375 | + |
|---|
| 376 | + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], |
|---|
| 377 | + |
|---|
| 378 | + "@react-native/assets-registry": ["@react-native/assets-registry@0.83.2", "", {}, "sha512-9I5l3pGAKnlpQ15uVkeB9Mgjvt3cZEaEc8EDtdexvdtZvLSjtwBzgourrOW4yZUijbjJr8h3YO2Y0q+THwUHTA=="], |
|---|
| 379 | + |
|---|
| 380 | + "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.83.2", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.83.2" } }, "sha512-XbcN/BEa64pVlb0Hb/E/Ph2SepjVN/FcNKrJcQvtaKZA6mBSO8pW8Eircdlr61/KBH94LihHbQoQDzkQFpeaTg=="], |
|---|
| 381 | + |
|---|
| 382 | + "@react-native/babel-preset": ["@react-native/babel-preset@0.83.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.83.2", "babel-plugin-syntax-hermes-parser": "0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, "peerDependencies": { "@babel/core": "*" } }, "sha512-X/RAXDfe6W+om/Fw1i6htTxQXFhBJ2jgNOWx3WpI3KbjeIWbq7ib6vrpTeIAW2NUMg+K3mML1NzgD4dpZeqdjA=="], |
|---|
| 383 | + |
|---|
| 384 | + "@react-native/codegen": ["@react-native/codegen@0.83.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.32.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/core": "*" } }, "sha512-9uK6X1miCXqtL4c759l74N/XbQeneWeQVjoV7SD2CGJuW7ZefxaoYenwGPs7rMoCdtS6wuIyR3hXQ+uWEBGYXA=="], |
|---|
| 385 | + |
|---|
| 386 | + "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.83.2", "", { "dependencies": { "@react-native/dev-middleware": "0.83.2", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.83.3", "metro-config": "^0.83.3", "metro-core": "^0.83.3", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-sTEF0eiUKtmImEP07Qo5c3Khvm1LIVX1Qyb6zWUqPL6W3MqFiXutZvKBjqLz6p49Szx8cplQLoXfLHT0bcDXKg=="], |
|---|
| 387 | + |
|---|
| 388 | + "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.83.2", "", {}, "sha512-t4fYfa7xopbUF5S4+ihNEwgaq4wLZLKLY0Ms8z72lkMteVd3bOX2Foxa8E2wTfRvdhPOkSpOsTeNDmD8ON4DoQ=="], |
|---|
| 389 | + |
|---|
| 390 | + "@react-native/debugger-shell": ["@react-native/debugger-shell@0.83.2", "", { "dependencies": { "cross-spawn": "^7.0.6", "fb-dotslash": "0.5.8" } }, "sha512-z9go6NJMsLSDJT5MW6VGugRsZHjYvUTwxtsVc3uLt4U9W6T3J6FWI2wHpXIzd2dUkXRfAiRQ3Zi8ZQQ8fRFg9A=="], |
|---|
| 391 | + |
|---|
| 392 | + "@react-native/dev-middleware": ["@react-native/dev-middleware@0.83.2", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.83.2", "@react-native/debugger-shell": "0.83.2", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^7.5.10" } }, "sha512-Zi4EVaAm28+icD19NN07Gh8Pqg/84QQu+jn4patfWKNkcToRFP5vPEbbp0eLOGWS+BVB1d1Fn5lvMrJsBbFcOg=="], |
|---|
| 393 | + |
|---|
| 394 | + "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.83.2", "", {}, "sha512-PqN11fXRAU+uJ0inZY1HWYlwJOXHOhF4SPyeHBBxjajKpm2PGunmvFWwkmBjmmUkP/CNO0ezTUudV0oj+2wiHQ=="], |
|---|
| 395 | + |
|---|
| 396 | + "@react-native/js-polyfills": ["@react-native/js-polyfills@0.83.2", "", {}, "sha512-dk6fIY2OrKW/2Nk2HydfYNrQau8g6LOtd7NVBrgaqa+lvuRyIML5iimShP5qPqQnx2ofHuzjFw+Ya0b5Q7nDbA=="], |
|---|
| 397 | + |
|---|
| 398 | + "@react-native/normalize-colors": ["@react-native/normalize-colors@0.83.2", "", {}, "sha512-gkZAb9LoVVzNuYzzOviH7DiPTXQoZPHuiTH2+O2+VWNtOkiznjgvqpwYAhg58a5zfRq5GXlbBdf5mzRj5+3Y5Q=="], |
|---|
| 399 | + |
|---|
| 400 | + "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.83.2", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "*" } }, "sha512-N7mRjHLW/+KWxMp9IHRWyE3VIkeG1m3PnZJAGEFLCN8VFb7e4VfI567o7tE/HYcdcXCylw+Eqhlciz8gDeQ71g=="], |
|---|
| 401 | + |
|---|
| 402 | + "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.15.3", "", { "dependencies": { "@react-navigation/elements": "^2.9.8", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.1.31", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-CIaHk5TuLeYlDgR1eij38kEbrQU5dAQxQZCC4Xv1wFZ/RRxppBopRMLzv2Il529a7mic6xG33OHcr9aEdOzq+A=="], |
|---|
| 403 | + |
|---|
| 404 | + "@react-navigation/core": ["@react-navigation/core@7.15.1", "", { "dependencies": { "@react-navigation/routers": "^7.5.3", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-Fqr6qxfZJIC4ewho7LtTa9zz6hcOzohX7D1lcDfrkGaYkS5xBwEZViGNxCJK/czUc74ua8NThyrObQFjB6Q/RQ=="], |
|---|
| 405 | + |
|---|
| 406 | + "@react-navigation/elements": ["@react-navigation/elements@2.9.8", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.1.31", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-3gpwUmVnDJYvK9nFmAA/YXw0hmT/C/lZx8RkRMK+ux9l1T+32EWnQFnn34Wa1BMDX8HN2r64yrlW93DIzKI7Uw=="], |
|---|
| 407 | + |
|---|
| 408 | + "@react-navigation/native": ["@react-navigation/native@7.1.31", "", { "dependencies": { "@react-navigation/core": "^7.15.1", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-+YCUwtfDgsux59Q0LDHc3Zid9ih93ecUCFWZOH6/+eNoUGnWx77wjS6ZfvBO/7E+EiIup11IVShDzCHR4of8hw=="], |
|---|
| 409 | + |
|---|
| 410 | + "@react-navigation/native-stack": ["@react-navigation/native-stack@7.14.2", "", { "dependencies": { "@react-navigation/elements": "^2.9.8", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.1.31", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-/nKxFAFSUSGV+NSXrXXcWEcGAHdyp8RyWjoGMDzVPdBhjCLblVSgHWx5y4mm+k0de9V1pkjsftUaroP7rQckzw=="], |
|---|
| 411 | + |
|---|
| 412 | + "@react-navigation/routers": ["@react-navigation/routers@7.5.3", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-1tJHg4KKRJuQ1/EvJxatrMef3NZXEPzwUIUZ3n1yJ2t7Q97siwRtbynRpQG9/69ebbtiZ8W3ScOZF/OmhvM4Rg=="], |
|---|
| 413 | + |
|---|
| 414 | + "@sinclair/typebox": ["@sinclair/typebox@0.27.10", "", {}, "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA=="], |
|---|
| 415 | + |
|---|
| 416 | + "@sinonjs/commons": ["@sinonjs/commons@3.0.1", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ=="], |
|---|
| 417 | + |
|---|
| 418 | + "@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="], |
|---|
| 419 | + |
|---|
| 420 | + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], |
|---|
| 421 | + |
|---|
| 422 | + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], |
|---|
| 423 | + |
|---|
| 424 | + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], |
|---|
| 425 | + |
|---|
| 426 | + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], |
|---|
| 427 | + |
|---|
| 428 | + "@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="], |
|---|
| 429 | + |
|---|
| 430 | + "@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="], |
|---|
| 431 | + |
|---|
| 432 | + "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="], |
|---|
| 433 | + |
|---|
| 434 | + "@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="], |
|---|
| 435 | + |
|---|
| 436 | + "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="], |
|---|
| 437 | + |
|---|
| 438 | + "@types/node": ["@types/node@25.3.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ=="], |
|---|
| 439 | + |
|---|
| 440 | + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], |
|---|
| 441 | + |
|---|
| 442 | + "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], |
|---|
| 443 | + |
|---|
| 444 | + "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], |
|---|
| 445 | + |
|---|
| 446 | + "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], |
|---|
| 447 | + |
|---|
| 448 | + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], |
|---|
| 449 | + |
|---|
| 450 | + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], |
|---|
| 451 | + |
|---|
| 452 | + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], |
|---|
| 453 | + |
|---|
| 454 | + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], |
|---|
| 455 | + |
|---|
| 456 | + "acorn": ["acorn@8.16.0", "", { "bin": "bin/acorn" }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], |
|---|
| 457 | + |
|---|
| 458 | + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], |
|---|
| 459 | + |
|---|
| 460 | + "anser": ["anser@1.4.10", "", {}, "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww=="], |
|---|
| 461 | + |
|---|
| 462 | + "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], |
|---|
| 463 | + |
|---|
| 464 | + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], |
|---|
| 465 | + |
|---|
| 466 | + "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], |
|---|
| 467 | + |
|---|
| 468 | + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], |
|---|
| 469 | + |
|---|
| 470 | + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], |
|---|
| 471 | + |
|---|
| 472 | + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], |
|---|
| 473 | + |
|---|
| 474 | + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], |
|---|
| 475 | + |
|---|
| 476 | + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], |
|---|
| 477 | + |
|---|
| 478 | + "array-timsort": ["array-timsort@1.0.3", "", {}, "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ=="], |
|---|
| 479 | + |
|---|
| 480 | + "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], |
|---|
| 481 | + |
|---|
| 482 | + "babel-jest": ["babel-jest@29.7.0", "", { "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg=="], |
|---|
| 483 | + |
|---|
| 484 | + "babel-plugin-istanbul": ["babel-plugin-istanbul@6.1.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA=="], |
|---|
| 485 | + |
|---|
| 486 | + "babel-plugin-jest-hoist": ["babel-plugin-jest-hoist@29.6.3", "", { "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" } }, "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg=="], |
|---|
| 487 | + |
|---|
| 488 | + "babel-plugin-module-resolver": ["babel-plugin-module-resolver@5.0.2", "", { "dependencies": { "find-babel-config": "^2.1.1", "glob": "^9.3.3", "pkg-up": "^3.1.0", "reselect": "^4.1.7", "resolve": "^1.22.8" } }, "sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg=="], |
|---|
| 489 | + |
|---|
| 490 | + "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.15", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw=="], |
|---|
| 491 | + |
|---|
| 492 | + "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.13.0", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A=="], |
|---|
| 493 | + |
|---|
| 494 | + "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.6", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.6" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A=="], |
|---|
| 495 | + |
|---|
| 496 | + "babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="], |
|---|
| 497 | + |
|---|
| 498 | + "babel-plugin-react-native-web": ["babel-plugin-react-native-web@0.21.2", "", {}, "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA=="], |
|---|
| 499 | + |
|---|
| 500 | + "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=="], |
|---|
| 501 | + |
|---|
| 502 | + "babel-plugin-transform-flow-enums": ["babel-plugin-transform-flow-enums@0.0.2", "", { "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" } }, "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ=="], |
|---|
| 503 | + |
|---|
| 504 | + "babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.2.0", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg=="], |
|---|
| 505 | + |
|---|
| 506 | + "babel-preset-expo": ["babel-preset-expo@55.0.10", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.2", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^55.0.2", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["expo-widgets"] }, "sha512-aRtW7qJKohGU2V0LUJ6IeP7py3+kVUo9zcc8+v1Kix8jGGuIvqvpo9S6W1Fmn9VFP2DBwkFDLiyzkCZS85urVA=="], |
|---|
| 507 | + |
|---|
| 508 | + "babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="], |
|---|
| 509 | + |
|---|
| 510 | + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], |
|---|
| 511 | + |
|---|
| 512 | + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], |
|---|
| 513 | + |
|---|
| 514 | + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": "dist/cli.cjs" }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], |
|---|
| 515 | + |
|---|
| 516 | + "better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="], |
|---|
| 517 | + |
|---|
| 518 | + "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], |
|---|
| 519 | + |
|---|
| 520 | + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], |
|---|
| 521 | + |
|---|
| 522 | + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], |
|---|
| 523 | + |
|---|
| 524 | + "bplist-creator": ["bplist-creator@0.1.0", "", { "dependencies": { "stream-buffers": "2.2.x" } }, "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg=="], |
|---|
| 525 | + |
|---|
| 526 | + "bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="], |
|---|
| 527 | + |
|---|
| 528 | + "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], |
|---|
| 529 | + |
|---|
| 530 | + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], |
|---|
| 531 | + |
|---|
| 532 | + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": "cli.js" }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], |
|---|
| 533 | + |
|---|
| 534 | + "bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="], |
|---|
| 535 | + |
|---|
| 536 | + "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], |
|---|
| 537 | + |
|---|
| 538 | + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], |
|---|
| 539 | + |
|---|
| 540 | + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], |
|---|
| 541 | + |
|---|
| 542 | + "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], |
|---|
| 543 | + |
|---|
| 544 | + "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], |
|---|
| 545 | + |
|---|
| 546 | + "caniuse-lite": ["caniuse-lite@1.0.30001775", "", {}, "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A=="], |
|---|
| 547 | + |
|---|
| 548 | + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], |
|---|
| 549 | + |
|---|
| 550 | + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], |
|---|
| 551 | + |
|---|
| 552 | + "chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="], |
|---|
| 553 | + |
|---|
| 554 | + "chromium-edge-launcher": ["chromium-edge-launcher@0.2.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0", "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg=="], |
|---|
| 555 | + |
|---|
| 556 | + "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], |
|---|
| 557 | + |
|---|
| 558 | + "cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="], |
|---|
| 559 | + |
|---|
| 560 | + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], |
|---|
| 561 | + |
|---|
| 562 | + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], |
|---|
| 563 | + |
|---|
| 564 | + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], |
|---|
| 565 | + |
|---|
| 566 | + "clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], |
|---|
| 567 | + |
|---|
| 568 | + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], |
|---|
| 569 | + |
|---|
| 570 | + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], |
|---|
| 571 | + |
|---|
| 572 | + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], |
|---|
| 573 | + |
|---|
| 574 | + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], |
|---|
| 575 | + |
|---|
| 576 | + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], |
|---|
| 577 | + |
|---|
| 578 | + "comment-json": ["comment-json@4.6.1", "", { "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", "esprima": "^4.0.1" } }, "sha512-kdBIsBGqD/sAeqvzeOhBvO/bhtpbfbIU/2lw7bp182FV1cVlY7gr1Jf3Q1I+NOsCk8e4gF5Sl9iYH5cNvVmx5w=="], |
|---|
| 579 | + |
|---|
| 580 | + "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], |
|---|
| 581 | + |
|---|
| 582 | + "compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="], |
|---|
| 583 | + |
|---|
| 584 | + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], |
|---|
| 585 | + |
|---|
| 586 | + "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], |
|---|
| 587 | + |
|---|
| 588 | + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], |
|---|
| 589 | + |
|---|
| 590 | + "core-js-compat": ["core-js-compat@3.48.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q=="], |
|---|
| 591 | + |
|---|
| 592 | + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], |
|---|
| 593 | + |
|---|
| 594 | + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], |
|---|
| 595 | + |
|---|
| 596 | + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], |
|---|
| 597 | + |
|---|
| 598 | + "css-in-js-utils": ["css-in-js-utils@3.1.0", "", { "dependencies": { "hyphenate-style-name": "^1.0.3" } }, "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A=="], |
|---|
| 599 | + |
|---|
| 600 | + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], |
|---|
| 601 | + |
|---|
| 602 | + "css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="], |
|---|
| 603 | + |
|---|
| 604 | + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], |
|---|
| 605 | + |
|---|
| 606 | + "cssesc": ["cssesc@3.0.0", "", { "bin": "bin/cssesc" }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], |
|---|
| 607 | + |
|---|
| 608 | + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], |
|---|
| 609 | + |
|---|
| 610 | + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], |
|---|
| 611 | + |
|---|
| 612 | + "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], |
|---|
| 613 | + |
|---|
| 614 | + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], |
|---|
| 615 | + |
|---|
| 616 | + "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], |
|---|
| 617 | + |
|---|
| 618 | + "define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], |
|---|
| 619 | + |
|---|
| 620 | + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], |
|---|
| 621 | + |
|---|
| 622 | + "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], |
|---|
| 623 | + |
|---|
| 624 | + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], |
|---|
| 625 | + |
|---|
| 626 | + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], |
|---|
| 627 | + |
|---|
| 628 | + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], |
|---|
| 629 | + |
|---|
| 630 | + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], |
|---|
| 631 | + |
|---|
| 632 | + "dnssd-advertise": ["dnssd-advertise@1.1.3", "", {}, "sha512-XENsHi3MBzWOCAXif3yZvU1Ah0l+nhJj1sjWL6TnOAYKvGiFhbTx32xHN7+wLMLUOCj7Nr0evADWG4R8JtqCDA=="], |
|---|
| 633 | + |
|---|
| 634 | + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], |
|---|
| 635 | + |
|---|
| 636 | + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], |
|---|
| 637 | + |
|---|
| 638 | + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], |
|---|
| 639 | + |
|---|
| 640 | + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], |
|---|
| 641 | + |
|---|
| 642 | + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], |
|---|
| 643 | + |
|---|
| 644 | + "electron-to-chromium": ["electron-to-chromium@1.5.302", "", {}, "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg=="], |
|---|
| 645 | + |
|---|
| 646 | + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], |
|---|
| 647 | + |
|---|
| 648 | + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], |
|---|
| 649 | + |
|---|
| 650 | + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], |
|---|
| 651 | + |
|---|
| 652 | + "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], |
|---|
| 653 | + |
|---|
| 654 | + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], |
|---|
| 655 | + |
|---|
| 656 | + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], |
|---|
| 657 | + |
|---|
| 658 | + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], |
|---|
| 659 | + |
|---|
| 660 | + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], |
|---|
| 661 | + |
|---|
| 662 | + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], |
|---|
| 663 | + |
|---|
| 664 | + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], |
|---|
| 665 | + |
|---|
| 666 | + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], |
|---|
| 667 | + |
|---|
| 668 | + "expo": ["expo@55.0.4", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.14", "@expo/config": "~55.0.8", "@expo/config-plugins": "~55.0.6", "@expo/devtools": "55.0.2", "@expo/fingerprint": "0.16.5", "@expo/local-build-cache-provider": "55.0.6", "@expo/log-box": "55.0.7", "@expo/metro": "~54.2.0", "@expo/metro-config": "55.0.9", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~55.0.10", "expo-asset": "~55.0.8", "expo-constants": "~55.0.7", "expo-file-system": "~55.0.10", "expo-font": "~55.0.4", "expo-keep-awake": "~55.0.4", "expo-modules-autolinking": "55.0.8", "expo-modules-core": "55.0.13", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.1" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "expo-modules-autolinking": "bin/autolinking", "fingerprint": "bin/fingerprint" } }, "sha512-cbQBPYwmH6FRvh942KR8mSdEcrVdsIMkjdHthtf59zlpzgrk28FabhOdL/Pc9WuS+CsIP3EIQbZqmLkTjv6qPg=="], |
|---|
| 669 | + |
|---|
| 670 | + "expo-asset": ["expo-asset@55.0.8", "", { "dependencies": { "@expo/image-utils": "^0.8.12", "expo-constants": "~55.0.7" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-yEz2svDX67R0yiW2skx6dJmcE0q7sj9ECpGMcxBExMCbctc+nMoZCnjUuhzPl5vhClUsO5HFFXS5vIGmf1bgHQ=="], |
|---|
| 671 | + |
|---|
| 672 | + "expo-audio": ["expo-audio@55.0.8", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-X61pQSikE2rsP2ZTMFUMThOmgGyYEHcmZpGVMrKJgcYtRCFKuctB/z69dFQPoumL+zTz8qlBoGohjkHVvA9P8A=="], |
|---|
| 673 | + |
|---|
| 674 | + "expo-constants": ["expo-constants@55.0.7", "", { "dependencies": { "@expo/config": "~55.0.8", "@expo/env": "~2.1.1" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-kdcO4TsQRRqt0USvjaY5vgQMO9H52K3kBZ/ejC7F6rz70mv08GoowrZ1CYOr5O4JpPDRlIpQfZJUucaS/c+KWQ=="], |
|---|
| 675 | + |
|---|
| 676 | + "expo-file-system": ["expo-file-system@55.0.10", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-ysFdVdUgtfj2ApY0Cn+pBg+yK4xp+SNwcaH8j2B91JJQ4OXJmnyCSmrNZYz7J4mdYVuv2GzxIP+N/IGlHQG3Yw=="], |
|---|
| 677 | + |
|---|
| 678 | + "expo-font": ["expo-font@55.0.4", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-ZKeGTFffPygvY5dM/9ATM2p7QDkhsaHopH7wFAWgP2lKzqUMS9B/RxCvw5CaObr9Ro7x9YptyeRKX2HmgmMfrg=="], |
|---|
| 679 | + |
|---|
| 680 | + "expo-glass-effect": ["expo-glass-effect@55.0.7", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-G7Q9rUaEY0YC36fGE6irDljfsfvzz/y49zagARAKvSJSyQMUSrhR25WOr5LK5Cw7gQNNBEy9U1ctlr7yCay/fQ=="], |
|---|
| 681 | + |
|---|
| 682 | + "expo-haptics": ["expo-haptics@55.0.8", "", { "peerDependencies": { "expo": "*" } }, "sha512-yVR6EsQwl1WuhFITc0PpfI/7dsBdjK/F2YA8xB80UUW9iTa+Tqz21FpH4n/vtbargpzFxkhl5WNYMa419+QWFQ=="], |
|---|
| 683 | + |
|---|
| 684 | + "expo-image": ["expo-image@55.0.5", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" } }, "sha512-oejmMwy5O9EtC8po9NxkcurWHqND6p8xuJaj9FGNo8NXLt9e+w3cKWx7HuPzkH5y3qFXQ9Od+z+I/wxEci36fw=="], |
|---|
| 685 | + |
|---|
| 686 | + "expo-image-loader": ["expo-image-loader@55.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-NOjp56wDrfuA5aiNAybBIjqIn1IxKeGJ8CECWZncQ/GzjZfyTYAHTCyeApYkdKkMBLHINzI4BbTGSlbCa0fXXQ=="], |
|---|
| 687 | + |
|---|
| 688 | + "expo-image-picker": ["expo-image-picker@55.0.11", "", { "dependencies": { "expo-image-loader": "~55.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-geJklIGdAR2N16iSk86oyJe7QgX5RpqDX1FjKpxO53fF4D0eBmg5Irm6gRwT0b+DHP1kJevZgzzbVJsRAV362g=="], |
|---|
| 689 | + |
|---|
| 690 | + "expo-keep-awake": ["expo-keep-awake@55.0.4", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-vwfdMtMS5Fxaon8gC0AiE70SpxTsHJ+rjeoVJl8kdfdbxczF7OIaVmfjFJ5Gfigd/WZiLqxhfZk34VAkXF4PNg=="], |
|---|
| 691 | + |
|---|
| 692 | + "expo-linking": ["expo-linking@55.0.7", "", { "dependencies": { "expo-constants": "~55.0.7", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MiGCedere1vzQTEi2aGrkzd7eh/rPSz4w6F3GMBuAJzYl+/0VhIuyhozpEGrueyDIXWfzaUVOcn3SfxVi+kwQQ=="], |
|---|
| 693 | + |
|---|
| 694 | + "expo-modules-autolinking": ["expo-modules-autolinking@55.0.8", "", { "dependencies": { "@expo/require-utils": "^55.0.2", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": "bin/expo-modules-autolinking.js" }, "sha512-nrWB1pkNp7bR8ECUTgYUiJ2Pyh6AvxCBXZ+lyPlfl1TzEIGhwU1Yqr+d78eJDueXaW+9zKeE0HqrTZoLS3ve4A=="], |
|---|
| 695 | + |
|---|
| 696 | + "expo-modules-core": ["expo-modules-core@55.0.13", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-DYLQTOJAR7jD3M9S0sH9myZaPEtShdicHrPiWcupIXMeMkQxFzErx+adUI8gZPy4AU45BgeGgtaogRfT25iLfw=="], |
|---|
| 697 | + |
|---|
| 698 | + "expo-router": ["expo-router@55.0.3", "", { "dependencies": { "@expo/metro-runtime": "^55.0.6", "@expo/schema-utils": "^55.0.2", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.10.1", "@react-navigation/native": "^7.1.28", "@react-navigation/native-stack": "^7.10.1", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^55.0.7", "expo-image": "^55.0.5", "expo-server": "^55.0.6", "expo-symbols": "^55.0.4", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.7", "@expo/metro-runtime": "^55.0.6", "@react-navigation/drawer": "^7.7.2", "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^55.0.7", "expo-linking": "^55.0.7", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-server-dom-webpack"] }, "sha512-B3MQAeZq9B2SS5kgEybGqXYR0AY7QYM7fQ5E4bJwtvZLJjWPmWhDALhBpD26ovK/i1k0fi9VgW47FKJODxM5Jg=="], |
|---|
| 699 | + |
|---|
| 700 | + "expo-secure-store": ["expo-secure-store@55.0.8", "", { "peerDependencies": { "expo": "*" } }, "sha512-8w9tQe8U6oRo5YIzqCqVhRrOnfoODNDoitBtLXEx+zS6WLUnkRq5kH7ViJuOgiM7PzLr9pvAliRiDOKyvFbTuQ=="], |
|---|
| 701 | + |
|---|
| 702 | + "expo-server": ["expo-server@55.0.6", "", {}, "sha512-xI72FTm469FfuuBL2R5aNtthgH+GR7ygOpsx/KcPS0K8AZaZd7VjtEExbzn9/qyyYkWW3T+3dAmCDKOMX8gdmQ=="], |
|---|
| 703 | + |
|---|
| 704 | + "expo-sharing": ["expo-sharing@55.0.11", "", { "dependencies": { "@expo/config-plugins": "^55.0.6", "@expo/config-types": "^55.0.5", "@expo/plist": "^0.5.2" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-YlVez832W0sYR2KJY4Dr8ON9aC+Wp8a/r40eQyhoHT9Tetkr2KBM7tWLT0CGKRuTTnrqJL1C51UacLkHJ9zmNA=="], |
|---|
| 705 | + |
|---|
| 706 | + "expo-splash-screen": ["expo-splash-screen@55.0.10", "", { "dependencies": { "@expo/prebuild-config": "^55.0.8" }, "peerDependencies": { "expo": "*" } }, "sha512-RN5qqrxudxFlRIjLFr/Ifmt+mUCLRc0gs66PekP6flzNS/JYEuoCbwJ+NmUwwJtPA+vyy60DYiky0QmS98ydmQ=="], |
|---|
| 707 | + |
|---|
| 708 | + "expo-status-bar": ["expo-status-bar@55.0.4", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-BPDjUXKqv1F9j2YNGLRZfkBEZXIEEpqj+t81y4c+4fdSN3Pos7goIHXgcl2ozbKQLgKRZQyNZQtbUgh5UjHYUQ=="], |
|---|
| 709 | + |
|---|
| 710 | + "expo-symbols": ["expo-symbols@55.0.4", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-w9rxPlpta3gks0G4Tvpq/qQdiMp4R/XOeOzyjSruYUQakmsWbQBKA+Sd/fCVXs7qFJSvVTOGXiOhZm+YJRYZVg=="], |
|---|
| 711 | + |
|---|
| 712 | + "expo-system-ui": ["expo-system-ui@55.0.9", "", { "dependencies": { "@react-native/normalize-colors": "0.83.2", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" } }, "sha512-8ygP1B0uFAFI8s7eHY2IcGnE83GhFeZYwHBr/fQ4dSXnc7iVT9zp2PvyTyiDiibQ69dBG+fauMQ4KlPcOO51kQ=="], |
|---|
| 713 | + |
|---|
| 714 | + "expo-web-browser": ["expo-web-browser@55.0.9", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-PvAVsG401QmZabtTsYh1cYcpPiqvBPs8oiOkSrp0jIXnneiM466HxmeNtvo+fNxqJ2nwOBz9qLPiWRO91VBfsQ=="], |
|---|
| 715 | + |
|---|
| 716 | + "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], |
|---|
| 717 | + |
|---|
| 718 | + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], |
|---|
| 719 | + |
|---|
| 720 | + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], |
|---|
| 721 | + |
|---|
| 722 | + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], |
|---|
| 723 | + |
|---|
| 724 | + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], |
|---|
| 725 | + |
|---|
| 726 | + "fb-dotslash": ["fb-dotslash@0.5.8", "", { "bin": { "dotslash": "bin/dotslash" } }, "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA=="], |
|---|
| 727 | + |
|---|
| 728 | + "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="], |
|---|
| 729 | + |
|---|
| 730 | + "fbjs": ["fbjs@3.0.5", "", { "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^1.0.35" } }, "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg=="], |
|---|
| 731 | + |
|---|
| 732 | + "fbjs-css-vars": ["fbjs-css-vars@1.0.2", "", {}, "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="], |
|---|
| 733 | + |
|---|
| 734 | + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], |
|---|
| 735 | + |
|---|
| 736 | + "fetch-nodeshim": ["fetch-nodeshim@0.4.8", "", {}, "sha512-YW5vG33rabBq6JpYosLNoXoaMN69/WH26MeeX2hkDVjN6UlvRGq3Wkazl9H0kisH95aMu/HtHL64JUvv/+Nv/g=="], |
|---|
| 737 | + |
|---|
| 738 | + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], |
|---|
| 739 | + |
|---|
| 740 | + "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="], |
|---|
| 741 | + |
|---|
| 742 | + "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], |
|---|
| 743 | + |
|---|
| 744 | + "find-babel-config": ["find-babel-config@2.1.2", "", { "dependencies": { "json5": "^2.2.3" } }, "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg=="], |
|---|
| 745 | + |
|---|
| 746 | + "find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], |
|---|
| 747 | + |
|---|
| 748 | + "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="], |
|---|
| 749 | + |
|---|
| 750 | + "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="], |
|---|
| 751 | + |
|---|
| 752 | + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], |
|---|
| 753 | + |
|---|
| 754 | + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], |
|---|
| 755 | + |
|---|
| 756 | + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], |
|---|
| 757 | + |
|---|
| 758 | + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], |
|---|
| 759 | + |
|---|
| 760 | + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], |
|---|
| 761 | + |
|---|
| 762 | + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], |
|---|
| 763 | + |
|---|
| 764 | + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], |
|---|
| 765 | + |
|---|
| 766 | + "get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="], |
|---|
| 767 | + |
|---|
| 768 | + "getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="], |
|---|
| 769 | + |
|---|
| 770 | + "glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], |
|---|
| 771 | + |
|---|
| 772 | + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], |
|---|
| 773 | + |
|---|
| 774 | + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], |
|---|
| 775 | + |
|---|
| 776 | + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], |
|---|
| 777 | + |
|---|
| 778 | + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], |
|---|
| 779 | + |
|---|
| 780 | + "hermes-compiler": ["hermes-compiler@0.14.1", "", {}, "sha512-+RPPQlayoZ9n6/KXKt5SFILWXCGJ/LV5d24L5smXrvTDrPS4L6dSctPczXauuvzFP3QEJbD1YO7Z3Ra4a+4IhA=="], |
|---|
| 781 | + |
|---|
| 782 | + "hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="], |
|---|
| 783 | + |
|---|
| 784 | + "hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="], |
|---|
| 785 | + |
|---|
| 786 | + "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], |
|---|
| 787 | + |
|---|
| 788 | + "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], |
|---|
| 789 | + |
|---|
| 790 | + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], |
|---|
| 791 | + |
|---|
| 792 | + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], |
|---|
| 793 | + |
|---|
| 794 | + "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], |
|---|
| 795 | + |
|---|
| 796 | + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], |
|---|
| 797 | + |
|---|
| 798 | + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], |
|---|
| 799 | + |
|---|
| 800 | + "image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": "bin/image-size.js" }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="], |
|---|
| 801 | + |
|---|
| 802 | + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], |
|---|
| 803 | + |
|---|
| 804 | + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], |
|---|
| 805 | + |
|---|
| 806 | + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], |
|---|
| 807 | + |
|---|
| 808 | + "inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="], |
|---|
| 809 | + |
|---|
| 810 | + "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], |
|---|
| 811 | + |
|---|
| 812 | + "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], |
|---|
| 813 | + |
|---|
| 814 | + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], |
|---|
| 815 | + |
|---|
| 816 | + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], |
|---|
| 817 | + |
|---|
| 818 | + "is-docker": ["is-docker@2.2.1", "", { "bin": "cli.js" }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], |
|---|
| 819 | + |
|---|
| 820 | + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], |
|---|
| 821 | + |
|---|
| 822 | + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], |
|---|
| 823 | + |
|---|
| 824 | + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], |
|---|
| 825 | + |
|---|
| 826 | + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], |
|---|
| 827 | + |
|---|
| 828 | + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], |
|---|
| 829 | + |
|---|
| 830 | + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], |
|---|
| 831 | + |
|---|
| 832 | + "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], |
|---|
| 833 | + |
|---|
| 834 | + "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=="], |
|---|
| 835 | + |
|---|
| 836 | + "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=="], |
|---|
| 837 | + |
|---|
| 838 | + "jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="], |
|---|
| 839 | + |
|---|
| 840 | + "jest-haste-map": ["jest-haste-map@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.6.3", "jest-util": "^29.7.0", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA=="], |
|---|
| 841 | + |
|---|
| 842 | + "jest-message-util": ["jest-message-util@29.7.0", "", { "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w=="], |
|---|
| 843 | + |
|---|
| 844 | + "jest-mock": ["jest-mock@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "jest-util": "^29.7.0" } }, "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw=="], |
|---|
| 845 | + |
|---|
| 846 | + "jest-regex-util": ["jest-regex-util@29.6.3", "", {}, "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg=="], |
|---|
| 847 | + |
|---|
| 848 | + "jest-util": ["jest-util@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="], |
|---|
| 849 | + |
|---|
| 850 | + "jest-validate": ["jest-validate@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", "pretty-format": "^29.7.0" } }, "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw=="], |
|---|
| 851 | + |
|---|
| 852 | + "jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], |
|---|
| 853 | + |
|---|
| 854 | + "jimp-compact": ["jimp-compact@0.16.1", "", {}, "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="], |
|---|
| 855 | + |
|---|
| 856 | + "jiti": ["jiti@1.21.7", "", { "bin": "bin/jiti.js" }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], |
|---|
| 857 | + |
|---|
| 858 | + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], |
|---|
| 859 | + |
|---|
| 860 | + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], |
|---|
| 861 | + |
|---|
| 862 | + "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="], |
|---|
| 863 | + |
|---|
| 864 | + "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], |
|---|
| 865 | + |
|---|
| 866 | + "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], |
|---|
| 867 | + |
|---|
| 868 | + "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], |
|---|
| 869 | + |
|---|
| 870 | + "lan-network": ["lan-network@0.2.0", "", { "bin": "dist/lan-network-cli.js" }, "sha512-EZgbsXMrGS+oK+Ta12mCjzBFse+SIewGdwrSTr5g+MSymnjpox2x05ceI20PQejJOFvOgzcXrfDk/SdY7dSCtw=="], |
|---|
| 871 | + |
|---|
| 872 | + "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], |
|---|
| 873 | + |
|---|
| 874 | + "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], |
|---|
| 875 | + |
|---|
| 876 | + "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], |
|---|
| 877 | + |
|---|
| 878 | + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], |
|---|
| 879 | + |
|---|
| 880 | + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], |
|---|
| 881 | + |
|---|
| 882 | + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], |
|---|
| 883 | + |
|---|
| 884 | + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], |
|---|
| 885 | + |
|---|
| 886 | + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], |
|---|
| 887 | + |
|---|
| 888 | + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], |
|---|
| 889 | + |
|---|
| 890 | + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], |
|---|
| 891 | + |
|---|
| 892 | + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], |
|---|
| 893 | + |
|---|
| 894 | + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], |
|---|
| 895 | + |
|---|
| 896 | + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], |
|---|
| 897 | + |
|---|
| 898 | + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], |
|---|
| 899 | + |
|---|
| 900 | + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], |
|---|
| 901 | + |
|---|
| 902 | + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], |
|---|
| 903 | + |
|---|
| 904 | + "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], |
|---|
| 905 | + |
|---|
| 906 | + "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], |
|---|
| 907 | + |
|---|
| 908 | + "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], |
|---|
| 909 | + |
|---|
| 910 | + "log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="], |
|---|
| 911 | + |
|---|
| 912 | + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], |
|---|
| 913 | + |
|---|
| 914 | + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], |
|---|
| 915 | + |
|---|
| 916 | + "makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="], |
|---|
| 917 | + |
|---|
| 918 | + "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="], |
|---|
| 919 | + |
|---|
| 920 | + "mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="], |
|---|
| 921 | + |
|---|
| 922 | + "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="], |
|---|
| 923 | + |
|---|
| 924 | + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], |
|---|
| 925 | + |
|---|
| 926 | + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], |
|---|
| 927 | + |
|---|
| 928 | + "metro": ["metro@0.83.3", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.32.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": "src/cli.js" }, "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q=="], |
|---|
| 929 | + |
|---|
| 930 | + "metro-babel-transformer": ["metro-babel-transformer@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g=="], |
|---|
| 931 | + |
|---|
| 932 | + "metro-cache": ["metro-cache@0.83.3", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.3" } }, "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q=="], |
|---|
| 933 | + |
|---|
| 934 | + "metro-cache-key": ["metro-cache-key@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw=="], |
|---|
| 935 | + |
|---|
| 936 | + "metro-config": ["metro-config@0.83.3", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.3", "metro-cache": "0.83.3", "metro-core": "0.83.3", "metro-runtime": "0.83.3", "yaml": "^2.6.1" } }, "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA=="], |
|---|
| 937 | + |
|---|
| 938 | + "metro-core": ["metro-core@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.3" } }, "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw=="], |
|---|
| 939 | + |
|---|
| 940 | + "metro-file-map": ["metro-file-map@0.83.3", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA=="], |
|---|
| 941 | + |
|---|
| 942 | + "metro-minify-terser": ["metro-minify-terser@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ=="], |
|---|
| 943 | + |
|---|
| 944 | + "metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="], |
|---|
| 945 | + |
|---|
| 946 | + "metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="], |
|---|
| 947 | + |
|---|
| 948 | + "metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], |
|---|
| 949 | + |
|---|
| 950 | + "metro-symbolicate": ["metro-symbolicate@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": "src/index.js" }, "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw=="], |
|---|
| 951 | + |
|---|
| 952 | + "metro-transform-plugins": ["metro-transform-plugins@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A=="], |
|---|
| 953 | + |
|---|
| 954 | + "metro-transform-worker": ["metro-transform-worker@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-minify-terser": "0.83.3", "metro-source-map": "0.83.3", "metro-transform-plugins": "0.83.3", "nullthrows": "^1.1.1" } }, "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA=="], |
|---|
| 955 | + |
|---|
| 956 | + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], |
|---|
| 957 | + |
|---|
| 958 | + "mime": ["mime@1.6.0", "", { "bin": "cli.js" }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], |
|---|
| 959 | + |
|---|
| 960 | + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], |
|---|
| 961 | + |
|---|
| 962 | + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], |
|---|
| 963 | + |
|---|
| 964 | + "mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="], |
|---|
| 965 | + |
|---|
| 966 | + "minimatch": ["minimatch@8.0.7", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg=="], |
|---|
| 967 | + |
|---|
| 968 | + "minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], |
|---|
| 969 | + |
|---|
| 970 | + "mkdirp": ["mkdirp@1.0.4", "", { "bin": "bin/cmd.js" }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], |
|---|
| 971 | + |
|---|
| 972 | + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], |
|---|
| 973 | + |
|---|
| 974 | + "multitars": ["multitars@0.2.4", "", {}, "sha512-XgLbg1HHchFauMCQPRwMj6MSyDd5koPlTA1hM3rUFkeXzGpjU/I9fP3to7yrObE9jcN8ChIOQGrM0tV0kUZaKg=="], |
|---|
| 975 | + |
|---|
| 976 | + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], |
|---|
| 977 | + |
|---|
| 978 | + "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], |
|---|
| 979 | + |
|---|
| 980 | + "nativewind": ["nativewind@4.2.2", "", { "dependencies": { "comment-json": "^4.2.5", "debug": "^4.3.7", "react-native-css-interop": "0.2.2" }, "peerDependencies": { "tailwindcss": ">3.3.0" } }, "sha512-kUGbUamKUWdnAIjfBuhIrtDHFtMyL1pEE3AEbCuKeg656pHuB0KtJRk6Lrie/+8haj8hCSlwOleQFJLrE1sZgA=="], |
|---|
| 981 | + |
|---|
| 982 | + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], |
|---|
| 983 | + |
|---|
| 984 | + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], |
|---|
| 985 | + |
|---|
| 986 | + "node-forge": ["node-forge@1.3.3", "", {}, "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg=="], |
|---|
| 987 | + |
|---|
| 988 | + "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="], |
|---|
| 989 | + |
|---|
| 990 | + "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], |
|---|
| 991 | + |
|---|
| 992 | + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], |
|---|
| 993 | + |
|---|
| 994 | + "npm-package-arg": ["npm-package-arg@11.0.3", "", { "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" } }, "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw=="], |
|---|
| 995 | + |
|---|
| 996 | + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], |
|---|
| 997 | + |
|---|
| 998 | + "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="], |
|---|
| 999 | + |
|---|
| 1000 | + "ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], |
|---|
| 1001 | + |
|---|
| 1002 | + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], |
|---|
| 1003 | + |
|---|
| 1004 | + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], |
|---|
| 1005 | + |
|---|
| 1006 | + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], |
|---|
| 1007 | + |
|---|
| 1008 | + "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="], |
|---|
| 1009 | + |
|---|
| 1010 | + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], |
|---|
| 1011 | + |
|---|
| 1012 | + "onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="], |
|---|
| 1013 | + |
|---|
| 1014 | + "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], |
|---|
| 1015 | + |
|---|
| 1016 | + "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=="], |
|---|
| 1017 | + |
|---|
| 1018 | + "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], |
|---|
| 1019 | + |
|---|
| 1020 | + "p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], |
|---|
| 1021 | + |
|---|
| 1022 | + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], |
|---|
| 1023 | + |
|---|
| 1024 | + "parse-png": ["parse-png@2.1.0", "", { "dependencies": { "pngjs": "^3.3.0" } }, "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ=="], |
|---|
| 1025 | + |
|---|
| 1026 | + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], |
|---|
| 1027 | + |
|---|
| 1028 | + "path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], |
|---|
| 1029 | + |
|---|
| 1030 | + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], |
|---|
| 1031 | + |
|---|
| 1032 | + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], |
|---|
| 1033 | + |
|---|
| 1034 | + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], |
|---|
| 1035 | + |
|---|
| 1036 | + "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=="], |
|---|
| 1037 | + |
|---|
| 1038 | + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], |
|---|
| 1039 | + |
|---|
| 1040 | + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], |
|---|
| 1041 | + |
|---|
| 1042 | + "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], |
|---|
| 1043 | + |
|---|
| 1044 | + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], |
|---|
| 1045 | + |
|---|
| 1046 | + "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], |
|---|
| 1047 | + |
|---|
| 1048 | + "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], |
|---|
| 1049 | + |
|---|
| 1050 | + "pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="], |
|---|
| 1051 | + |
|---|
| 1052 | + "postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], |
|---|
| 1053 | + |
|---|
| 1054 | + "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], |
|---|
| 1055 | + |
|---|
| 1056 | + "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="], |
|---|
| 1057 | + |
|---|
| 1058 | + "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["tsx"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], |
|---|
| 1059 | + |
|---|
| 1060 | + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], |
|---|
| 1061 | + |
|---|
| 1062 | + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], |
|---|
| 1063 | + |
|---|
| 1064 | + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], |
|---|
| 1065 | + |
|---|
| 1066 | + "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="], |
|---|
| 1067 | + |
|---|
| 1068 | + "proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="], |
|---|
| 1069 | + |
|---|
| 1070 | + "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], |
|---|
| 1071 | + |
|---|
| 1072 | + "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="], |
|---|
| 1073 | + |
|---|
| 1074 | + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], |
|---|
| 1075 | + |
|---|
| 1076 | + "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="], |
|---|
| 1077 | + |
|---|
| 1078 | + "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="], |
|---|
| 1079 | + |
|---|
| 1080 | + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], |
|---|
| 1081 | + |
|---|
| 1082 | + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], |
|---|
| 1083 | + |
|---|
| 1084 | + "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], |
|---|
| 1085 | + |
|---|
| 1086 | + "react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="], |
|---|
| 1087 | + |
|---|
| 1088 | + "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], |
|---|
| 1089 | + |
|---|
| 1090 | + "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="], |
|---|
| 1091 | + |
|---|
| 1092 | + "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="], |
|---|
| 1093 | + |
|---|
| 1094 | + "react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="], |
|---|
| 1095 | + |
|---|
| 1096 | + "react-native": ["react-native@0.83.2", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.2", "@react-native/codegen": "0.83.2", "@react-native/community-cli-plugin": "0.83.2", "@react-native/gradle-plugin": "0.83.2", "@react-native/js-polyfills": "0.83.2", "@react-native/normalize-colors": "0.83.2", "@react-native/virtualized-lists": "0.83.2", "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.1", "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" }, "bin": "cli.js" }, "sha512-ZDma3SLkRN2U2dg0/EZqxNBAx4of/oTnPjXAQi299VLq2gdnbZowGy9hzqv+O7sTA62g+lM1v+2FM5DUnJ/6hg=="], |
|---|
| 1097 | + |
|---|
| 1098 | + "react-native-css-interop": ["react-native-css-interop@0.2.2", "", { "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-2eUyl7RH1RT6TYbe5nm+d4HZ2Pr6Nmve158B57tb5W4Bo52Xzp+PFeWAdFnAr2HNB+r9b6qa8o3xH1YREVQU0g=="], |
|---|
| 1099 | + |
|---|
| 1100 | + "react-native-draggable-flatlist": ["react-native-draggable-flatlist@4.0.3", "", { "dependencies": { "@babel/preset-typescript": "^7.17.12" }, "peerDependencies": { "react-native": ">=0.64.0", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=2.8.0" } }, "sha512-2F4x5BFieWdGq9SetD2nSAR7s7oQCSgNllYgERRXXtNfSOuAGAVbDb/3H3lP0y5f7rEyNwabKorZAD/SyyNbDw=="], |
|---|
| 1101 | + |
|---|
| 1102 | + "react-native-gesture-handler": ["react-native-gesture-handler@2.30.0", "", { "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-5YsnKHGa0X9C8lb5oCnKm0fLUPM6CRduvUUw2Bav4RIj/C3HcFh4RIUnF8wgG6JQWCL1//gRx4v+LVWgcIQdGA=="], |
|---|
| 1103 | + |
|---|
| 1104 | + "react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.2.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q=="], |
|---|
| 1105 | + |
|---|
| 1106 | + "react-native-reanimated": ["react-native-reanimated@4.2.1", "", { "dependencies": { "react-native-is-edge-to-edge": "1.2.1", "semver": "7.7.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": ">=0.7.0" } }, "sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg=="], |
|---|
| 1107 | + |
|---|
| 1108 | + "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="], |
|---|
| 1109 | + |
|---|
| 1110 | + "react-native-screens": ["react-native-screens@4.23.0", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-XhO3aK0UeLpBn4kLecd+J+EDeRRJlI/Ro9Fze06vo1q163VeYtzfU9QS09/VyDFMWR1qxDC1iazCArTPSFFiPw=="], |
|---|
| 1111 | + |
|---|
| 1112 | + "react-native-svg": ["react-native-svg@15.15.3", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/k4KYwPBLGcx2f5d4FjE+vCScK7QOX14cl2lIASJ28u4slHHtIhL0SZKU7u9qmRBHxTCKPoPBtN6haT1NENJNA=="], |
|---|
| 1113 | + |
|---|
| 1114 | + "react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="], |
|---|
| 1115 | + |
|---|
| 1116 | + "react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="], |
|---|
| 1117 | + |
|---|
| 1118 | + "react-native-worklets": ["react-native-worklets@0.7.2", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "7.27.1", "@babel/plugin-transform-class-properties": "7.27.1", "@babel/plugin-transform-classes": "7.28.4", "@babel/plugin-transform-nullish-coalescing-operator": "7.27.1", "@babel/plugin-transform-optional-chaining": "7.27.1", "@babel/plugin-transform-shorthand-properties": "7.27.1", "@babel/plugin-transform-template-literals": "7.27.1", "@babel/plugin-transform-unicode-regex": "7.27.1", "@babel/preset-typescript": "7.27.1", "convert-source-map": "2.0.0", "semver": "7.7.3" }, "peerDependencies": { "@babel/core": "*", "react": "*", "react-native": "*" } }, "sha512-DuLu1kMV/Uyl9pQHp3hehAlThoLw7Yk2FwRTpzASOmI+cd4845FWn3m2bk9MnjUw8FBRIyhwLqYm2AJaXDXsog=="], |
|---|
| 1119 | + |
|---|
| 1120 | + "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], |
|---|
| 1121 | + |
|---|
| 1122 | + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], |
|---|
| 1123 | + |
|---|
| 1124 | + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], |
|---|
| 1125 | + |
|---|
| 1126 | + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], |
|---|
| 1127 | + |
|---|
| 1128 | + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], |
|---|
| 1129 | + |
|---|
| 1130 | + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], |
|---|
| 1131 | + |
|---|
| 1132 | + "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], |
|---|
| 1133 | + |
|---|
| 1134 | + "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="], |
|---|
| 1135 | + |
|---|
| 1136 | + "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="], |
|---|
| 1137 | + |
|---|
| 1138 | + "regexpu-core": ["regexpu-core@6.4.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="], |
|---|
| 1139 | + |
|---|
| 1140 | + "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], |
|---|
| 1141 | + |
|---|
| 1142 | + "regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": "bin/parser" }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="], |
|---|
| 1143 | + |
|---|
| 1144 | + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], |
|---|
| 1145 | + |
|---|
| 1146 | + "reselect": ["reselect@4.1.8", "", {}, "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="], |
|---|
| 1147 | + |
|---|
| 1148 | + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], |
|---|
| 1149 | + |
|---|
| 1150 | + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], |
|---|
| 1151 | + |
|---|
| 1152 | + "resolve-workspace-root": ["resolve-workspace-root@2.0.1", "", {}, "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w=="], |
|---|
| 1153 | + |
|---|
| 1154 | + "restore-cursor": ["restore-cursor@2.0.0", "", { "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" } }, "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q=="], |
|---|
| 1155 | + |
|---|
| 1156 | + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], |
|---|
| 1157 | + |
|---|
| 1158 | + "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": "bin.js" }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], |
|---|
| 1159 | + |
|---|
| 1160 | + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], |
|---|
| 1161 | + |
|---|
| 1162 | + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], |
|---|
| 1163 | + |
|---|
| 1164 | + "sax": ["sax@1.5.0", "", {}, "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA=="], |
|---|
| 1165 | + |
|---|
| 1166 | + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], |
|---|
| 1167 | + |
|---|
| 1168 | + "semver": ["semver@7.6.3", "", { "bin": "bin/semver.js" }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], |
|---|
| 1169 | + |
|---|
| 1170 | + "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], |
|---|
| 1171 | + |
|---|
| 1172 | + "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], |
|---|
| 1173 | + |
|---|
| 1174 | + "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], |
|---|
| 1175 | + |
|---|
| 1176 | + "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="], |
|---|
| 1177 | + |
|---|
| 1178 | + "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], |
|---|
| 1179 | + |
|---|
| 1180 | + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], |
|---|
| 1181 | + |
|---|
| 1182 | + "sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="], |
|---|
| 1183 | + |
|---|
| 1184 | + "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="], |
|---|
| 1185 | + |
|---|
| 1186 | + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], |
|---|
| 1187 | + |
|---|
| 1188 | + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], |
|---|
| 1189 | + |
|---|
| 1190 | + "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], |
|---|
| 1191 | + |
|---|
| 1192 | + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], |
|---|
| 1193 | + |
|---|
| 1194 | + "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="], |
|---|
| 1195 | + |
|---|
| 1196 | + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], |
|---|
| 1197 | + |
|---|
| 1198 | + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], |
|---|
| 1199 | + |
|---|
| 1200 | + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], |
|---|
| 1201 | + |
|---|
| 1202 | + "slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="], |
|---|
| 1203 | + |
|---|
| 1204 | + "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], |
|---|
| 1205 | + |
|---|
| 1206 | + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], |
|---|
| 1207 | + |
|---|
| 1208 | + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], |
|---|
| 1209 | + |
|---|
| 1210 | + "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], |
|---|
| 1211 | + |
|---|
| 1212 | + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], |
|---|
| 1213 | + |
|---|
| 1214 | + "stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="], |
|---|
| 1215 | + |
|---|
| 1216 | + "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], |
|---|
| 1217 | + |
|---|
| 1218 | + "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="], |
|---|
| 1219 | + |
|---|
| 1220 | + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], |
|---|
| 1221 | + |
|---|
| 1222 | + "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="], |
|---|
| 1223 | + |
|---|
| 1224 | + "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], |
|---|
| 1225 | + |
|---|
| 1226 | + "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=="], |
|---|
| 1227 | + |
|---|
| 1228 | + "strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="], |
|---|
| 1229 | + |
|---|
| 1230 | + "structured-headers": ["structured-headers@0.4.1", "", {}, "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="], |
|---|
| 1231 | + |
|---|
| 1232 | + "styleq": ["styleq@0.1.3", "", {}, "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="], |
|---|
| 1233 | + |
|---|
| 1234 | + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], |
|---|
| 1235 | + |
|---|
| 1236 | + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], |
|---|
| 1237 | + |
|---|
| 1238 | + "supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="], |
|---|
| 1239 | + |
|---|
| 1240 | + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], |
|---|
| 1241 | + |
|---|
| 1242 | + "tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="], |
|---|
| 1243 | + |
|---|
| 1244 | + "terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="], |
|---|
| 1245 | + |
|---|
| 1246 | + "terser": ["terser@5.46.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": "bin/terser" }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], |
|---|
| 1247 | + |
|---|
| 1248 | + "test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="], |
|---|
| 1249 | + |
|---|
| 1250 | + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], |
|---|
| 1251 | + |
|---|
| 1252 | + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], |
|---|
| 1253 | + |
|---|
| 1254 | + "throat": ["throat@5.0.0", "", {}, "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="], |
|---|
| 1255 | + |
|---|
| 1256 | + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], |
|---|
| 1257 | + |
|---|
| 1258 | + "tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="], |
|---|
| 1259 | + |
|---|
| 1260 | + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], |
|---|
| 1261 | + |
|---|
| 1262 | + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], |
|---|
| 1263 | + |
|---|
| 1264 | + "toqr": ["toqr@0.1.1", "", {}, "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA=="], |
|---|
| 1265 | + |
|---|
| 1266 | + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], |
|---|
| 1267 | + |
|---|
| 1268 | + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], |
|---|
| 1269 | + |
|---|
| 1270 | + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], |
|---|
| 1271 | + |
|---|
| 1272 | + "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="], |
|---|
| 1273 | + |
|---|
| 1274 | + "type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="], |
|---|
| 1275 | + |
|---|
| 1276 | + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], |
|---|
| 1277 | + |
|---|
| 1278 | + "ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": "script/cli.js" }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="], |
|---|
| 1279 | + |
|---|
| 1280 | + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], |
|---|
| 1281 | + |
|---|
| 1282 | + "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], |
|---|
| 1283 | + |
|---|
| 1284 | + "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="], |
|---|
| 1285 | + |
|---|
| 1286 | + "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.1", "", {}, "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg=="], |
|---|
| 1287 | + |
|---|
| 1288 | + "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.2.0", "", {}, "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ=="], |
|---|
| 1289 | + |
|---|
| 1290 | + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], |
|---|
| 1291 | + |
|---|
| 1292 | + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], |
|---|
| 1293 | + |
|---|
| 1294 | + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], |
|---|
| 1295 | + |
|---|
| 1296 | + "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="], |
|---|
| 1297 | + |
|---|
| 1298 | + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], |
|---|
| 1299 | + |
|---|
| 1300 | + "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], |
|---|
| 1301 | + |
|---|
| 1302 | + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], |
|---|
| 1303 | + |
|---|
| 1304 | + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], |
|---|
| 1305 | + |
|---|
| 1306 | + "uuid": ["uuid@7.0.3", "", { "bin": "dist/bin/uuid" }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="], |
|---|
| 1307 | + |
|---|
| 1308 | + "validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="], |
|---|
| 1309 | + |
|---|
| 1310 | + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], |
|---|
| 1311 | + |
|---|
| 1312 | + "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="], |
|---|
| 1313 | + |
|---|
| 1314 | + "vlq": ["vlq@1.0.1", "", {}, "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="], |
|---|
| 1315 | + |
|---|
| 1316 | + "walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="], |
|---|
| 1317 | + |
|---|
| 1318 | + "warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="], |
|---|
| 1319 | + |
|---|
| 1320 | + "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], |
|---|
| 1321 | + |
|---|
| 1322 | + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], |
|---|
| 1323 | + |
|---|
| 1324 | + "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="], |
|---|
| 1325 | + |
|---|
| 1326 | + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], |
|---|
| 1327 | + |
|---|
| 1328 | + "whatwg-url-minimum": ["whatwg-url-minimum@0.1.1", "", {}, "sha512-u2FNVjFVFZhdjb502KzXy1gKn1mEisQRJssmSJT8CPhZdZa0AP6VCbWlXERKyGu0l09t0k50FiDiralpGhBxgA=="], |
|---|
| 1329 | + |
|---|
| 1330 | + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], |
|---|
| 1331 | + |
|---|
| 1332 | + "wrap-ansi": ["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=="], |
|---|
| 1333 | + |
|---|
| 1334 | + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], |
|---|
| 1335 | + |
|---|
| 1336 | + "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=="], |
|---|
| 1337 | + |
|---|
| 1338 | + "ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], |
|---|
| 1339 | + |
|---|
| 1340 | + "xcode": ["xcode@3.0.1", "", { "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" } }, "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA=="], |
|---|
| 1341 | + |
|---|
| 1342 | + "xml2js": ["xml2js@0.6.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w=="], |
|---|
| 1343 | + |
|---|
| 1344 | + "xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], |
|---|
| 1345 | + |
|---|
| 1346 | + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], |
|---|
| 1347 | + |
|---|
| 1348 | + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], |
|---|
| 1349 | + |
|---|
| 1350 | + "yaml": ["yaml@2.8.2", "", { "bin": "bin.mjs" }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], |
|---|
| 1351 | + |
|---|
| 1352 | + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], |
|---|
| 1353 | + |
|---|
| 1354 | + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], |
|---|
| 1355 | + |
|---|
| 1356 | + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], |
|---|
| 1357 | + |
|---|
| 1358 | + "@babel/core/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1359 | + |
|---|
| 1360 | + "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], |
|---|
| 1361 | + |
|---|
| 1362 | + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1363 | + |
|---|
| 1364 | + "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1365 | + |
|---|
| 1366 | + "@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1367 | + |
|---|
| 1368 | + "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1369 | + |
|---|
| 1370 | + "@expo/cli/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], |
|---|
| 1371 | + |
|---|
| 1372 | + "@expo/cli/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|---|
| 1373 | + |
|---|
| 1374 | + "@expo/cli/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1375 | + |
|---|
| 1376 | + "@expo/cli/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], |
|---|
| 1377 | + |
|---|
| 1378 | + "@expo/config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], |
|---|
| 1379 | + |
|---|
| 1380 | + "@expo/config/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1381 | + |
|---|
| 1382 | + "@expo/config-plugins/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], |
|---|
| 1383 | + |
|---|
| 1384 | + "@expo/config-plugins/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1385 | + |
|---|
| 1386 | + "@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], |
|---|
| 1387 | + |
|---|
| 1388 | + "@expo/fingerprint/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], |
|---|
| 1389 | + |
|---|
| 1390 | + "@expo/fingerprint/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], |
|---|
| 1391 | + |
|---|
| 1392 | + "@expo/fingerprint/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1393 | + |
|---|
| 1394 | + "@expo/image-utils/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1395 | + |
|---|
| 1396 | + "@expo/metro-config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], |
|---|
| 1397 | + |
|---|
| 1398 | + "@expo/metro-config/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|---|
| 1399 | + |
|---|
| 1400 | + "@expo/prebuild-config/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1401 | + |
|---|
| 1402 | + "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], |
|---|
| 1403 | + |
|---|
| 1404 | + "@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=="], |
|---|
| 1405 | + |
|---|
| 1406 | + "@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], |
|---|
| 1407 | + |
|---|
| 1408 | + "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], |
|---|
| 1409 | + |
|---|
| 1410 | + "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], |
|---|
| 1411 | + |
|---|
| 1412 | + "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], |
|---|
| 1413 | + |
|---|
| 1414 | + "@react-native/babel-preset/@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw=="], |
|---|
| 1415 | + |
|---|
| 1416 | + "@react-native/babel-preset/@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-replace-supers": "^7.28.6", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q=="], |
|---|
| 1417 | + |
|---|
| 1418 | + "@react-native/babel-preset/@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg=="], |
|---|
| 1419 | + |
|---|
| 1420 | + "@react-native/babel-preset/@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w=="], |
|---|
| 1421 | + |
|---|
| 1422 | + "@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=="], |
|---|
| 1423 | + |
|---|
| 1424 | + "@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1425 | + |
|---|
| 1426 | + "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], |
|---|
| 1427 | + |
|---|
| 1428 | + "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1429 | + |
|---|
| 1430 | + "better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], |
|---|
| 1431 | + |
|---|
| 1432 | + "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], |
|---|
| 1433 | + |
|---|
| 1434 | + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], |
|---|
| 1435 | + |
|---|
| 1436 | + "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], |
|---|
| 1437 | + |
|---|
| 1438 | + "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], |
|---|
| 1439 | + |
|---|
| 1440 | + "compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], |
|---|
| 1441 | + |
|---|
| 1442 | + "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], |
|---|
| 1443 | + |
|---|
| 1444 | + "css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], |
|---|
| 1445 | + |
|---|
| 1446 | + "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], |
|---|
| 1447 | + |
|---|
| 1448 | + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], |
|---|
| 1449 | + |
|---|
| 1450 | + "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], |
|---|
| 1451 | + |
|---|
| 1452 | + "fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|---|
| 1453 | + |
|---|
| 1454 | + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], |
|---|
| 1455 | + |
|---|
| 1456 | + "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], |
|---|
| 1457 | + |
|---|
| 1458 | + "finalhandler/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], |
|---|
| 1459 | + |
|---|
| 1460 | + "finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], |
|---|
| 1461 | + |
|---|
| 1462 | + "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], |
|---|
| 1463 | + |
|---|
| 1464 | + "istanbul-lib-instrument/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], |
|---|
| 1465 | + |
|---|
| 1466 | + "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], |
|---|
| 1467 | + |
|---|
| 1468 | + "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], |
|---|
| 1469 | + |
|---|
| 1470 | + "log-symbols/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=="], |
|---|
| 1471 | + |
|---|
| 1472 | + "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], |
|---|
| 1473 | + |
|---|
| 1474 | + "npm-package-arg/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1475 | + |
|---|
| 1476 | + "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=="], |
|---|
| 1477 | + |
|---|
| 1478 | + "path-scurry/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1479 | + |
|---|
| 1480 | + "pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], |
|---|
| 1481 | + |
|---|
| 1482 | + "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=="], |
|---|
| 1483 | + |
|---|
| 1484 | + "react-native/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1485 | + |
|---|
| 1486 | + "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=="], |
|---|
| 1487 | + |
|---|
| 1488 | + "react-native-css-interop/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], |
|---|
| 1489 | + |
|---|
| 1490 | + "react-native-reanimated/semver": ["semver@7.7.3", "", { "bin": "bin/semver.js" }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], |
|---|
| 1491 | + |
|---|
| 1492 | + "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="], |
|---|
| 1493 | + |
|---|
| 1494 | + "react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="], |
|---|
| 1495 | + |
|---|
| 1496 | + "react-native-worklets/@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="], |
|---|
| 1497 | + |
|---|
| 1498 | + "react-native-worklets/semver": ["semver@7.7.3", "", { "bin": "bin/semver.js" }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], |
|---|
| 1499 | + |
|---|
| 1500 | + "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=="], |
|---|
| 1501 | + |
|---|
| 1502 | + "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], |
|---|
| 1503 | + |
|---|
| 1504 | + "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], |
|---|
| 1505 | + |
|---|
| 1506 | + "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], |
|---|
| 1507 | + |
|---|
| 1508 | + "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], |
|---|
| 1509 | + |
|---|
| 1510 | + "strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], |
|---|
| 1511 | + |
|---|
| 1512 | + "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], |
|---|
| 1513 | + |
|---|
| 1514 | + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], |
|---|
| 1515 | + |
|---|
| 1516 | + "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=="], |
|---|
| 1517 | + |
|---|
| 1518 | + "test-exclude/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], |
|---|
| 1519 | + |
|---|
| 1520 | + "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], |
|---|
| 1521 | + |
|---|
| 1522 | + "wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], |
|---|
| 1523 | + |
|---|
| 1524 | + "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], |
|---|
| 1525 | + |
|---|
| 1526 | + "xml2js/xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], |
|---|
| 1527 | + |
|---|
| 1528 | + "@expo/cli/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], |
|---|
| 1529 | + |
|---|
| 1530 | + "@expo/cli/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1531 | + |
|---|
| 1532 | + "@expo/cli/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], |
|---|
| 1533 | + |
|---|
| 1534 | + "@expo/config-plugins/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], |
|---|
| 1535 | + |
|---|
| 1536 | + "@expo/config-plugins/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1537 | + |
|---|
| 1538 | + "@expo/config-plugins/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], |
|---|
| 1539 | + |
|---|
| 1540 | + "@expo/config/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], |
|---|
| 1541 | + |
|---|
| 1542 | + "@expo/config/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1543 | + |
|---|
| 1544 | + "@expo/config/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], |
|---|
| 1545 | + |
|---|
| 1546 | + "@expo/fingerprint/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1547 | + |
|---|
| 1548 | + "@expo/fingerprint/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], |
|---|
| 1549 | + |
|---|
| 1550 | + "@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], |
|---|
| 1551 | + |
|---|
| 1552 | + "@expo/metro-config/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], |
|---|
| 1553 | + |
|---|
| 1554 | + "@expo/metro-config/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], |
|---|
| 1555 | + |
|---|
| 1556 | + "@expo/metro-config/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], |
|---|
| 1557 | + |
|---|
| 1558 | + "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], |
|---|
| 1559 | + |
|---|
| 1560 | + "@istanbuljs/load-nyc-config/find-up/path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], |
|---|
| 1561 | + |
|---|
| 1562 | + "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], |
|---|
| 1563 | + |
|---|
| 1564 | + "@react-native/codegen/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], |
|---|
| 1565 | + |
|---|
| 1566 | + "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], |
|---|
| 1567 | + |
|---|
| 1568 | + "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], |
|---|
| 1569 | + |
|---|
| 1570 | + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], |
|---|
| 1571 | + |
|---|
| 1572 | + "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], |
|---|
| 1573 | + |
|---|
| 1574 | + "log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], |
|---|
| 1575 | + |
|---|
| 1576 | + "log-symbols/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], |
|---|
| 1577 | + |
|---|
| 1578 | + "log-symbols/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], |
|---|
| 1579 | + |
|---|
| 1580 | + "ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], |
|---|
| 1581 | + |
|---|
| 1582 | + "ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], |
|---|
| 1583 | + |
|---|
| 1584 | + "ora/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], |
|---|
| 1585 | + |
|---|
| 1586 | + "react-native-css-interop/lightningcss/detect-libc": ["detect-libc@1.0.3", "", { "bin": "bin/detect-libc.js" }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], |
|---|
| 1587 | + |
|---|
| 1588 | + "react-native-css-interop/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.27.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gl/lqIXY+d+ySmMbgDf0pgaWSqrWYxVHoc88q+Vhf2YNzZ8DwoRzGt5NZDVqqIW5ScpSnmmjcgXP87Dn2ylSSQ=="], |
|---|
| 1589 | + |
|---|
| 1590 | + "react-native-css-interop/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.27.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-0+mZa54IlcNAoQS9E0+niovhyjjQWEMrwW0p2sSdLRhLDc8LMQ/b67z7+B5q4VmjYCMSfnFi3djAAQFIDuj/Tg=="], |
|---|
| 1591 | + |
|---|
| 1592 | + "react-native-css-interop/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.27.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-n1sEf85fePoU2aDN2PzYjoI8gbBqnmLGEhKq7q0DKLj0UTVmOTwDC7PtLcy/zFxzASTSBlVQYJUhwIStQMIpRA=="], |
|---|
| 1593 | + |
|---|
| 1594 | + "react-native-css-interop/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.27.0", "", { "os": "linux", "cpu": "arm" }, "sha512-MUMRmtdRkOkd5z3h986HOuNBD1c2lq2BSQA1Jg88d9I7bmPGx08bwGcnB75dvr17CwxjxD6XPi3Qh8ArmKFqCA=="], |
|---|
| 1595 | + |
|---|
| 1596 | + "react-native-css-interop/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.27.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-cPsxo1QEWq2sfKkSq2Bq5feQDHdUEwgtA9KaB27J5AX22+l4l0ptgjMZZtYtUnteBofjee+0oW1wQ1guv04a7A=="], |
|---|
| 1597 | + |
|---|
| 1598 | + "react-native-css-interop/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.27.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg=="], |
|---|
| 1599 | + |
|---|
| 1600 | + "react-native-css-interop/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.27.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A=="], |
|---|
| 1601 | + |
|---|
| 1602 | + "react-native-css-interop/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.27.0", "", { "os": "linux", "cpu": "x64" }, "sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA=="], |
|---|
| 1603 | + |
|---|
| 1604 | + "react-native-css-interop/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.27.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ=="], |
|---|
| 1605 | + |
|---|
| 1606 | + "react-native-css-interop/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.27.0", "", { "os": "win32", "cpu": "x64" }, "sha512-/OJLj94Zm/waZShL8nB5jsNj3CfNATLCTyFxZyouilfTmSoLDX7VlVAmhPHoZWVFp4vdmoiEbPEYC8HID3m6yw=="], |
|---|
| 1607 | + |
|---|
| 1608 | + "react-native/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], |
|---|
| 1609 | + |
|---|
| 1610 | + "rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], |
|---|
| 1611 | + |
|---|
| 1612 | + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], |
|---|
| 1613 | + |
|---|
| 1614 | + "test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], |
|---|
| 1615 | + |
|---|
| 1616 | + "@expo/cli/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], |
|---|
| 1617 | + |
|---|
| 1618 | + "@expo/cli/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], |
|---|
| 1619 | + |
|---|
| 1620 | + "@expo/config-plugins/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], |
|---|
| 1621 | + |
|---|
| 1622 | + "@expo/config-plugins/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], |
|---|
| 1623 | + |
|---|
| 1624 | + "@expo/config/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], |
|---|
| 1625 | + |
|---|
| 1626 | + "@expo/config/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], |
|---|
| 1627 | + |
|---|
| 1628 | + "@expo/fingerprint/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], |
|---|
| 1629 | + |
|---|
| 1630 | + "@expo/fingerprint/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], |
|---|
| 1631 | + |
|---|
| 1632 | + "@expo/metro-config/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], |
|---|
| 1633 | + |
|---|
| 1634 | + "@expo/metro-config/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], |
|---|
| 1635 | + |
|---|
| 1636 | + "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], |
|---|
| 1637 | + |
|---|
| 1638 | + "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], |
|---|
| 1639 | + |
|---|
| 1640 | + "log-symbols/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], |
|---|
| 1641 | + |
|---|
| 1642 | + "log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], |
|---|
| 1643 | + |
|---|
| 1644 | + "ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], |
|---|
| 1645 | + |
|---|
| 1646 | + "ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], |
|---|
| 1647 | + |
|---|
| 1648 | + "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], |
|---|
| 1649 | + |
|---|
| 1650 | + "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], |
|---|
| 1651 | + |
|---|
| 1652 | + "@expo/cli/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], |
|---|
| 1653 | + |
|---|
| 1654 | + "@expo/config-plugins/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], |
|---|
| 1655 | + |
|---|
| 1656 | + "@expo/config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], |
|---|
| 1657 | + |
|---|
| 1658 | + "@expo/metro-config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], |
|---|
| 1659 | + |
|---|
| 1660 | + "log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], |
|---|
| 1661 | + |
|---|
| 1662 | + "ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], |
|---|
| 1663 | + } |
|---|
| 1664 | +} |
|---|
| .. | .. |
|---|
| 1 | +/** |
|---|
| 2 | + * SessionDrawer — Gmail-style left drawer for session navigation. |
|---|
| 3 | + * |
|---|
| 4 | + * Slides in from the left with a dark overlay. Shows sessions with |
|---|
| 5 | + * unread badges. Swipe left to remove, long press to rename. |
|---|
| 6 | + */ |
|---|
| 7 | +import React, { useCallback, useEffect, useRef, useState } from "react"; |
|---|
| 8 | +import { |
|---|
| 9 | + Animated, |
|---|
| 10 | + Dimensions, |
|---|
| 11 | + Keyboard, |
|---|
| 12 | + LayoutAnimation, |
|---|
| 13 | + Pressable, |
|---|
| 14 | + StyleSheet, |
|---|
| 15 | + Text, |
|---|
| 16 | + TextInput, |
|---|
| 17 | + View, |
|---|
| 18 | +} from "react-native"; |
|---|
| 19 | +import { |
|---|
| 20 | + GestureHandlerRootView, |
|---|
| 21 | + Swipeable, |
|---|
| 22 | +} from "react-native-gesture-handler"; |
|---|
| 23 | +import DraggableFlatList, { |
|---|
| 24 | + RenderItemParams, |
|---|
| 25 | + ScaleDecorator, |
|---|
| 26 | +} from "react-native-draggable-flatlist"; |
|---|
| 27 | +import * as Haptics from "expo-haptics"; |
|---|
| 28 | +import { WsSession } from "../types"; |
|---|
| 29 | +import { useChat } from "../contexts/ChatContext"; |
|---|
| 30 | +import { useTheme, type ThemeColors } from "../contexts/ThemeContext"; |
|---|
| 31 | + |
|---|
| 32 | +const SCREEN_WIDTH = Dimensions.get("window").width; |
|---|
| 33 | +const DRAWER_WIDTH = SCREEN_WIDTH * 0.82; |
|---|
| 34 | +const ROW_WIDTH = DRAWER_WIDTH; |
|---|
| 35 | + |
|---|
| 36 | +interface SessionDrawerProps { |
|---|
| 37 | + visible: boolean; |
|---|
| 38 | + onClose: () => void; |
|---|
| 39 | +} |
|---|
| 40 | + |
|---|
| 41 | +/* ── Swipeable row ── */ |
|---|
| 42 | + |
|---|
| 43 | +function SessionRow({ |
|---|
| 44 | + session, |
|---|
| 45 | + unreadCount, |
|---|
| 46 | + onSwitch, |
|---|
| 47 | + onLongPress, |
|---|
| 48 | + onDelete, |
|---|
| 49 | + onDrag, |
|---|
| 50 | + isDragging, |
|---|
| 51 | + colors, |
|---|
| 52 | +}: { |
|---|
| 53 | + session: WsSession; |
|---|
| 54 | + unreadCount: number; |
|---|
| 55 | + onSwitch: () => void; |
|---|
| 56 | + onLongPress: () => void; |
|---|
| 57 | + onDelete: () => void; |
|---|
| 58 | + onDrag: () => void; |
|---|
| 59 | + isDragging: boolean; |
|---|
| 60 | + colors: ThemeColors; |
|---|
| 61 | +}) { |
|---|
| 62 | + const swipeRef = useRef<Swipeable>(null); |
|---|
| 63 | + |
|---|
| 64 | + const renderRightActions = ( |
|---|
| 65 | + _progress: Animated.AnimatedInterpolation<number>, |
|---|
| 66 | + dragX: Animated.AnimatedInterpolation<number>, |
|---|
| 67 | + ) => { |
|---|
| 68 | + const scale = dragX.interpolate({ |
|---|
| 69 | + inputRange: [-80, -40, 0], |
|---|
| 70 | + outputRange: [1, 0.8, 0], |
|---|
| 71 | + extrapolate: "clamp", |
|---|
| 72 | + }); |
|---|
| 73 | + return ( |
|---|
| 74 | + <Pressable |
|---|
| 75 | + onPress={() => { |
|---|
| 76 | + swipeRef.current?.close(); |
|---|
| 77 | + onDelete(); |
|---|
| 78 | + }} |
|---|
| 79 | + style={{ |
|---|
| 80 | + backgroundColor: colors.danger, |
|---|
| 81 | + justifyContent: "center", |
|---|
| 82 | + alignItems: "center", |
|---|
| 83 | + width: 72, |
|---|
| 84 | + borderRadius: 12, |
|---|
| 85 | + marginLeft: 8, |
|---|
| 86 | + }} |
|---|
| 87 | + > |
|---|
| 88 | + <Animated.Text |
|---|
| 89 | + style={{ |
|---|
| 90 | + color: "#FFF", |
|---|
| 91 | + fontSize: 13, |
|---|
| 92 | + fontWeight: "600", |
|---|
| 93 | + transform: [{ scale }], |
|---|
| 94 | + }} |
|---|
| 95 | + > |
|---|
| 96 | + Remove |
|---|
| 97 | + </Animated.Text> |
|---|
| 98 | + </Pressable> |
|---|
| 99 | + ); |
|---|
| 100 | + }; |
|---|
| 101 | + |
|---|
| 102 | + return ( |
|---|
| 103 | + <View style={{ width: ROW_WIDTH }}> |
|---|
| 104 | + <Swipeable |
|---|
| 105 | + ref={swipeRef} |
|---|
| 106 | + renderRightActions={renderRightActions} |
|---|
| 107 | + rightThreshold={50} |
|---|
| 108 | + friction={2} |
|---|
| 109 | + overshootRight={false} |
|---|
| 110 | + > |
|---|
| 111 | + <Pressable onPress={onSwitch} onLongPress={onLongPress} delayLongPress={400}> |
|---|
| 112 | + <View |
|---|
| 113 | + style={{ |
|---|
| 114 | + width: ROW_WIDTH, |
|---|
| 115 | + flexDirection: "row", |
|---|
| 116 | + alignItems: "center", |
|---|
| 117 | + paddingVertical: 14, |
|---|
| 118 | + paddingLeft: 16, |
|---|
| 119 | + paddingRight: 12, |
|---|
| 120 | + backgroundColor: session.isActive ? colors.accentBg : "transparent", |
|---|
| 121 | + borderRadius: 12, |
|---|
| 122 | + opacity: isDragging ? 0.8 : 1, |
|---|
| 123 | + }} |
|---|
| 124 | + > |
|---|
| 125 | + {/* Icon — left */} |
|---|
| 126 | + <View |
|---|
| 127 | + style={{ |
|---|
| 128 | + width: 40, |
|---|
| 129 | + height: 40, |
|---|
| 130 | + borderRadius: 20, |
|---|
| 131 | + backgroundColor: session.isActive ? colors.accent : colors.border, |
|---|
| 132 | + alignItems: "center", |
|---|
| 133 | + justifyContent: "center", |
|---|
| 134 | + }} |
|---|
| 135 | + > |
|---|
| 136 | + {session.isActive ? ( |
|---|
| 137 | + <View |
|---|
| 138 | + style={{ |
|---|
| 139 | + width: 10, |
|---|
| 140 | + height: 10, |
|---|
| 141 | + borderRadius: 5, |
|---|
| 142 | + backgroundColor: "#FFF", |
|---|
| 143 | + }} |
|---|
| 144 | + /> |
|---|
| 145 | + ) : ( |
|---|
| 146 | + <Text style={{ color: colors.textSecondary, fontSize: 15, fontWeight: "700" }}> |
|---|
| 147 | + {session.kind === "api" ? "A" : "T"} |
|---|
| 148 | + </Text> |
|---|
| 149 | + )} |
|---|
| 150 | + </View> |
|---|
| 151 | + |
|---|
| 152 | + {/* Name + subtitle — middle */} |
|---|
| 153 | + <View style={{ flex: 1, marginLeft: 14 }}> |
|---|
| 154 | + <Text |
|---|
| 155 | + style={{ |
|---|
| 156 | + color: session.isActive ? colors.accent : colors.text, |
|---|
| 157 | + fontSize: 17, |
|---|
| 158 | + fontWeight: session.isActive ? "700" : "600", |
|---|
| 159 | + }} |
|---|
| 160 | + numberOfLines={1} |
|---|
| 161 | + > |
|---|
| 162 | + {session.name} |
|---|
| 163 | + </Text> |
|---|
| 164 | + <Text |
|---|
| 165 | + style={{ |
|---|
| 166 | + color: colors.textMuted, |
|---|
| 167 | + fontSize: 12, |
|---|
| 168 | + marginTop: 2, |
|---|
| 169 | + }} |
|---|
| 170 | + numberOfLines={1} |
|---|
| 171 | + > |
|---|
| 172 | + {session.kind === "api" ? "Headless" : "Terminal"} |
|---|
| 173 | + {session.isActive ? " — active" : ""} |
|---|
| 174 | + </Text> |
|---|
| 175 | + </View> |
|---|
| 176 | + |
|---|
| 177 | + {/* Unread badge */} |
|---|
| 178 | + {unreadCount > 0 && ( |
|---|
| 179 | + <View |
|---|
| 180 | + style={{ |
|---|
| 181 | + minWidth: 24, |
|---|
| 182 | + height: 24, |
|---|
| 183 | + borderRadius: 12, |
|---|
| 184 | + backgroundColor: colors.accent, |
|---|
| 185 | + alignItems: "center", |
|---|
| 186 | + justifyContent: "center", |
|---|
| 187 | + paddingHorizontal: 7, |
|---|
| 188 | + }} |
|---|
| 189 | + > |
|---|
| 190 | + <Text style={{ color: "#FFF", fontSize: 12, fontWeight: "700" }}> |
|---|
| 191 | + {unreadCount > 99 ? "99+" : unreadCount} |
|---|
| 192 | + </Text> |
|---|
| 193 | + </View> |
|---|
| 194 | + )} |
|---|
| 195 | + |
|---|
| 196 | + {/* Drag handle */} |
|---|
| 197 | + <Pressable |
|---|
| 198 | + onPressIn={onDrag} |
|---|
| 199 | + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 200 | + style={{ |
|---|
| 201 | + marginLeft: 8, |
|---|
| 202 | + paddingHorizontal: 4, |
|---|
| 203 | + paddingVertical: 8, |
|---|
| 204 | + }} |
|---|
| 205 | + > |
|---|
| 206 | + <Text style={{ color: colors.textMuted, fontSize: 16, letterSpacing: 1 }}>⋮⋮</Text> |
|---|
| 207 | + </Pressable> |
|---|
| 208 | + </View> |
|---|
| 209 | + </Pressable> |
|---|
| 210 | + </Swipeable> |
|---|
| 211 | + </View> |
|---|
| 212 | + ); |
|---|
| 213 | +} |
|---|
| 214 | + |
|---|
| 215 | +/* ── Inline rename ── */ |
|---|
| 216 | + |
|---|
| 217 | +function RenameEditor({ |
|---|
| 218 | + name, |
|---|
| 219 | + onConfirm, |
|---|
| 220 | + onCancel, |
|---|
| 221 | + colors, |
|---|
| 222 | +}: { |
|---|
| 223 | + name: string; |
|---|
| 224 | + onConfirm: (newName: string) => void; |
|---|
| 225 | + onCancel: () => void; |
|---|
| 226 | + colors: ThemeColors; |
|---|
| 227 | +}) { |
|---|
| 228 | + const [editName, setEditName] = useState(name); |
|---|
| 229 | + return ( |
|---|
| 230 | + <View style={{ paddingHorizontal: 16, paddingVertical: 8, width: ROW_WIDTH }}> |
|---|
| 231 | + <TextInput |
|---|
| 232 | + value={editName} |
|---|
| 233 | + onChangeText={setEditName} |
|---|
| 234 | + autoFocus |
|---|
| 235 | + onSubmitEditing={() => onConfirm(editName.trim())} |
|---|
| 236 | + onBlur={onCancel} |
|---|
| 237 | + returnKeyType="done" |
|---|
| 238 | + style={{ |
|---|
| 239 | + color: colors.text, |
|---|
| 240 | + fontSize: 17, |
|---|
| 241 | + fontWeight: "600", |
|---|
| 242 | + borderBottomWidth: 2, |
|---|
| 243 | + borderBottomColor: colors.accent, |
|---|
| 244 | + paddingVertical: 10, |
|---|
| 245 | + paddingHorizontal: 4, |
|---|
| 246 | + }} |
|---|
| 247 | + placeholderTextColor={colors.textMuted} |
|---|
| 248 | + placeholder="Session name..." |
|---|
| 249 | + /> |
|---|
| 250 | + </View> |
|---|
| 251 | + ); |
|---|
| 252 | +} |
|---|
| 253 | + |
|---|
| 254 | +/* ── Main Drawer ── */ |
|---|
| 255 | + |
|---|
| 256 | +export function SessionDrawer({ visible, onClose }: SessionDrawerProps) { |
|---|
| 257 | + const { |
|---|
| 258 | + sessions, |
|---|
| 259 | + activeSessionId, |
|---|
| 260 | + requestSessions, |
|---|
| 261 | + switchSession, |
|---|
| 262 | + renameSession, |
|---|
| 263 | + removeSession, |
|---|
| 264 | + createSession, |
|---|
| 265 | + unreadCounts, |
|---|
| 266 | + } = useChat(); |
|---|
| 267 | + const { colors } = useTheme(); |
|---|
| 268 | + const [editingId, setEditingId] = useState<string | null>(null); |
|---|
| 269 | + const slideAnim = useRef(new Animated.Value(-DRAWER_WIDTH)).current; |
|---|
| 270 | + const fadeAnim = useRef(new Animated.Value(0)).current; |
|---|
| 271 | + const [rendered, setRendered] = useState(false); |
|---|
| 272 | + |
|---|
| 273 | + // Local ordering: merge server sessions while preserving user's drag order |
|---|
| 274 | + const [orderedSessions, setOrderedSessions] = useState<WsSession[]>([]); |
|---|
| 275 | + useEffect(() => { |
|---|
| 276 | + setOrderedSessions((prev) => { |
|---|
| 277 | + if (prev.length === 0) return sessions; |
|---|
| 278 | + const serverIds = new Set(sessions.map((s) => s.id)); |
|---|
| 279 | + // Keep existing order, update session data, remove deleted |
|---|
| 280 | + const kept = prev |
|---|
| 281 | + .filter((p) => serverIds.has(p.id)) |
|---|
| 282 | + .map((p) => sessions.find((s) => s.id === p.id)!); |
|---|
| 283 | + // Append any new sessions at the end |
|---|
| 284 | + const keptIds = new Set(kept.map((s) => s.id)); |
|---|
| 285 | + const added = sessions.filter((s) => !keptIds.has(s.id)); |
|---|
| 286 | + return [...kept, ...added]; |
|---|
| 287 | + }); |
|---|
| 288 | + }, [sessions]); |
|---|
| 289 | + |
|---|
| 290 | + useEffect(() => { |
|---|
| 291 | + if (visible) { |
|---|
| 292 | + Keyboard.dismiss(); |
|---|
| 293 | + setRendered(true); |
|---|
| 294 | + requestSessions(); |
|---|
| 295 | + Animated.parallel([ |
|---|
| 296 | + Animated.spring(slideAnim, { |
|---|
| 297 | + toValue: 0, |
|---|
| 298 | + useNativeDriver: true, |
|---|
| 299 | + damping: 22, |
|---|
| 300 | + stiffness: 200, |
|---|
| 301 | + }), |
|---|
| 302 | + Animated.timing(fadeAnim, { |
|---|
| 303 | + toValue: 1, |
|---|
| 304 | + duration: 200, |
|---|
| 305 | + useNativeDriver: true, |
|---|
| 306 | + }), |
|---|
| 307 | + ]).start(); |
|---|
| 308 | + } else { |
|---|
| 309 | + Animated.parallel([ |
|---|
| 310 | + Animated.timing(slideAnim, { |
|---|
| 311 | + toValue: -DRAWER_WIDTH, |
|---|
| 312 | + duration: 200, |
|---|
| 313 | + useNativeDriver: true, |
|---|
| 314 | + }), |
|---|
| 315 | + Animated.timing(fadeAnim, { |
|---|
| 316 | + toValue: 0, |
|---|
| 317 | + duration: 200, |
|---|
| 318 | + useNativeDriver: true, |
|---|
| 319 | + }), |
|---|
| 320 | + ]).start(() => { |
|---|
| 321 | + setRendered(false); |
|---|
| 322 | + setEditingId(null); |
|---|
| 323 | + }); |
|---|
| 324 | + } |
|---|
| 325 | + }, [visible]); |
|---|
| 326 | + |
|---|
| 327 | + const handleClose = useCallback(() => { |
|---|
| 328 | + setEditingId(null); |
|---|
| 329 | + Keyboard.dismiss(); |
|---|
| 330 | + onClose(); |
|---|
| 331 | + }, [onClose]); |
|---|
| 332 | + |
|---|
| 333 | + const handleSwitch = useCallback( |
|---|
| 334 | + (session: WsSession) => { |
|---|
| 335 | + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); |
|---|
| 336 | + switchSession(session.id); |
|---|
| 337 | + handleClose(); |
|---|
| 338 | + }, |
|---|
| 339 | + [switchSession, handleClose], |
|---|
| 340 | + ); |
|---|
| 341 | + |
|---|
| 342 | + const handleStartRename = useCallback((session: WsSession) => { |
|---|
| 343 | + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); |
|---|
| 344 | + setEditingId(session.id); |
|---|
| 345 | + }, []); |
|---|
| 346 | + |
|---|
| 347 | + const handleConfirmRename = useCallback( |
|---|
| 348 | + (sessionId: string, newName: string) => { |
|---|
| 349 | + if (newName) renameSession(sessionId, newName); |
|---|
| 350 | + setEditingId(null); |
|---|
| 351 | + }, |
|---|
| 352 | + [renameSession], |
|---|
| 353 | + ); |
|---|
| 354 | + |
|---|
| 355 | + const handleRemove = useCallback( |
|---|
| 356 | + (session: WsSession) => { |
|---|
| 357 | + Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning); |
|---|
| 358 | + LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); |
|---|
| 359 | + removeSession(session.id); |
|---|
| 360 | + }, |
|---|
| 361 | + [removeSession], |
|---|
| 362 | + ); |
|---|
| 363 | + |
|---|
| 364 | + const handleNewSession = useCallback(() => { |
|---|
| 365 | + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); |
|---|
| 366 | + createSession(); |
|---|
| 367 | + handleClose(); |
|---|
| 368 | + setTimeout(() => requestSessions(), 2500); |
|---|
| 369 | + }, [createSession, requestSessions, handleClose]); |
|---|
| 370 | + |
|---|
| 371 | + const renderItem = useCallback( |
|---|
| 372 | + ({ item, drag, isActive }: RenderItemParams<WsSession>) => { |
|---|
| 373 | + if (editingId === item.id) { |
|---|
| 374 | + return ( |
|---|
| 375 | + <RenameEditor |
|---|
| 376 | + name={item.name} |
|---|
| 377 | + onConfirm={(name) => handleConfirmRename(item.id, name)} |
|---|
| 378 | + onCancel={() => setEditingId(null)} |
|---|
| 379 | + colors={colors} |
|---|
| 380 | + /> |
|---|
| 381 | + ); |
|---|
| 382 | + } |
|---|
| 383 | + return ( |
|---|
| 384 | + <ScaleDecorator> |
|---|
| 385 | + <SessionRow |
|---|
| 386 | + session={item} |
|---|
| 387 | + unreadCount={unreadCounts[item.id] ?? 0} |
|---|
| 388 | + onSwitch={() => handleSwitch(item)} |
|---|
| 389 | + onLongPress={() => handleStartRename(item)} |
|---|
| 390 | + onDelete={() => handleRemove(item)} |
|---|
| 391 | + onDrag={drag} |
|---|
| 392 | + isDragging={isActive} |
|---|
| 393 | + colors={colors} |
|---|
| 394 | + /> |
|---|
| 395 | + </ScaleDecorator> |
|---|
| 396 | + ); |
|---|
| 397 | + }, |
|---|
| 398 | + [editingId, unreadCounts, colors, handleSwitch, handleStartRename, handleRemove, handleConfirmRename], |
|---|
| 399 | + ); |
|---|
| 400 | + |
|---|
| 401 | + const keyExtractor = useCallback((item: WsSession) => item.id, []); |
|---|
| 402 | + |
|---|
| 403 | + const handleDragEnd = useCallback( |
|---|
| 404 | + ({ data }: { data: WsSession[] }) => { |
|---|
| 405 | + setOrderedSessions(data); |
|---|
| 406 | + }, |
|---|
| 407 | + [], |
|---|
| 408 | + ); |
|---|
| 409 | + |
|---|
| 410 | + const renderSeparator = useCallback( |
|---|
| 411 | + () => ( |
|---|
| 412 | + <View |
|---|
| 413 | + style={{ |
|---|
| 414 | + height: 1, |
|---|
| 415 | + backgroundColor: colors.border, |
|---|
| 416 | + marginHorizontal: 16, |
|---|
| 417 | + marginVertical: 1, |
|---|
| 418 | + }} |
|---|
| 419 | + /> |
|---|
| 420 | + ), |
|---|
| 421 | + [colors.border], |
|---|
| 422 | + ); |
|---|
| 423 | + |
|---|
| 424 | + if (!rendered) return null; |
|---|
| 425 | + |
|---|
| 426 | + return ( |
|---|
| 427 | + <View style={StyleSheet.absoluteFill} pointerEvents="box-none"> |
|---|
| 428 | + <View style={{ ...StyleSheet.absoluteFillObject, zIndex: 100 }}> |
|---|
| 429 | + {/* Backdrop */} |
|---|
| 430 | + <Animated.View |
|---|
| 431 | + style={{ |
|---|
| 432 | + ...StyleSheet.absoluteFillObject, |
|---|
| 433 | + backgroundColor: "rgba(0,0,0,0.5)", |
|---|
| 434 | + opacity: fadeAnim, |
|---|
| 435 | + }} |
|---|
| 436 | + > |
|---|
| 437 | + <Pressable style={{ flex: 1 }} onPress={handleClose} /> |
|---|
| 438 | + </Animated.View> |
|---|
| 439 | + |
|---|
| 440 | + {/* Drawer panel */} |
|---|
| 441 | + <Animated.View |
|---|
| 442 | + style={{ |
|---|
| 443 | + position: "absolute", |
|---|
| 444 | + top: 0, |
|---|
| 445 | + bottom: 0, |
|---|
| 446 | + left: 0, |
|---|
| 447 | + width: DRAWER_WIDTH, |
|---|
| 448 | + backgroundColor: colors.bgSecondary, |
|---|
| 449 | + transform: [{ translateX: slideAnim }], |
|---|
| 450 | + shadowColor: "#000", |
|---|
| 451 | + shadowOffset: { width: 4, height: 0 }, |
|---|
| 452 | + shadowOpacity: 0.4, |
|---|
| 453 | + shadowRadius: 12, |
|---|
| 454 | + elevation: 20, |
|---|
| 455 | + }} |
|---|
| 456 | + > |
|---|
| 457 | + <GestureHandlerRootView style={{ flex: 1 }}> |
|---|
| 458 | + {/* Header */} |
|---|
| 459 | + <View |
|---|
| 460 | + style={{ |
|---|
| 461 | + paddingTop: 60, |
|---|
| 462 | + paddingHorizontal: 20, |
|---|
| 463 | + paddingBottom: 16, |
|---|
| 464 | + borderBottomWidth: 1, |
|---|
| 465 | + borderBottomColor: colors.border, |
|---|
| 466 | + }} |
|---|
| 467 | + > |
|---|
| 468 | + <View |
|---|
| 469 | + style={{ |
|---|
| 470 | + flexDirection: "row", |
|---|
| 471 | + alignItems: "center", |
|---|
| 472 | + justifyContent: "space-between", |
|---|
| 473 | + }} |
|---|
| 474 | + > |
|---|
| 475 | + <Text |
|---|
| 476 | + style={{ |
|---|
| 477 | + color: colors.text, |
|---|
| 478 | + fontSize: 22, |
|---|
| 479 | + fontWeight: "800", |
|---|
| 480 | + letterSpacing: -0.5, |
|---|
| 481 | + }} |
|---|
| 482 | + > |
|---|
| 483 | + Sessions |
|---|
| 484 | + </Text> |
|---|
| 485 | + <View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}> |
|---|
| 486 | + <Pressable |
|---|
| 487 | + onPress={() => requestSessions()} |
|---|
| 488 | + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 489 | + style={({ pressed }) => ({ |
|---|
| 490 | + paddingHorizontal: 10, |
|---|
| 491 | + paddingVertical: 5, |
|---|
| 492 | + borderRadius: 10, |
|---|
| 493 | + backgroundColor: pressed ? colors.bgTertiary : colors.bgTertiary + "80", |
|---|
| 494 | + })} |
|---|
| 495 | + > |
|---|
| 496 | + <Text style={{ color: colors.textSecondary, fontSize: 13 }}> |
|---|
| 497 | + Refresh |
|---|
| 498 | + </Text> |
|---|
| 499 | + </Pressable> |
|---|
| 500 | + <Pressable |
|---|
| 501 | + onPress={handleNewSession} |
|---|
| 502 | + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 503 | + style={({ pressed }) => ({ |
|---|
| 504 | + width: 30, |
|---|
| 505 | + height: 30, |
|---|
| 506 | + borderRadius: 15, |
|---|
| 507 | + alignItems: "center", |
|---|
| 508 | + justifyContent: "center", |
|---|
| 509 | + backgroundColor: pressed ? colors.accent + "CC" : colors.accent, |
|---|
| 510 | + })} |
|---|
| 511 | + > |
|---|
| 512 | + <Text style={{ color: "#FFF", fontSize: 20, fontWeight: "600", marginTop: -1 }}> |
|---|
| 513 | + + |
|---|
| 514 | + </Text> |
|---|
| 515 | + </Pressable> |
|---|
| 516 | + </View> |
|---|
| 517 | + </View> |
|---|
| 518 | + </View> |
|---|
| 519 | + |
|---|
| 520 | + {/* Session list */} |
|---|
| 521 | + {orderedSessions.length === 0 ? ( |
|---|
| 522 | + <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}> |
|---|
| 523 | + <Text style={{ color: colors.textMuted, fontSize: 14 }}> |
|---|
| 524 | + No sessions found |
|---|
| 525 | + </Text> |
|---|
| 526 | + </View> |
|---|
| 527 | + ) : ( |
|---|
| 528 | + <DraggableFlatList |
|---|
| 529 | + data={orderedSessions} |
|---|
| 530 | + keyExtractor={keyExtractor} |
|---|
| 531 | + renderItem={renderItem} |
|---|
| 532 | + onDragEnd={handleDragEnd} |
|---|
| 533 | + ItemSeparatorComponent={renderSeparator} |
|---|
| 534 | + contentContainerStyle={{ paddingVertical: 4 }} |
|---|
| 535 | + showsVerticalScrollIndicator={false} |
|---|
| 536 | + keyboardShouldPersistTaps="handled" |
|---|
| 537 | + /> |
|---|
| 538 | + )} |
|---|
| 539 | + |
|---|
| 540 | + {/* Footer */} |
|---|
| 541 | + <View |
|---|
| 542 | + style={{ |
|---|
| 543 | + paddingVertical: 12, |
|---|
| 544 | + paddingHorizontal: 20, |
|---|
| 545 | + borderTopWidth: 1, |
|---|
| 546 | + borderTopColor: colors.border, |
|---|
| 547 | + }} |
|---|
| 548 | + > |
|---|
| 549 | + <Text |
|---|
| 550 | + style={{ |
|---|
| 551 | + color: colors.textMuted, |
|---|
| 552 | + fontSize: 11, |
|---|
| 553 | + textAlign: "center", |
|---|
| 554 | + }} |
|---|
| 555 | + > |
|---|
| 556 | + Tap to switch — Long press to rename — Swipe to remove |
|---|
| 557 | + </Text> |
|---|
| 558 | + </View> |
|---|
| 559 | + </GestureHandlerRootView> |
|---|
| 560 | + </Animated.View> |
|---|
| 561 | + </View> |
|---|
| 562 | + </View> |
|---|
| 563 | + ); |
|---|
| 564 | +} |
|---|
| .. | .. |
|---|
| 1 | | -import React, { useCallback, useEffect, useState } from "react"; |
|---|
| 1 | +import React, { useCallback, useEffect, useRef, useState } from "react"; |
|---|
| 2 | 2 | import { |
|---|
| 3 | + Animated, |
|---|
| 4 | + Keyboard, |
|---|
| 5 | + LayoutAnimation, |
|---|
| 3 | 6 | Modal, |
|---|
| 7 | + Platform, |
|---|
| 4 | 8 | Pressable, |
|---|
| 5 | 9 | ScrollView, |
|---|
| 6 | 10 | Text, |
|---|
| 7 | 11 | TextInput, |
|---|
| 12 | + UIManager, |
|---|
| 8 | 13 | View, |
|---|
| 9 | 14 | } from "react-native"; |
|---|
| 15 | +import { |
|---|
| 16 | + GestureHandlerRootView, |
|---|
| 17 | + PanGestureHandler, |
|---|
| 18 | + PanGestureHandlerGestureEvent, |
|---|
| 19 | + State, |
|---|
| 20 | + Swipeable, |
|---|
| 21 | +} from "react-native-gesture-handler"; |
|---|
| 10 | 22 | import * as Haptics from "expo-haptics"; |
|---|
| 11 | 23 | import { WsSession } from "../types"; |
|---|
| 12 | 24 | import { useChat } from "../contexts/ChatContext"; |
|---|
| 25 | + |
|---|
| 26 | +if ( |
|---|
| 27 | + Platform.OS === "android" && |
|---|
| 28 | + UIManager.setLayoutAnimationEnabledExperimental |
|---|
| 29 | +) { |
|---|
| 30 | + UIManager.setLayoutAnimationEnabledExperimental(true); |
|---|
| 31 | +} |
|---|
| 13 | 32 | |
|---|
| 14 | 33 | interface SessionPickerProps { |
|---|
| 15 | 34 | visible: boolean; |
|---|
| 16 | 35 | onClose: () => void; |
|---|
| 17 | 36 | } |
|---|
| 18 | 37 | |
|---|
| 38 | +/* ── Swipeable row with delete action ── */ |
|---|
| 39 | + |
|---|
| 40 | +function SessionRow({ |
|---|
| 41 | + session, |
|---|
| 42 | + onSwitch, |
|---|
| 43 | + onLongPress, |
|---|
| 44 | + onDelete, |
|---|
| 45 | +}: { |
|---|
| 46 | + session: WsSession; |
|---|
| 47 | + onSwitch: () => void; |
|---|
| 48 | + onLongPress: () => void; |
|---|
| 49 | + onDelete: () => void; |
|---|
| 50 | +}) { |
|---|
| 51 | + const swipeRef = useRef<Swipeable>(null); |
|---|
| 52 | + |
|---|
| 53 | + const renderRightActions = ( |
|---|
| 54 | + _progress: Animated.AnimatedInterpolation<number>, |
|---|
| 55 | + dragX: Animated.AnimatedInterpolation<number>, |
|---|
| 56 | + ) => { |
|---|
| 57 | + const scale = dragX.interpolate({ |
|---|
| 58 | + inputRange: [-100, -50, 0], |
|---|
| 59 | + outputRange: [1, 0.8, 0], |
|---|
| 60 | + extrapolate: "clamp", |
|---|
| 61 | + }); |
|---|
| 62 | + |
|---|
| 63 | + return ( |
|---|
| 64 | + <Pressable |
|---|
| 65 | + onPress={() => { |
|---|
| 66 | + swipeRef.current?.close(); |
|---|
| 67 | + onDelete(); |
|---|
| 68 | + }} |
|---|
| 69 | + style={{ |
|---|
| 70 | + backgroundColor: "#FF3B30", |
|---|
| 71 | + justifyContent: "center", |
|---|
| 72 | + alignItems: "center", |
|---|
| 73 | + width: 80, |
|---|
| 74 | + borderRadius: 16, |
|---|
| 75 | + marginLeft: 8, |
|---|
| 76 | + }} |
|---|
| 77 | + > |
|---|
| 78 | + <Animated.Text |
|---|
| 79 | + style={{ |
|---|
| 80 | + color: "#FFF", |
|---|
| 81 | + fontSize: 14, |
|---|
| 82 | + fontWeight: "600", |
|---|
| 83 | + transform: [{ scale }], |
|---|
| 84 | + }} |
|---|
| 85 | + > |
|---|
| 86 | + Remove |
|---|
| 87 | + </Animated.Text> |
|---|
| 88 | + </Pressable> |
|---|
| 89 | + ); |
|---|
| 90 | + }; |
|---|
| 91 | + |
|---|
| 92 | + return ( |
|---|
| 93 | + <Swipeable |
|---|
| 94 | + ref={swipeRef} |
|---|
| 95 | + renderRightActions={renderRightActions} |
|---|
| 96 | + rightThreshold={60} |
|---|
| 97 | + friction={2} |
|---|
| 98 | + overshootRight={false} |
|---|
| 99 | + > |
|---|
| 100 | + <Pressable |
|---|
| 101 | + onPress={onSwitch} |
|---|
| 102 | + onLongPress={onLongPress} |
|---|
| 103 | + delayLongPress={400} |
|---|
| 104 | + style={({ pressed }) => ({ |
|---|
| 105 | + width: "100%", |
|---|
| 106 | + backgroundColor: pressed ? "#252538" : "#1E1E2E", |
|---|
| 107 | + borderRadius: 16, |
|---|
| 108 | + padding: 14, |
|---|
| 109 | + flexDirection: "row", |
|---|
| 110 | + alignItems: "center", |
|---|
| 111 | + borderWidth: session.isActive ? 2 : 1, |
|---|
| 112 | + borderColor: session.isActive ? "#4A9EFF" : "#2E2E45", |
|---|
| 113 | + })} |
|---|
| 114 | + > |
|---|
| 115 | + {/* Number badge */} |
|---|
| 116 | + <View |
|---|
| 117 | + style={{ |
|---|
| 118 | + width: 32, |
|---|
| 119 | + height: 32, |
|---|
| 120 | + borderRadius: 16, |
|---|
| 121 | + backgroundColor: session.isActive ? "#4A9EFF" : "#252538", |
|---|
| 122 | + alignItems: "center", |
|---|
| 123 | + justifyContent: "center", |
|---|
| 124 | + marginRight: 12, |
|---|
| 125 | + }} |
|---|
| 126 | + > |
|---|
| 127 | + <Text |
|---|
| 128 | + style={{ |
|---|
| 129 | + color: session.isActive ? "#FFF" : "#9898B0", |
|---|
| 130 | + fontSize: 14, |
|---|
| 131 | + fontWeight: "700", |
|---|
| 132 | + }} |
|---|
| 133 | + > |
|---|
| 134 | + {session.index} |
|---|
| 135 | + </Text> |
|---|
| 136 | + </View> |
|---|
| 137 | + |
|---|
| 138 | + {/* Session info */} |
|---|
| 139 | + <View style={{ flex: 1 }}> |
|---|
| 140 | + <Text |
|---|
| 141 | + style={{ |
|---|
| 142 | + color: "#E8E8F0", |
|---|
| 143 | + fontSize: 16, |
|---|
| 144 | + fontWeight: "600", |
|---|
| 145 | + }} |
|---|
| 146 | + numberOfLines={1} |
|---|
| 147 | + > |
|---|
| 148 | + {session.name} |
|---|
| 149 | + </Text> |
|---|
| 150 | + <Text |
|---|
| 151 | + style={{ |
|---|
| 152 | + color: "#5A5A78", |
|---|
| 153 | + fontSize: 11, |
|---|
| 154 | + marginTop: 1, |
|---|
| 155 | + }} |
|---|
| 156 | + > |
|---|
| 157 | + {session.kind === "api" |
|---|
| 158 | + ? "Headless" |
|---|
| 159 | + : session.kind === "visual" |
|---|
| 160 | + ? "Visual" |
|---|
| 161 | + : session.type === "terminal" |
|---|
| 162 | + ? "Terminal" |
|---|
| 163 | + : "Claude"} |
|---|
| 164 | + {session.isActive ? " — active" : ""} |
|---|
| 165 | + </Text> |
|---|
| 166 | + </View> |
|---|
| 167 | + |
|---|
| 168 | + {/* Active indicator */} |
|---|
| 169 | + {session.isActive && ( |
|---|
| 170 | + <View |
|---|
| 171 | + style={{ |
|---|
| 172 | + width: 8, |
|---|
| 173 | + height: 8, |
|---|
| 174 | + borderRadius: 4, |
|---|
| 175 | + backgroundColor: "#2ED573", |
|---|
| 176 | + }} |
|---|
| 177 | + /> |
|---|
| 178 | + )} |
|---|
| 179 | + </Pressable> |
|---|
| 180 | + </Swipeable> |
|---|
| 181 | + ); |
|---|
| 182 | +} |
|---|
| 183 | + |
|---|
| 184 | +/* ── Inline rename editor ── */ |
|---|
| 185 | + |
|---|
| 186 | +function RenameEditor({ |
|---|
| 187 | + name, |
|---|
| 188 | + onConfirm, |
|---|
| 189 | + onCancel, |
|---|
| 190 | +}: { |
|---|
| 191 | + name: string; |
|---|
| 192 | + onConfirm: (newName: string) => void; |
|---|
| 193 | + onCancel: () => void; |
|---|
| 194 | +}) { |
|---|
| 195 | + const [editName, setEditName] = useState(name); |
|---|
| 196 | + |
|---|
| 197 | + return ( |
|---|
| 198 | + <View |
|---|
| 199 | + style={{ |
|---|
| 200 | + backgroundColor: "#1E1E2E", |
|---|
| 201 | + borderRadius: 16, |
|---|
| 202 | + padding: 14, |
|---|
| 203 | + borderWidth: 2, |
|---|
| 204 | + borderColor: "#4A9EFF", |
|---|
| 205 | + }} |
|---|
| 206 | + > |
|---|
| 207 | + <TextInput |
|---|
| 208 | + value={editName} |
|---|
| 209 | + onChangeText={setEditName} |
|---|
| 210 | + autoFocus |
|---|
| 211 | + onSubmitEditing={() => onConfirm(editName.trim())} |
|---|
| 212 | + onBlur={onCancel} |
|---|
| 213 | + returnKeyType="done" |
|---|
| 214 | + style={{ |
|---|
| 215 | + color: "#E8E8F0", |
|---|
| 216 | + fontSize: 16, |
|---|
| 217 | + fontWeight: "600", |
|---|
| 218 | + padding: 0, |
|---|
| 219 | + marginBottom: 10, |
|---|
| 220 | + }} |
|---|
| 221 | + placeholderTextColor="#5A5A78" |
|---|
| 222 | + placeholder="Session name..." |
|---|
| 223 | + /> |
|---|
| 224 | + <View style={{ flexDirection: "row", gap: 8 }}> |
|---|
| 225 | + <Pressable |
|---|
| 226 | + onPress={() => onConfirm(editName.trim())} |
|---|
| 227 | + style={{ |
|---|
| 228 | + flex: 1, |
|---|
| 229 | + backgroundColor: "#4A9EFF", |
|---|
| 230 | + borderRadius: 10, |
|---|
| 231 | + paddingVertical: 8, |
|---|
| 232 | + alignItems: "center", |
|---|
| 233 | + }} |
|---|
| 234 | + > |
|---|
| 235 | + <Text style={{ color: "#FFF", fontSize: 14, fontWeight: "600" }}> |
|---|
| 236 | + Save |
|---|
| 237 | + </Text> |
|---|
| 238 | + </Pressable> |
|---|
| 239 | + <Pressable |
|---|
| 240 | + onPress={onCancel} |
|---|
| 241 | + style={{ |
|---|
| 242 | + flex: 1, |
|---|
| 243 | + backgroundColor: "#252538", |
|---|
| 244 | + borderRadius: 10, |
|---|
| 245 | + paddingVertical: 8, |
|---|
| 246 | + alignItems: "center", |
|---|
| 247 | + }} |
|---|
| 248 | + > |
|---|
| 249 | + <Text style={{ color: "#9898B0", fontSize: 14 }}>Cancel</Text> |
|---|
| 250 | + </Pressable> |
|---|
| 251 | + </View> |
|---|
| 252 | + </View> |
|---|
| 253 | + ); |
|---|
| 254 | +} |
|---|
| 255 | + |
|---|
| 256 | +/* ── Main SessionPicker ── */ |
|---|
| 257 | + |
|---|
| 19 | 258 | export function SessionPicker({ visible, onClose }: SessionPickerProps) { |
|---|
| 20 | | - const { sessions, requestSessions, switchSession, renameSession } = useChat(); |
|---|
| 259 | + const { |
|---|
| 260 | + sessions, |
|---|
| 261 | + requestSessions, |
|---|
| 262 | + switchSession, |
|---|
| 263 | + renameSession, |
|---|
| 264 | + removeSession, |
|---|
| 265 | + } = useChat(); |
|---|
| 21 | 266 | const [editingId, setEditingId] = useState<string | null>(null); |
|---|
| 22 | | - const [editName, setEditName] = useState(""); |
|---|
| 267 | + const [keyboardHeight, setKeyboardHeight] = useState(0); |
|---|
| 268 | + |
|---|
| 269 | + // Sort: active first, then by index |
|---|
| 270 | + const sortedSessions = [...sessions].sort((a, b) => { |
|---|
| 271 | + if (a.isActive && !b.isActive) return -1; |
|---|
| 272 | + if (!a.isActive && b.isActive) return 1; |
|---|
| 273 | + return a.index - b.index; |
|---|
| 274 | + }); |
|---|
| 23 | 275 | |
|---|
| 24 | 276 | useEffect(() => { |
|---|
| 25 | | - if (visible) { |
|---|
| 277 | + const showSub = Keyboard.addListener("keyboardWillShow", (e) => |
|---|
| 278 | + setKeyboardHeight(e.endCoordinates.height), |
|---|
| 279 | + ); |
|---|
| 280 | + const hideSub = Keyboard.addListener("keyboardWillHide", () => |
|---|
| 281 | + setKeyboardHeight(0), |
|---|
| 282 | + ); |
|---|
| 283 | + return () => { |
|---|
| 284 | + showSub.remove(); |
|---|
| 285 | + hideSub.remove(); |
|---|
| 286 | + }; |
|---|
| 287 | + }, []); |
|---|
| 288 | + |
|---|
| 289 | + useEffect(() => { |
|---|
| 290 | + if (!visible) { |
|---|
| 291 | + setEditingId(null); |
|---|
| 292 | + } else { |
|---|
| 26 | 293 | requestSessions(); |
|---|
| 27 | 294 | } |
|---|
| 28 | 295 | }, [visible, requestSessions]); |
|---|
| 296 | + |
|---|
| 297 | + const handleClose = useCallback(() => { |
|---|
| 298 | + setEditingId(null); |
|---|
| 299 | + Keyboard.dismiss(); |
|---|
| 300 | + onClose(); |
|---|
| 301 | + }, [onClose]); |
|---|
| 29 | 302 | |
|---|
| 30 | 303 | const handleSwitch = useCallback( |
|---|
| 31 | 304 | (session: WsSession) => { |
|---|
| 32 | 305 | Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); |
|---|
| 33 | 306 | switchSession(session.id); |
|---|
| 34 | | - onClose(); |
|---|
| 307 | + handleClose(); |
|---|
| 35 | 308 | }, |
|---|
| 36 | | - [switchSession, onClose] |
|---|
| 309 | + [switchSession, handleClose], |
|---|
| 37 | 310 | ); |
|---|
| 38 | 311 | |
|---|
| 39 | 312 | const handleStartRename = useCallback((session: WsSession) => { |
|---|
| 313 | + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); |
|---|
| 40 | 314 | setEditingId(session.id); |
|---|
| 41 | | - setEditName(session.name); |
|---|
| 42 | 315 | }, []); |
|---|
| 43 | 316 | |
|---|
| 44 | | - const handleConfirmRename = useCallback(() => { |
|---|
| 45 | | - if (editingId && editName.trim()) { |
|---|
| 46 | | - renameSession(editingId, editName.trim()); |
|---|
| 47 | | - } |
|---|
| 48 | | - setEditingId(null); |
|---|
| 49 | | - setEditName(""); |
|---|
| 50 | | - }, [editingId, editName, renameSession]); |
|---|
| 317 | + const handleConfirmRename = useCallback( |
|---|
| 318 | + (sessionId: string, newName: string) => { |
|---|
| 319 | + if (newName) { |
|---|
| 320 | + renameSession(sessionId, newName); |
|---|
| 321 | + } |
|---|
| 322 | + setEditingId(null); |
|---|
| 323 | + }, |
|---|
| 324 | + [renameSession], |
|---|
| 325 | + ); |
|---|
| 326 | + |
|---|
| 327 | + const handleRemove = useCallback( |
|---|
| 328 | + (session: WsSession) => { |
|---|
| 329 | + Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning); |
|---|
| 330 | + LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); |
|---|
| 331 | + removeSession(session.id); |
|---|
| 332 | + }, |
|---|
| 333 | + [removeSession], |
|---|
| 334 | + ); |
|---|
| 51 | 335 | |
|---|
| 52 | 336 | return ( |
|---|
| 53 | 337 | <Modal |
|---|
| 54 | 338 | visible={visible} |
|---|
| 55 | 339 | animationType="slide" |
|---|
| 56 | 340 | transparent |
|---|
| 57 | | - onRequestClose={onClose} |
|---|
| 341 | + onRequestClose={handleClose} |
|---|
| 58 | 342 | > |
|---|
| 59 | | - <View |
|---|
| 60 | | - style={{ |
|---|
| 61 | | - flex: 1, |
|---|
| 62 | | - backgroundColor: "rgba(0,0,0,0.6)", |
|---|
| 63 | | - justifyContent: "flex-end", |
|---|
| 64 | | - }} |
|---|
| 65 | | - > |
|---|
| 66 | | - <Pressable |
|---|
| 67 | | - style={{ flex: 1 }} |
|---|
| 68 | | - onPress={onClose} |
|---|
| 69 | | - /> |
|---|
| 343 | + <GestureHandlerRootView style={{ flex: 1 }}> |
|---|
| 70 | 344 | <View |
|---|
| 71 | 345 | style={{ |
|---|
| 72 | | - backgroundColor: "#14141F", |
|---|
| 73 | | - borderTopLeftRadius: 24, |
|---|
| 74 | | - borderTopRightRadius: 24, |
|---|
| 75 | | - maxHeight: "70%", |
|---|
| 76 | | - paddingBottom: 40, |
|---|
| 346 | + flex: 1, |
|---|
| 347 | + backgroundColor: "rgba(0,0,0,0.6)", |
|---|
| 348 | + justifyContent: "flex-end", |
|---|
| 77 | 349 | }} |
|---|
| 78 | 350 | > |
|---|
| 79 | | - {/* Handle bar */} |
|---|
| 80 | | - <View style={{ alignItems: "center", paddingTop: 12, paddingBottom: 8 }}> |
|---|
| 81 | | - <View |
|---|
| 82 | | - style={{ |
|---|
| 83 | | - width: 40, |
|---|
| 84 | | - height: 4, |
|---|
| 85 | | - borderRadius: 2, |
|---|
| 86 | | - backgroundColor: "#2E2E45", |
|---|
| 87 | | - }} |
|---|
| 88 | | - /> |
|---|
| 89 | | - </View> |
|---|
| 90 | | - |
|---|
| 91 | | - {/* Header */} |
|---|
| 351 | + <Pressable style={{ flex: 1 }} onPress={handleClose} /> |
|---|
| 92 | 352 | <View |
|---|
| 93 | 353 | style={{ |
|---|
| 94 | | - flexDirection: "row", |
|---|
| 95 | | - alignItems: "center", |
|---|
| 96 | | - justifyContent: "space-between", |
|---|
| 97 | | - paddingHorizontal: 20, |
|---|
| 98 | | - paddingBottom: 16, |
|---|
| 354 | + backgroundColor: "#14141F", |
|---|
| 355 | + borderTopLeftRadius: 24, |
|---|
| 356 | + borderTopRightRadius: 24, |
|---|
| 357 | + maxHeight: "70%", |
|---|
| 358 | + paddingBottom: Math.max(40, keyboardHeight), |
|---|
| 99 | 359 | }} |
|---|
| 100 | 360 | > |
|---|
| 101 | | - <Text |
|---|
| 361 | + {/* Handle bar */} |
|---|
| 362 | + <View |
|---|
| 363 | + style={{ alignItems: "center", paddingTop: 12, paddingBottom: 8 }} |
|---|
| 364 | + > |
|---|
| 365 | + <View |
|---|
| 366 | + style={{ |
|---|
| 367 | + width: 40, |
|---|
| 368 | + height: 4, |
|---|
| 369 | + borderRadius: 2, |
|---|
| 370 | + backgroundColor: "#2E2E45", |
|---|
| 371 | + }} |
|---|
| 372 | + /> |
|---|
| 373 | + </View> |
|---|
| 374 | + |
|---|
| 375 | + {/* Header */} |
|---|
| 376 | + <View |
|---|
| 102 | 377 | style={{ |
|---|
| 103 | | - color: "#E8E8F0", |
|---|
| 104 | | - fontSize: 20, |
|---|
| 105 | | - fontWeight: "700", |
|---|
| 378 | + flexDirection: "row", |
|---|
| 379 | + alignItems: "center", |
|---|
| 380 | + justifyContent: "space-between", |
|---|
| 381 | + paddingHorizontal: 20, |
|---|
| 382 | + paddingBottom: 12, |
|---|
| 106 | 383 | }} |
|---|
| 107 | 384 | > |
|---|
| 108 | | - Sessions |
|---|
| 109 | | - </Text> |
|---|
| 110 | | - <Pressable |
|---|
| 111 | | - onPress={() => requestSessions()} |
|---|
| 112 | | - hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 113 | | - style={{ |
|---|
| 114 | | - paddingHorizontal: 12, |
|---|
| 115 | | - paddingVertical: 6, |
|---|
| 116 | | - borderRadius: 12, |
|---|
| 117 | | - backgroundColor: "#1E1E2E", |
|---|
| 118 | | - }} |
|---|
| 385 | + <Text |
|---|
| 386 | + style={{ |
|---|
| 387 | + color: "#E8E8F0", |
|---|
| 388 | + fontSize: 20, |
|---|
| 389 | + fontWeight: "700", |
|---|
| 390 | + }} |
|---|
| 391 | + > |
|---|
| 392 | + Sessions |
|---|
| 393 | + </Text> |
|---|
| 394 | + <Pressable |
|---|
| 395 | + onPress={() => requestSessions()} |
|---|
| 396 | + hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 397 | + style={({ pressed }) => ({ |
|---|
| 398 | + paddingHorizontal: 12, |
|---|
| 399 | + paddingVertical: 6, |
|---|
| 400 | + borderRadius: 12, |
|---|
| 401 | + backgroundColor: pressed ? "#252538" : "#1E1E2E", |
|---|
| 402 | + })} |
|---|
| 403 | + > |
|---|
| 404 | + <Text style={{ color: "#9898B0", fontSize: 13 }}>Refresh</Text> |
|---|
| 405 | + </Pressable> |
|---|
| 406 | + </View> |
|---|
| 407 | + |
|---|
| 408 | + {/* Session list */} |
|---|
| 409 | + <ScrollView |
|---|
| 410 | + style={{ paddingHorizontal: 16 }} |
|---|
| 411 | + showsVerticalScrollIndicator={false} |
|---|
| 412 | + keyboardShouldPersistTaps="handled" |
|---|
| 119 | 413 | > |
|---|
| 120 | | - <Text style={{ color: "#9898B0", fontSize: 13 }}>Refresh</Text> |
|---|
| 121 | | - </Pressable> |
|---|
| 122 | | - </View> |
|---|
| 123 | | - |
|---|
| 124 | | - {/* Session list */} |
|---|
| 125 | | - <ScrollView |
|---|
| 126 | | - style={{ paddingHorizontal: 16 }} |
|---|
| 127 | | - showsVerticalScrollIndicator={false} |
|---|
| 128 | | - > |
|---|
| 129 | | - {sessions.length === 0 ? ( |
|---|
| 130 | | - <View style={{ alignItems: "center", paddingVertical: 32 }}> |
|---|
| 131 | | - <Text style={{ color: "#5A5A78", fontSize: 15 }}> |
|---|
| 132 | | - No sessions found |
|---|
| 133 | | - </Text> |
|---|
| 134 | | - </View> |
|---|
| 135 | | - ) : ( |
|---|
| 136 | | - sessions.map((session) => ( |
|---|
| 137 | | - <View key={session.id} style={{ marginBottom: 8 }}> |
|---|
| 138 | | - {editingId === session.id ? ( |
|---|
| 139 | | - /* Rename mode */ |
|---|
| 140 | | - <View |
|---|
| 141 | | - style={{ |
|---|
| 142 | | - backgroundColor: "#1E1E2E", |
|---|
| 143 | | - borderRadius: 16, |
|---|
| 144 | | - padding: 16, |
|---|
| 145 | | - borderWidth: 2, |
|---|
| 146 | | - borderColor: "#4A9EFF", |
|---|
| 147 | | - }} |
|---|
| 148 | | - > |
|---|
| 149 | | - <TextInput |
|---|
| 150 | | - value={editName} |
|---|
| 151 | | - onChangeText={setEditName} |
|---|
| 152 | | - autoFocus |
|---|
| 153 | | - onSubmitEditing={handleConfirmRename} |
|---|
| 154 | | - returnKeyType="done" |
|---|
| 155 | | - style={{ |
|---|
| 156 | | - color: "#E8E8F0", |
|---|
| 157 | | - fontSize: 17, |
|---|
| 158 | | - fontWeight: "600", |
|---|
| 159 | | - padding: 0, |
|---|
| 160 | | - marginBottom: 12, |
|---|
| 161 | | - }} |
|---|
| 162 | | - placeholderTextColor="#5A5A78" |
|---|
| 163 | | - placeholder="Session name..." |
|---|
| 164 | | - /> |
|---|
| 165 | | - <View style={{ flexDirection: "row", gap: 8 }}> |
|---|
| 166 | | - <Pressable |
|---|
| 167 | | - onPress={handleConfirmRename} |
|---|
| 168 | | - style={{ |
|---|
| 169 | | - flex: 1, |
|---|
| 170 | | - backgroundColor: "#4A9EFF", |
|---|
| 171 | | - borderRadius: 10, |
|---|
| 172 | | - paddingVertical: 10, |
|---|
| 173 | | - alignItems: "center", |
|---|
| 174 | | - }} |
|---|
| 175 | | - > |
|---|
| 176 | | - <Text style={{ color: "#FFF", fontSize: 15, fontWeight: "600" }}> |
|---|
| 177 | | - Save |
|---|
| 178 | | - </Text> |
|---|
| 179 | | - </Pressable> |
|---|
| 180 | | - <Pressable |
|---|
| 181 | | - onPress={() => setEditingId(null)} |
|---|
| 182 | | - style={{ |
|---|
| 183 | | - flex: 1, |
|---|
| 184 | | - backgroundColor: "#252538", |
|---|
| 185 | | - borderRadius: 10, |
|---|
| 186 | | - paddingVertical: 10, |
|---|
| 187 | | - alignItems: "center", |
|---|
| 188 | | - }} |
|---|
| 189 | | - > |
|---|
| 190 | | - <Text style={{ color: "#9898B0", fontSize: 15 }}>Cancel</Text> |
|---|
| 191 | | - </Pressable> |
|---|
| 192 | | - </View> |
|---|
| 193 | | - </View> |
|---|
| 194 | | - ) : ( |
|---|
| 195 | | - /* Normal session row */ |
|---|
| 196 | | - <Pressable |
|---|
| 197 | | - onPress={() => handleSwitch(session)} |
|---|
| 198 | | - onLongPress={() => handleStartRename(session)} |
|---|
| 199 | | - style={({ pressed }) => ({ |
|---|
| 200 | | - backgroundColor: pressed ? "#252538" : "#1E1E2E", |
|---|
| 201 | | - borderRadius: 16, |
|---|
| 202 | | - padding: 16, |
|---|
| 203 | | - flexDirection: "row", |
|---|
| 204 | | - alignItems: "center", |
|---|
| 205 | | - borderWidth: session.isActive ? 2 : 1, |
|---|
| 206 | | - borderColor: session.isActive ? "#4A9EFF" : "#2E2E45", |
|---|
| 207 | | - })} |
|---|
| 208 | | - > |
|---|
| 209 | | - {/* Number badge */} |
|---|
| 210 | | - <View |
|---|
| 211 | | - style={{ |
|---|
| 212 | | - width: 36, |
|---|
| 213 | | - height: 36, |
|---|
| 214 | | - borderRadius: 18, |
|---|
| 215 | | - backgroundColor: session.isActive ? "#4A9EFF" : "#252538", |
|---|
| 216 | | - alignItems: "center", |
|---|
| 217 | | - justifyContent: "center", |
|---|
| 218 | | - marginRight: 14, |
|---|
| 219 | | - }} |
|---|
| 220 | | - > |
|---|
| 221 | | - <Text |
|---|
| 222 | | - style={{ |
|---|
| 223 | | - color: session.isActive ? "#FFF" : "#9898B0", |
|---|
| 224 | | - fontSize: 16, |
|---|
| 225 | | - fontWeight: "700", |
|---|
| 226 | | - }} |
|---|
| 227 | | - > |
|---|
| 228 | | - {session.index} |
|---|
| 229 | | - </Text> |
|---|
| 230 | | - </View> |
|---|
| 231 | | - |
|---|
| 232 | | - {/* Session info */} |
|---|
| 233 | | - <View style={{ flex: 1 }}> |
|---|
| 234 | | - <Text |
|---|
| 235 | | - style={{ |
|---|
| 236 | | - color: "#E8E8F0", |
|---|
| 237 | | - fontSize: 17, |
|---|
| 238 | | - fontWeight: "600", |
|---|
| 239 | | - }} |
|---|
| 240 | | - numberOfLines={1} |
|---|
| 241 | | - > |
|---|
| 242 | | - {session.name} |
|---|
| 243 | | - </Text> |
|---|
| 244 | | - <Text |
|---|
| 245 | | - style={{ |
|---|
| 246 | | - color: "#5A5A78", |
|---|
| 247 | | - fontSize: 12, |
|---|
| 248 | | - marginTop: 2, |
|---|
| 249 | | - }} |
|---|
| 250 | | - > |
|---|
| 251 | | - {session.kind === "api" ? "Headless" : session.kind === "visual" ? "Visual" : session.type === "terminal" ? "Terminal" : "Claude"} |
|---|
| 252 | | - {session.isActive ? " — active" : ""} |
|---|
| 253 | | - </Text> |
|---|
| 254 | | - </View> |
|---|
| 255 | | - |
|---|
| 256 | | - {/* Active indicator */} |
|---|
| 257 | | - {session.isActive && ( |
|---|
| 258 | | - <View |
|---|
| 259 | | - style={{ |
|---|
| 260 | | - width: 10, |
|---|
| 261 | | - height: 10, |
|---|
| 262 | | - borderRadius: 5, |
|---|
| 263 | | - backgroundColor: "#2ED573", |
|---|
| 264 | | - }} |
|---|
| 265 | | - /> |
|---|
| 266 | | - )} |
|---|
| 267 | | - </Pressable> |
|---|
| 268 | | - )} |
|---|
| 414 | + {sortedSessions.length === 0 ? ( |
|---|
| 415 | + <View style={{ alignItems: "center", paddingVertical: 32 }}> |
|---|
| 416 | + <Text style={{ color: "#5A5A78", fontSize: 15 }}> |
|---|
| 417 | + No sessions found |
|---|
| 418 | + </Text> |
|---|
| 269 | 419 | </View> |
|---|
| 270 | | - )) |
|---|
| 271 | | - )} |
|---|
| 420 | + ) : ( |
|---|
| 421 | + sortedSessions.map((session) => ( |
|---|
| 422 | + <View key={session.id} style={{ marginBottom: 6 }}> |
|---|
| 423 | + {editingId === session.id ? ( |
|---|
| 424 | + <RenameEditor |
|---|
| 425 | + name={session.name} |
|---|
| 426 | + onConfirm={(name) => |
|---|
| 427 | + handleConfirmRename(session.id, name) |
|---|
| 428 | + } |
|---|
| 429 | + onCancel={() => setEditingId(null)} |
|---|
| 430 | + /> |
|---|
| 431 | + ) : ( |
|---|
| 432 | + <SessionRow |
|---|
| 433 | + session={session} |
|---|
| 434 | + onSwitch={() => handleSwitch(session)} |
|---|
| 435 | + onLongPress={() => handleStartRename(session)} |
|---|
| 436 | + onDelete={() => handleRemove(session)} |
|---|
| 437 | + /> |
|---|
| 438 | + )} |
|---|
| 439 | + </View> |
|---|
| 440 | + )) |
|---|
| 441 | + )} |
|---|
| 272 | 442 | |
|---|
| 273 | | - {/* Hint */} |
|---|
| 274 | | - <Text |
|---|
| 275 | | - style={{ |
|---|
| 276 | | - color: "#5A5A78", |
|---|
| 277 | | - fontSize: 12, |
|---|
| 278 | | - textAlign: "center", |
|---|
| 279 | | - paddingVertical: 12, |
|---|
| 280 | | - }} |
|---|
| 281 | | - > |
|---|
| 282 | | - Tap to switch — Long press to rename |
|---|
| 283 | | - </Text> |
|---|
| 284 | | - </ScrollView> |
|---|
| 443 | + <Text |
|---|
| 444 | + style={{ |
|---|
| 445 | + color: "#5A5A78", |
|---|
| 446 | + fontSize: 11, |
|---|
| 447 | + textAlign: "center", |
|---|
| 448 | + paddingVertical: 10, |
|---|
| 449 | + }} |
|---|
| 450 | + > |
|---|
| 451 | + Tap to switch — Long press to rename — Swipe left to remove |
|---|
| 452 | + </Text> |
|---|
| 453 | + </ScrollView> |
|---|
| 454 | + </View> |
|---|
| 285 | 455 | </View> |
|---|
| 286 | | - </View> |
|---|
| 456 | + </GestureHandlerRootView> |
|---|
| 287 | 457 | </Modal> |
|---|
| 288 | 458 | ); |
|---|
| 289 | 459 | } |
|---|
| .. | .. |
|---|
| 1 | 1 | import React, { useState } from "react"; |
|---|
| 2 | | -import { Pressable, Text, View, useWindowDimensions } from "react-native"; |
|---|
| 2 | +import { Pressable, Text, View } from "react-native"; |
|---|
| 3 | 3 | import * as Haptics from "expo-haptics"; |
|---|
| 4 | +import { useTheme } from "../../contexts/ThemeContext"; |
|---|
| 4 | 5 | |
|---|
| 5 | 6 | interface CommandBarProps { |
|---|
| 6 | | - onSessions: () => void; |
|---|
| 7 | 7 | onScreenshot: () => void; |
|---|
| 8 | | - onHelp: () => void; |
|---|
| 8 | + onNavigate: () => void; |
|---|
| 9 | + onPhoto: () => void; |
|---|
| 10 | + onClear: () => void; |
|---|
| 9 | 11 | } |
|---|
| 10 | 12 | |
|---|
| 11 | | -export function CommandBar({ onSessions, onScreenshot, onHelp }: CommandBarProps) { |
|---|
| 13 | +export function CommandBar({ onScreenshot, onNavigate, onPhoto, onClear }: CommandBarProps) { |
|---|
| 14 | + const { colors } = useTheme(); |
|---|
| 12 | 15 | return ( |
|---|
| 13 | 16 | <View |
|---|
| 14 | 17 | style={{ |
|---|
| .. | .. |
|---|
| 18 | 21 | gap: 8, |
|---|
| 19 | 22 | }} |
|---|
| 20 | 23 | > |
|---|
| 21 | | - <CmdBtn icon="📋" label="Sessions" bg="#1A2744" border="#2E4A7A" onPress={onSessions} /> |
|---|
| 22 | | - <CmdBtn icon="📸" label="Screen" bg="#1A3A2A" border="#2E6A4A" onPress={onScreenshot} /> |
|---|
| 23 | | - <CmdBtn icon="❓" label="Help" bg="#3A1A2A" border="#6A2E4A" onPress={onHelp} /> |
|---|
| 24 | + <CmdBtn icon="📸" label="Screen" onPress={onScreenshot} colors={colors} /> |
|---|
| 25 | + <CmdBtn icon="🧭" label="Navigate" onPress={onNavigate} colors={colors} /> |
|---|
| 26 | + <CmdBtn icon="📎" label="Photo" onPress={onPhoto} colors={colors} /> |
|---|
| 27 | + <CmdBtn icon="🗑" label="Clear" onPress={onClear} colors={colors} /> |
|---|
| 24 | 28 | </View> |
|---|
| 25 | 29 | ); |
|---|
| 26 | 30 | } |
|---|
| 27 | 31 | |
|---|
| 28 | 32 | interface TextModeCommandBarProps { |
|---|
| 29 | | - onSessions: () => void; |
|---|
| 30 | 33 | onScreenshot: () => void; |
|---|
| 31 | 34 | onNavigate: () => void; |
|---|
| 35 | + onPhoto: () => void; |
|---|
| 36 | + onHelp: () => void; |
|---|
| 32 | 37 | onClear: () => void; |
|---|
| 33 | 38 | } |
|---|
| 34 | 39 | |
|---|
| 35 | 40 | export function TextModeCommandBar({ |
|---|
| 36 | | - onSessions, |
|---|
| 37 | 41 | onScreenshot, |
|---|
| 38 | 42 | onNavigate, |
|---|
| 43 | + onPhoto, |
|---|
| 44 | + onHelp, |
|---|
| 39 | 45 | onClear, |
|---|
| 40 | 46 | }: TextModeCommandBarProps) { |
|---|
| 47 | + const { colors } = useTheme(); |
|---|
| 41 | 48 | return ( |
|---|
| 42 | 49 | <View |
|---|
| 43 | 50 | style={{ |
|---|
| .. | .. |
|---|
| 47 | 54 | gap: 8, |
|---|
| 48 | 55 | }} |
|---|
| 49 | 56 | > |
|---|
| 50 | | - <CmdBtn icon="📋" label="Sessions" bg="#1A2744" border="#2E4A7A" onPress={onSessions} /> |
|---|
| 51 | | - <CmdBtn icon="📸" label="Screen" bg="#1A3A2A" border="#2E6A4A" onPress={onScreenshot} /> |
|---|
| 52 | | - <CmdBtn icon="🧭" label="Navigate" bg="#2A2A1A" border="#5A5A2E" onPress={onNavigate} /> |
|---|
| 53 | | - <CmdBtn icon="🗑" label="Clear" bg="#3A1A1A" border="#6A2E2E" onPress={onClear} /> |
|---|
| 57 | + <CmdBtn icon="📸" label="Screen" onPress={onScreenshot} colors={colors} /> |
|---|
| 58 | + <CmdBtn icon="🧭" label="Navigate" onPress={onNavigate} colors={colors} /> |
|---|
| 59 | + <CmdBtn icon="📎" label="Photo" onPress={onPhoto} colors={colors} /> |
|---|
| 60 | + <CmdBtn icon="❓" label="Help" onPress={onHelp} colors={colors} /> |
|---|
| 61 | + <CmdBtn icon="🗑" label="Clear" onPress={onClear} colors={colors} /> |
|---|
| 54 | 62 | </View> |
|---|
| 55 | 63 | ); |
|---|
| 56 | 64 | } |
|---|
| .. | .. |
|---|
| 58 | 66 | function CmdBtn({ |
|---|
| 59 | 67 | icon, |
|---|
| 60 | 68 | label, |
|---|
| 61 | | - bg, |
|---|
| 62 | | - border, |
|---|
| 63 | 69 | onPress, |
|---|
| 70 | + colors, |
|---|
| 64 | 71 | }: { |
|---|
| 65 | 72 | icon: string; |
|---|
| 66 | 73 | label: string; |
|---|
| 67 | | - bg: string; |
|---|
| 68 | | - border: string; |
|---|
| 69 | 74 | onPress: () => void; |
|---|
| 75 | + colors: ReturnType<typeof useTheme>["colors"]; |
|---|
| 70 | 76 | }) { |
|---|
| 71 | 77 | const [pressed, setPressed] = useState(false); |
|---|
| 72 | | - const { width } = useWindowDimensions(); |
|---|
| 73 | 78 | |
|---|
| 74 | 79 | return ( |
|---|
| 75 | 80 | <View style={{ flex: 1 }}> |
|---|
| .. | .. |
|---|
| 87 | 92 | borderRadius: 16, |
|---|
| 88 | 93 | alignItems: "center", |
|---|
| 89 | 94 | justifyContent: "center", |
|---|
| 90 | | - backgroundColor: pressed ? "#4A9EFF" : bg, |
|---|
| 95 | + backgroundColor: pressed ? colors.accent : colors.bgTertiary, |
|---|
| 91 | 96 | borderWidth: 1.5, |
|---|
| 92 | | - borderColor: pressed ? "#4A9EFF" : border, |
|---|
| 97 | + borderColor: pressed ? colors.accent : colors.border, |
|---|
| 93 | 98 | }} |
|---|
| 94 | 99 | > |
|---|
| 95 | 100 | <Text style={{ fontSize: 26, marginBottom: 2 }}>{icon}</Text> |
|---|
| 96 | | - <Text style={{ color: "#C8C8E0", fontSize: 13, fontWeight: "700" }}> |
|---|
| 101 | + <Text style={{ color: colors.textSecondary, fontSize: 13, fontWeight: "700" }}> |
|---|
| 97 | 102 | {label} |
|---|
| 98 | 103 | </Text> |
|---|
| 99 | 104 | </View> |
|---|
| .. | .. |
|---|
| 1 | +import React, { useEffect, useRef, useState } from "react"; |
|---|
| 2 | +import { |
|---|
| 3 | + Dimensions, |
|---|
| 4 | + Image, |
|---|
| 5 | + KeyboardAvoidingView, |
|---|
| 6 | + Modal, |
|---|
| 7 | + Platform, |
|---|
| 8 | + Pressable, |
|---|
| 9 | + Text, |
|---|
| 10 | + TextInput, |
|---|
| 11 | + View, |
|---|
| 12 | +} from "react-native"; |
|---|
| 13 | +import { useTheme } from "../../contexts/ThemeContext"; |
|---|
| 14 | + |
|---|
| 15 | +interface ImageCaptionModalProps { |
|---|
| 16 | + visible: boolean; |
|---|
| 17 | + imageUri: string; |
|---|
| 18 | + onSend: (caption: string) => void; |
|---|
| 19 | + onCancel: () => void; |
|---|
| 20 | +} |
|---|
| 21 | + |
|---|
| 22 | +export function ImageCaptionModal({ visible, imageUri, onSend, onCancel }: ImageCaptionModalProps) { |
|---|
| 23 | + const { colors } = useTheme(); |
|---|
| 24 | + const [caption, setCaption] = useState(""); |
|---|
| 25 | + const inputRef = useRef<TextInput>(null); |
|---|
| 26 | + const { width, height } = Dimensions.get("window"); |
|---|
| 27 | + |
|---|
| 28 | + useEffect(() => { |
|---|
| 29 | + if (visible) { |
|---|
| 30 | + setCaption(""); |
|---|
| 31 | + setTimeout(() => inputRef.current?.focus(), 300); |
|---|
| 32 | + } |
|---|
| 33 | + }, [visible]); |
|---|
| 34 | + |
|---|
| 35 | + const handleSend = () => { |
|---|
| 36 | + onSend(caption.trim()); |
|---|
| 37 | + setCaption(""); |
|---|
| 38 | + }; |
|---|
| 39 | + |
|---|
| 40 | + return ( |
|---|
| 41 | + <Modal visible={visible} animationType="slide" transparent={false} onRequestClose={onCancel}> |
|---|
| 42 | + <View style={{ flex: 1, backgroundColor: "#000" }}> |
|---|
| 43 | + <KeyboardAvoidingView |
|---|
| 44 | + style={{ flex: 1 }} |
|---|
| 45 | + behavior={Platform.OS === "ios" ? "padding" : undefined} |
|---|
| 46 | + keyboardVerticalOffset={0} |
|---|
| 47 | + > |
|---|
| 48 | + {/* Top bar with cancel */} |
|---|
| 49 | + <View |
|---|
| 50 | + style={{ |
|---|
| 51 | + paddingTop: 54, |
|---|
| 52 | + paddingHorizontal: 16, |
|---|
| 53 | + paddingBottom: 12, |
|---|
| 54 | + flexDirection: "row", |
|---|
| 55 | + alignItems: "center", |
|---|
| 56 | + justifyContent: "space-between", |
|---|
| 57 | + }} |
|---|
| 58 | + > |
|---|
| 59 | + <Pressable |
|---|
| 60 | + onPress={onCancel} |
|---|
| 61 | + hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} |
|---|
| 62 | + style={{ |
|---|
| 63 | + paddingHorizontal: 12, |
|---|
| 64 | + paddingVertical: 6, |
|---|
| 65 | + borderRadius: 16, |
|---|
| 66 | + backgroundColor: "rgba(255,255,255,0.15)", |
|---|
| 67 | + }} |
|---|
| 68 | + > |
|---|
| 69 | + <Text style={{ color: "#fff", fontSize: 16, fontWeight: "600" }}>Cancel</Text> |
|---|
| 70 | + </Pressable> |
|---|
| 71 | + </View> |
|---|
| 72 | + |
|---|
| 73 | + {/* Image preview */} |
|---|
| 74 | + <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}> |
|---|
| 75 | + <Image |
|---|
| 76 | + source={{ uri: imageUri }} |
|---|
| 77 | + style={{ width, height: height * 0.55 }} |
|---|
| 78 | + resizeMode="contain" |
|---|
| 79 | + /> |
|---|
| 80 | + </View> |
|---|
| 81 | + |
|---|
| 82 | + {/* Caption input + send */} |
|---|
| 83 | + <View |
|---|
| 84 | + style={{ |
|---|
| 85 | + flexDirection: "row", |
|---|
| 86 | + alignItems: "flex-end", |
|---|
| 87 | + paddingHorizontal: 12, |
|---|
| 88 | + paddingVertical: 10, |
|---|
| 89 | + paddingBottom: 34, |
|---|
| 90 | + gap: 8, |
|---|
| 91 | + }} |
|---|
| 92 | + > |
|---|
| 93 | + <TextInput |
|---|
| 94 | + ref={inputRef} |
|---|
| 95 | + value={caption} |
|---|
| 96 | + onChangeText={setCaption} |
|---|
| 97 | + placeholder="Add a caption..." |
|---|
| 98 | + placeholderTextColor="rgba(255,255,255,0.4)" |
|---|
| 99 | + multiline |
|---|
| 100 | + maxLength={2000} |
|---|
| 101 | + style={{ |
|---|
| 102 | + flex: 1, |
|---|
| 103 | + backgroundColor: "rgba(255,255,255,0.12)", |
|---|
| 104 | + borderRadius: 20, |
|---|
| 105 | + paddingHorizontal: 16, |
|---|
| 106 | + paddingVertical: 10, |
|---|
| 107 | + maxHeight: 100, |
|---|
| 108 | + color: "#fff", |
|---|
| 109 | + fontSize: 16, |
|---|
| 110 | + }} |
|---|
| 111 | + /> |
|---|
| 112 | + <Pressable |
|---|
| 113 | + onPress={handleSend} |
|---|
| 114 | + style={{ |
|---|
| 115 | + width: 44, |
|---|
| 116 | + height: 44, |
|---|
| 117 | + borderRadius: 22, |
|---|
| 118 | + alignItems: "center", |
|---|
| 119 | + justifyContent: "center", |
|---|
| 120 | + backgroundColor: colors.accent, |
|---|
| 121 | + marginBottom: 1, |
|---|
| 122 | + }} |
|---|
| 123 | + > |
|---|
| 124 | + <Text style={{ fontSize: 20, fontWeight: "bold", color: "#fff" }}>{"\u2191"}</Text> |
|---|
| 125 | + </Pressable> |
|---|
| 126 | + </View> |
|---|
| 127 | + </KeyboardAvoidingView> |
|---|
| 128 | + </View> |
|---|
| 129 | + </Modal> |
|---|
| 130 | + ); |
|---|
| 131 | +} |
|---|
| .. | .. |
|---|
| 1 | +import React, { useCallback } from "react"; |
|---|
| 2 | +import { |
|---|
| 3 | + Alert, |
|---|
| 4 | + Dimensions, |
|---|
| 5 | + Image, |
|---|
| 6 | + Modal, |
|---|
| 7 | + Pressable, |
|---|
| 8 | + ScrollView, |
|---|
| 9 | + Text, |
|---|
| 10 | + View, |
|---|
| 11 | +} from "react-native"; |
|---|
| 12 | +import { cacheDirectory, writeAsStringAsync } from "expo-file-system/legacy"; |
|---|
| 13 | +import * as Sharing from "expo-sharing"; |
|---|
| 14 | + |
|---|
| 15 | +/** Apple-style share icon (square with upward arrow) */ |
|---|
| 16 | +function ShareIcon({ size = 18, color = "#fff" }: { size?: number; color?: string }) { |
|---|
| 17 | + const boxSize = size * 0.7; |
|---|
| 18 | + const arrowWidth = 2; |
|---|
| 19 | + return ( |
|---|
| 20 | + <View style={{ width: size, height: size, alignItems: "center", justifyContent: "flex-end" }}> |
|---|
| 21 | + {/* Arrow shaft + head */} |
|---|
| 22 | + <View |
|---|
| 23 | + style={{ |
|---|
| 24 | + position: "absolute", |
|---|
| 25 | + top: 0, |
|---|
| 26 | + width: arrowWidth, |
|---|
| 27 | + height: size * 0.65, |
|---|
| 28 | + backgroundColor: color, |
|---|
| 29 | + borderRadius: 1, |
|---|
| 30 | + }} |
|---|
| 31 | + /> |
|---|
| 32 | + <View |
|---|
| 33 | + style={{ |
|---|
| 34 | + position: "absolute", |
|---|
| 35 | + top: 0, |
|---|
| 36 | + width: 0, |
|---|
| 37 | + height: 0, |
|---|
| 38 | + borderLeftWidth: size * 0.22, |
|---|
| 39 | + borderRightWidth: size * 0.22, |
|---|
| 40 | + borderBottomWidth: size * 0.25, |
|---|
| 41 | + borderLeftColor: "transparent", |
|---|
| 42 | + borderRightColor: "transparent", |
|---|
| 43 | + borderBottomColor: color, |
|---|
| 44 | + transform: [{ translateY: -size * 0.12 }], |
|---|
| 45 | + }} |
|---|
| 46 | + /> |
|---|
| 47 | + {/* Open box (3 sides) */} |
|---|
| 48 | + <View |
|---|
| 49 | + style={{ |
|---|
| 50 | + width: boxSize, |
|---|
| 51 | + height: boxSize * 0.7, |
|---|
| 52 | + borderWidth: arrowWidth, |
|---|
| 53 | + borderTopWidth: 0, |
|---|
| 54 | + borderColor: color, |
|---|
| 55 | + borderRadius: 2, |
|---|
| 56 | + }} |
|---|
| 57 | + /> |
|---|
| 58 | + </View> |
|---|
| 59 | + ); |
|---|
| 60 | +} |
|---|
| 61 | + |
|---|
| 62 | +interface ImageViewerProps { |
|---|
| 63 | + visible: boolean; |
|---|
| 64 | + imageBase64: string; |
|---|
| 65 | + onClose: () => void; |
|---|
| 66 | +} |
|---|
| 67 | + |
|---|
| 68 | +export function ImageViewer({ visible, imageBase64, onClose }: ImageViewerProps) { |
|---|
| 69 | + const { width, height } = Dimensions.get("window"); |
|---|
| 70 | + |
|---|
| 71 | + const handleShare = useCallback(async () => { |
|---|
| 72 | + try { |
|---|
| 73 | + const fileUri = `${cacheDirectory}pailot-screenshot-${Date.now()}.png`; |
|---|
| 74 | + await writeAsStringAsync(fileUri, imageBase64, { |
|---|
| 75 | + encoding: "base64", |
|---|
| 76 | + }); |
|---|
| 77 | + if (!(await Sharing.isAvailableAsync())) { |
|---|
| 78 | + Alert.alert("Sharing not available on this device"); |
|---|
| 79 | + return; |
|---|
| 80 | + } |
|---|
| 81 | + await Sharing.shareAsync(fileUri, { mimeType: "image/png" }); |
|---|
| 82 | + } catch (err: any) { |
|---|
| 83 | + if (err?.message?.includes("User did not share")) return; |
|---|
| 84 | + Alert.alert("Share Error", err?.message ?? String(err)); |
|---|
| 85 | + } |
|---|
| 86 | + }, [imageBase64]); |
|---|
| 87 | + |
|---|
| 88 | + return ( |
|---|
| 89 | + <Modal |
|---|
| 90 | + visible={visible} |
|---|
| 91 | + transparent |
|---|
| 92 | + animationType="fade" |
|---|
| 93 | + onRequestClose={onClose} |
|---|
| 94 | + > |
|---|
| 95 | + <View style={{ flex: 1, backgroundColor: "rgba(0,0,0,0.95)" }}> |
|---|
| 96 | + {/* Top bar: share + close */} |
|---|
| 97 | + <View |
|---|
| 98 | + style={{ |
|---|
| 99 | + position: "absolute", |
|---|
| 100 | + top: 60, |
|---|
| 101 | + right: 20, |
|---|
| 102 | + zIndex: 10, |
|---|
| 103 | + flexDirection: "row", |
|---|
| 104 | + gap: 12, |
|---|
| 105 | + }} |
|---|
| 106 | + > |
|---|
| 107 | + <Pressable |
|---|
| 108 | + onPress={handleShare} |
|---|
| 109 | + hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} |
|---|
| 110 | + style={{ |
|---|
| 111 | + width: 40, |
|---|
| 112 | + height: 40, |
|---|
| 113 | + borderRadius: 20, |
|---|
| 114 | + backgroundColor: "rgba(255,255,255,0.15)", |
|---|
| 115 | + alignItems: "center", |
|---|
| 116 | + justifyContent: "center", |
|---|
| 117 | + }} |
|---|
| 118 | + > |
|---|
| 119 | + <ShareIcon size={20} color="#fff" /> |
|---|
| 120 | + </Pressable> |
|---|
| 121 | + <Pressable |
|---|
| 122 | + onPress={onClose} |
|---|
| 123 | + hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} |
|---|
| 124 | + style={{ |
|---|
| 125 | + width: 40, |
|---|
| 126 | + height: 40, |
|---|
| 127 | + borderRadius: 20, |
|---|
| 128 | + backgroundColor: "rgba(255,255,255,0.15)", |
|---|
| 129 | + alignItems: "center", |
|---|
| 130 | + justifyContent: "center", |
|---|
| 131 | + }} |
|---|
| 132 | + > |
|---|
| 133 | + <Text style={{ color: "#fff", fontSize: 20, fontWeight: "600" }}> |
|---|
| 134 | + ✕ |
|---|
| 135 | + </Text> |
|---|
| 136 | + </Pressable> |
|---|
| 137 | + </View> |
|---|
| 138 | + |
|---|
| 139 | + {/* Zoomable image */} |
|---|
| 140 | + <ScrollView |
|---|
| 141 | + maximumZoomScale={5} |
|---|
| 142 | + minimumZoomScale={1} |
|---|
| 143 | + centerContent |
|---|
| 144 | + contentContainerStyle={{ |
|---|
| 145 | + flex: 1, |
|---|
| 146 | + justifyContent: "center", |
|---|
| 147 | + alignItems: "center", |
|---|
| 148 | + }} |
|---|
| 149 | + showsVerticalScrollIndicator={false} |
|---|
| 150 | + showsHorizontalScrollIndicator={false} |
|---|
| 151 | + > |
|---|
| 152 | + <Image |
|---|
| 153 | + source={{ uri: `data:image/png;base64,${imageBase64}` }} |
|---|
| 154 | + style={{ width, height: height * 0.85 }} |
|---|
| 155 | + resizeMode="contain" |
|---|
| 156 | + /> |
|---|
| 157 | + </ScrollView> |
|---|
| 158 | + </View> |
|---|
| 159 | + </Modal> |
|---|
| 160 | + ); |
|---|
| 161 | +} |
|---|
| .. | .. |
|---|
| 8 | 8 | } from "react-native"; |
|---|
| 9 | 9 | import * as Haptics from "expo-haptics"; |
|---|
| 10 | 10 | import { VoiceButton } from "./VoiceButton"; |
|---|
| 11 | +import { useTheme } from "../../contexts/ThemeContext"; |
|---|
| 11 | 12 | |
|---|
| 12 | 13 | interface InputBarProps { |
|---|
| 13 | 14 | onSendText: (text: string) => void; |
|---|
| 15 | + onVoiceRecorded: (uri: string) => void; |
|---|
| 14 | 16 | onReplay: () => void; |
|---|
| 15 | 17 | isTextMode: boolean; |
|---|
| 16 | 18 | onToggleMode: () => void; |
|---|
| 19 | + audioPlaying?: boolean; |
|---|
| 17 | 20 | } |
|---|
| 18 | 21 | |
|---|
| 19 | 22 | export function InputBar({ |
|---|
| 20 | 23 | onSendText, |
|---|
| 24 | + onVoiceRecorded, |
|---|
| 21 | 25 | onReplay, |
|---|
| 22 | 26 | isTextMode, |
|---|
| 23 | 27 | onToggleMode, |
|---|
| 28 | + audioPlaying = false, |
|---|
| 24 | 29 | }: InputBarProps) { |
|---|
| 25 | 30 | const [text, setText] = useState(""); |
|---|
| 26 | 31 | const inputRef = useRef<TextInput>(null); |
|---|
| 32 | + const { colors } = useTheme(); |
|---|
| 33 | + |
|---|
| 34 | + const canSend = !!text.trim(); |
|---|
| 27 | 35 | |
|---|
| 28 | 36 | const handleSend = useCallback(() => { |
|---|
| 29 | 37 | const trimmed = text.trim(); |
|---|
| .. | .. |
|---|
| 43 | 51 | paddingVertical: 10, |
|---|
| 44 | 52 | paddingBottom: 6, |
|---|
| 45 | 53 | borderTopWidth: 1, |
|---|
| 46 | | - borderTopColor: "#2E2E45", |
|---|
| 54 | + borderTopColor: colors.border, |
|---|
| 47 | 55 | alignItems: "center", |
|---|
| 48 | 56 | }} |
|---|
| 49 | 57 | > |
|---|
| 50 | | - {/* Replay last message */} |
|---|
| 58 | + {/* Replay / Stop */} |
|---|
| 51 | 59 | <Pressable |
|---|
| 52 | 60 | onPress={() => { |
|---|
| 53 | 61 | Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); |
|---|
| .. | .. |
|---|
| 61 | 69 | borderRadius: 34, |
|---|
| 62 | 70 | alignItems: "center", |
|---|
| 63 | 71 | justifyContent: "center", |
|---|
| 64 | | - backgroundColor: "#1A2E1A", |
|---|
| 72 | + backgroundColor: colors.bgTertiary, |
|---|
| 65 | 73 | borderWidth: 1.5, |
|---|
| 66 | | - borderColor: "#3A6A3A", |
|---|
| 74 | + borderColor: colors.border, |
|---|
| 67 | 75 | }} |
|---|
| 68 | 76 | > |
|---|
| 69 | | - <Text style={{ fontSize: 24 }}>▶</Text> |
|---|
| 70 | | - <Text style={{ color: "#8ABF8A", fontSize: 10, marginTop: 1, fontWeight: "600" }}>Replay</Text> |
|---|
| 77 | + <Text style={{ fontSize: 24 }}>{audioPlaying ? "\u23F8" : "\u25B6"}</Text> |
|---|
| 78 | + <Text style={{ color: colors.textSecondary, fontSize: 10, marginTop: 1, fontWeight: "600" }}> |
|---|
| 79 | + {audioPlaying ? "Stop" : "Replay"} |
|---|
| 80 | + </Text> |
|---|
| 71 | 81 | </View> |
|---|
| 72 | 82 | </Pressable> |
|---|
| 73 | 83 | |
|---|
| 74 | | - {/* Talk button — center, biggest */} |
|---|
| 84 | + {/* Talk button */} |
|---|
| 75 | 85 | <View style={{ flex: 1, alignItems: "center" }}> |
|---|
| 76 | | - <VoiceButton onTranscript={onSendText} /> |
|---|
| 86 | + <VoiceButton onVoiceRecorded={onVoiceRecorded} /> |
|---|
| 77 | 87 | </View> |
|---|
| 78 | 88 | |
|---|
| 79 | 89 | {/* Text mode toggle */} |
|---|
| .. | .. |
|---|
| 91 | 101 | borderRadius: 34, |
|---|
| 92 | 102 | alignItems: "center", |
|---|
| 93 | 103 | justifyContent: "center", |
|---|
| 94 | | - backgroundColor: "#1A1A3E", |
|---|
| 104 | + backgroundColor: colors.bgTertiary, |
|---|
| 95 | 105 | borderWidth: 1.5, |
|---|
| 96 | | - borderColor: "#3A3A7A", |
|---|
| 106 | + borderColor: colors.border, |
|---|
| 97 | 107 | }} |
|---|
| 98 | 108 | > |
|---|
| 99 | | - <Text style={{ fontSize: 22, color: "#9898D0", fontWeight: "700" }}>Aa</Text> |
|---|
| 109 | + <Text style={{ fontSize: 22, color: colors.textSecondary, fontWeight: "700" }}>Aa</Text> |
|---|
| 100 | 110 | </View> |
|---|
| 101 | 111 | </Pressable> |
|---|
| 102 | 112 | </View> |
|---|
| .. | .. |
|---|
| 112 | 122 | paddingHorizontal: 12, |
|---|
| 113 | 123 | paddingVertical: 8, |
|---|
| 114 | 124 | borderTopWidth: 1, |
|---|
| 115 | | - borderTopColor: "#2E2E45", |
|---|
| 125 | + borderTopColor: colors.border, |
|---|
| 116 | 126 | alignItems: "flex-end", |
|---|
| 117 | 127 | }} |
|---|
| 118 | 128 | > |
|---|
| .. | .. |
|---|
| 129 | 139 | borderRadius: 20, |
|---|
| 130 | 140 | alignItems: "center", |
|---|
| 131 | 141 | justifyContent: "center", |
|---|
| 132 | | - backgroundColor: "#1E1E2E", |
|---|
| 142 | + backgroundColor: colors.bgTertiary, |
|---|
| 133 | 143 | marginBottom: 2, |
|---|
| 134 | 144 | }} |
|---|
| 135 | 145 | > |
|---|
| 136 | | - <Text style={{ fontSize: 20 }}>🎤</Text> |
|---|
| 146 | + <Text style={{ fontSize: 20 }}>{"\uD83C\uDFA4"}</Text> |
|---|
| 137 | 147 | </Pressable> |
|---|
| 138 | 148 | |
|---|
| 139 | 149 | {/* Text input */} |
|---|
| .. | .. |
|---|
| 142 | 152 | value={text} |
|---|
| 143 | 153 | onChangeText={setText} |
|---|
| 144 | 154 | placeholder="Message PAI..." |
|---|
| 145 | | - placeholderTextColor="#5A5A78" |
|---|
| 155 | + placeholderTextColor={colors.textMuted} |
|---|
| 146 | 156 | multiline |
|---|
| 147 | 157 | maxLength={2000} |
|---|
| 148 | 158 | onSubmitEditing={handleSend} |
|---|
| .. | .. |
|---|
| 150 | 160 | blurOnSubmit |
|---|
| 151 | 161 | style={{ |
|---|
| 152 | 162 | flex: 1, |
|---|
| 153 | | - backgroundColor: "#1E1E2E", |
|---|
| 163 | + backgroundColor: colors.bgTertiary, |
|---|
| 154 | 164 | borderRadius: 20, |
|---|
| 155 | 165 | paddingHorizontal: 16, |
|---|
| 156 | 166 | paddingVertical: 10, |
|---|
| 157 | 167 | maxHeight: 120, |
|---|
| 158 | | - color: "#E8E8F0", |
|---|
| 168 | + color: colors.text, |
|---|
| 159 | 169 | fontSize: 16, |
|---|
| 160 | 170 | }} |
|---|
| 161 | 171 | /> |
|---|
| .. | .. |
|---|
| 163 | 173 | {/* Send button */} |
|---|
| 164 | 174 | <Pressable |
|---|
| 165 | 175 | onPress={handleSend} |
|---|
| 166 | | - disabled={!text.trim()} |
|---|
| 176 | + disabled={!canSend} |
|---|
| 167 | 177 | style={{ |
|---|
| 168 | 178 | width: 40, |
|---|
| 169 | 179 | height: 40, |
|---|
| .. | .. |
|---|
| 171 | 181 | alignItems: "center", |
|---|
| 172 | 182 | justifyContent: "center", |
|---|
| 173 | 183 | marginBottom: 2, |
|---|
| 174 | | - backgroundColor: text.trim() ? "#4A9EFF" : "#1E1E2E", |
|---|
| 184 | + backgroundColor: canSend ? colors.accent : colors.bgTertiary, |
|---|
| 175 | 185 | }} |
|---|
| 176 | 186 | > |
|---|
| 177 | 187 | <Text |
|---|
| 178 | 188 | style={{ |
|---|
| 179 | 189 | fontSize: 18, |
|---|
| 180 | 190 | fontWeight: "bold", |
|---|
| 181 | | - color: text.trim() ? "#FFFFFF" : "#5A5A78", |
|---|
| 191 | + color: canSend ? "#FFFFFF" : colors.textMuted, |
|---|
| 182 | 192 | }} |
|---|
| 183 | 193 | > |
|---|
| 184 | | - ↑ |
|---|
| 194 | + {"\u2191"} |
|---|
| 185 | 195 | </Text> |
|---|
| 186 | 196 | </Pressable> |
|---|
| 187 | 197 | </View> |
|---|
| .. | .. |
|---|
| 1 | | -import React, { useCallback, useState } from "react"; |
|---|
| 1 | +import React, { useCallback, useEffect, useState } from "react"; |
|---|
| 2 | 2 | import { Image, Pressable, Text, View } from "react-native"; |
|---|
| 3 | 3 | import { Message } from "../../types"; |
|---|
| 4 | | -import { playAudio, stopPlayback } from "../../services/audio"; |
|---|
| 4 | +import { playAudio, stopPlayback, onPlayingChange } from "../../services/audio"; |
|---|
| 5 | +import { ImageViewer } from "./ImageViewer"; |
|---|
| 6 | +import { useTheme } from "../../contexts/ThemeContext"; |
|---|
| 5 | 7 | |
|---|
| 6 | 8 | interface MessageBubbleProps { |
|---|
| 7 | 9 | message: Message; |
|---|
| .. | .. |
|---|
| 22 | 24 | |
|---|
| 23 | 25 | export function MessageBubble({ message }: MessageBubbleProps) { |
|---|
| 24 | 26 | const [isPlaying, setIsPlaying] = useState(false); |
|---|
| 27 | + const [showViewer, setShowViewer] = useState(false); |
|---|
| 28 | + const { colors, isDark } = useTheme(); |
|---|
| 29 | + |
|---|
| 30 | + useEffect(() => { |
|---|
| 31 | + return onPlayingChange((playing) => { |
|---|
| 32 | + if (!playing) setIsPlaying(false); |
|---|
| 33 | + }); |
|---|
| 34 | + }, []); |
|---|
| 25 | 35 | |
|---|
| 26 | 36 | const isUser = message.role === "user"; |
|---|
| 27 | 37 | const isSystem = message.role === "system"; |
|---|
| .. | .. |
|---|
| 40 | 50 | |
|---|
| 41 | 51 | if (isSystem) { |
|---|
| 42 | 52 | return ( |
|---|
| 43 | | - <View className="items-center my-1 px-4"> |
|---|
| 44 | | - <Text className="text-pai-text-muted text-xs">{message.content}</Text> |
|---|
| 53 | + <View style={{ alignItems: "center", marginVertical: 4, paddingHorizontal: 16 }}> |
|---|
| 54 | + <Text style={{ color: colors.textMuted, fontSize: 12 }}>{message.content}</Text> |
|---|
| 45 | 55 | </View> |
|---|
| 46 | 56 | ); |
|---|
| 47 | 57 | } |
|---|
| 48 | 58 | |
|---|
| 59 | + const bubbleBg = isUser |
|---|
| 60 | + ? colors.accent |
|---|
| 61 | + : isDark ? "#252538" : colors.bgSecondary; |
|---|
| 62 | + const bubbleRadius = isUser |
|---|
| 63 | + ? { borderTopRightRadius: 4 } |
|---|
| 64 | + : { borderTopLeftRadius: 4 }; |
|---|
| 65 | + |
|---|
| 49 | 66 | return ( |
|---|
| 50 | 67 | <View |
|---|
| 51 | | - className={`flex-row my-1 px-3 ${isUser ? "justify-end" : "justify-start"}`} |
|---|
| 68 | + style={{ |
|---|
| 69 | + flexDirection: "row", |
|---|
| 70 | + marginVertical: 4, |
|---|
| 71 | + paddingHorizontal: 12, |
|---|
| 72 | + justifyContent: isUser ? "flex-end" : "flex-start", |
|---|
| 73 | + }} |
|---|
| 52 | 74 | > |
|---|
| 53 | 75 | <View |
|---|
| 54 | | - className={`max-w-[78%] rounded-2xl px-4 py-3 ${ |
|---|
| 55 | | - isUser |
|---|
| 56 | | - ? "bg-pai-accent rounded-tr-sm" |
|---|
| 57 | | - : "bg-pai-surface rounded-tl-sm" |
|---|
| 58 | | - }`} |
|---|
| 76 | + style={{ |
|---|
| 77 | + maxWidth: "78%", |
|---|
| 78 | + borderRadius: 16, |
|---|
| 79 | + paddingHorizontal: 16, |
|---|
| 80 | + paddingVertical: 12, |
|---|
| 81 | + backgroundColor: bubbleBg, |
|---|
| 82 | + ...bubbleRadius, |
|---|
| 83 | + }} |
|---|
| 59 | 84 | > |
|---|
| 60 | 85 | {message.type === "image" && message.imageBase64 ? ( |
|---|
| 61 | | - /* Image message */ |
|---|
| 62 | 86 | <View> |
|---|
| 63 | | - <Image |
|---|
| 64 | | - source={{ uri: `data:image/png;base64,${message.imageBase64}` }} |
|---|
| 65 | | - style={{ |
|---|
| 66 | | - width: 260, |
|---|
| 67 | | - height: 180, |
|---|
| 68 | | - borderRadius: 10, |
|---|
| 69 | | - backgroundColor: "#14141F", |
|---|
| 70 | | - }} |
|---|
| 71 | | - resizeMode="contain" |
|---|
| 72 | | - /> |
|---|
| 87 | + <Pressable onPress={() => setShowViewer(true)}> |
|---|
| 88 | + <Image |
|---|
| 89 | + source={{ uri: `data:image/png;base64,${message.imageBase64}` }} |
|---|
| 90 | + style={{ |
|---|
| 91 | + width: 260, |
|---|
| 92 | + height: 180, |
|---|
| 93 | + borderRadius: 10, |
|---|
| 94 | + backgroundColor: colors.bgTertiary, |
|---|
| 95 | + }} |
|---|
| 96 | + resizeMode="contain" |
|---|
| 97 | + /> |
|---|
| 98 | + </Pressable> |
|---|
| 73 | 99 | {message.content ? ( |
|---|
| 74 | 100 | <Text |
|---|
| 75 | 101 | style={{ |
|---|
| 76 | | - color: isUser ? "#FFF" : "#9898B0", |
|---|
| 102 | + color: isUser ? "#FFF" : colors.textSecondary, |
|---|
| 77 | 103 | fontSize: 12, |
|---|
| 78 | 104 | marginTop: 4, |
|---|
| 79 | 105 | }} |
|---|
| .. | .. |
|---|
| 81 | 107 | {message.content} |
|---|
| 82 | 108 | </Text> |
|---|
| 83 | 109 | ) : null} |
|---|
| 110 | + <ImageViewer |
|---|
| 111 | + visible={showViewer} |
|---|
| 112 | + imageBase64={message.imageBase64} |
|---|
| 113 | + onClose={() => setShowViewer(false)} |
|---|
| 114 | + /> |
|---|
| 84 | 115 | </View> |
|---|
| 85 | 116 | ) : message.type === "voice" ? ( |
|---|
| 86 | 117 | <Pressable |
|---|
| 87 | 118 | onPress={handleVoicePress} |
|---|
| 88 | | - className="flex-row items-center gap-3" |
|---|
| 119 | + style={{ flexDirection: "row", alignItems: "center", gap: 12 }} |
|---|
| 89 | 120 | > |
|---|
| 90 | | - {/* Play/pause icon */} |
|---|
| 91 | 121 | <View |
|---|
| 92 | | - className={`w-9 h-9 rounded-full items-center justify-center ${ |
|---|
| 93 | | - isPlaying ? "bg-pai-voice" : isUser ? "bg-white/20" : "bg-pai-border" |
|---|
| 94 | | - }`} |
|---|
| 122 | + style={{ |
|---|
| 123 | + width: 36, |
|---|
| 124 | + height: 36, |
|---|
| 125 | + borderRadius: 18, |
|---|
| 126 | + alignItems: "center", |
|---|
| 127 | + justifyContent: "center", |
|---|
| 128 | + backgroundColor: isPlaying |
|---|
| 129 | + ? "#FF9F43" |
|---|
| 130 | + : isUser |
|---|
| 131 | + ? "rgba(255,255,255,0.2)" |
|---|
| 132 | + : colors.border, |
|---|
| 133 | + }} |
|---|
| 95 | 134 | > |
|---|
| 96 | | - <Text |
|---|
| 97 | | - className={`text-base ${isUser ? "text-white" : "text-pai-text"}`} |
|---|
| 98 | | - > |
|---|
| 99 | | - {isPlaying ? "⏸" : "▶"} |
|---|
| 135 | + <Text style={{ fontSize: 14, color: isUser ? "#FFF" : colors.text }}> |
|---|
| 136 | + {isPlaying ? "\u23F8" : "\u25B6"} |
|---|
| 100 | 137 | </Text> |
|---|
| 101 | 138 | </View> |
|---|
| 102 | 139 | |
|---|
| 103 | | - {/* Waveform placeholder */} |
|---|
| 104 | | - <View className="flex-1 flex-row items-center gap-px h-8"> |
|---|
| 140 | + <View style={{ flex: 1, flexDirection: "row", alignItems: "center", gap: 1, height: 32 }}> |
|---|
| 105 | 141 | {Array.from({ length: 20 }).map((_, i) => ( |
|---|
| 106 | 142 | <View |
|---|
| 107 | 143 | key={i} |
|---|
| 108 | | - className={`flex-1 rounded-full ${ |
|---|
| 109 | | - isPlaying && i < 10 |
|---|
| 110 | | - ? "bg-pai-voice" |
|---|
| 111 | | - : isUser |
|---|
| 112 | | - ? "bg-white/50" |
|---|
| 113 | | - : "bg-pai-text-muted" |
|---|
| 114 | | - }`} |
|---|
| 115 | 144 | style={{ |
|---|
| 145 | + flex: 1, |
|---|
| 146 | + borderRadius: 2, |
|---|
| 147 | + backgroundColor: isPlaying && i < 10 |
|---|
| 148 | + ? "#FF9F43" |
|---|
| 149 | + : isUser |
|---|
| 150 | + ? "rgba(255,255,255,0.5)" |
|---|
| 151 | + : colors.textMuted, |
|---|
| 116 | 152 | height: `${20 + Math.sin(i * 0.8) * 60}%`, |
|---|
| 117 | 153 | }} |
|---|
| 118 | 154 | /> |
|---|
| 119 | 155 | ))} |
|---|
| 120 | 156 | </View> |
|---|
| 121 | 157 | |
|---|
| 122 | | - {/* Duration */} |
|---|
| 123 | 158 | <Text |
|---|
| 124 | | - className={`text-xs ${ |
|---|
| 125 | | - isUser ? "text-white/80" : "text-pai-text-secondary" |
|---|
| 126 | | - }`} |
|---|
| 159 | + style={{ |
|---|
| 160 | + fontSize: 11, |
|---|
| 161 | + color: isUser ? "rgba(255,255,255,0.8)" : colors.textSecondary, |
|---|
| 162 | + }} |
|---|
| 127 | 163 | > |
|---|
| 128 | 164 | {formatDuration(message.duration)} |
|---|
| 129 | 165 | </Text> |
|---|
| 130 | 166 | </Pressable> |
|---|
| 131 | 167 | ) : ( |
|---|
| 132 | 168 | <Text |
|---|
| 133 | | - className={`text-base leading-6 ${ |
|---|
| 134 | | - isUser ? "text-white" : "text-pai-text" |
|---|
| 135 | | - }`} |
|---|
| 169 | + style={{ |
|---|
| 170 | + fontSize: 16, |
|---|
| 171 | + lineHeight: 24, |
|---|
| 172 | + color: isUser ? "#FFF" : colors.text, |
|---|
| 173 | + }} |
|---|
| 136 | 174 | > |
|---|
| 137 | 175 | {message.content} |
|---|
| 138 | 176 | </Text> |
|---|
| 139 | 177 | )} |
|---|
| 140 | 178 | |
|---|
| 141 | | - {/* Timestamp + status */} |
|---|
| 142 | | - <View className={`flex-row items-center mt-1 gap-1 ${isUser ? "justify-end" : "justify-start"}`}> |
|---|
| 179 | + <View |
|---|
| 180 | + style={{ |
|---|
| 181 | + flexDirection: "row", |
|---|
| 182 | + alignItems: "center", |
|---|
| 183 | + marginTop: 4, |
|---|
| 184 | + gap: 4, |
|---|
| 185 | + justifyContent: isUser ? "flex-end" : "flex-start", |
|---|
| 186 | + }} |
|---|
| 187 | + > |
|---|
| 143 | 188 | <Text |
|---|
| 144 | | - className={`text-2xs ${ |
|---|
| 145 | | - isUser ? "text-white/60" : "text-pai-text-muted" |
|---|
| 146 | | - }`} |
|---|
| 189 | + style={{ |
|---|
| 190 | + fontSize: 10, |
|---|
| 191 | + color: isUser ? "rgba(255,255,255,0.6)" : colors.textMuted, |
|---|
| 192 | + }} |
|---|
| 147 | 193 | > |
|---|
| 148 | 194 | {formatTime(message.timestamp)} |
|---|
| 149 | 195 | </Text> |
|---|
| 150 | 196 | {isUser && message.status === "error" && ( |
|---|
| 151 | | - <Text className="text-2xs text-pai-error"> !</Text> |
|---|
| 197 | + <Text style={{ fontSize: 10, color: colors.danger }}> !</Text> |
|---|
| 152 | 198 | )} |
|---|
| 153 | 199 | </View> |
|---|
| 154 | 200 | </View> |
|---|
| .. | .. |
|---|
| 1 | | -import React, { useCallback, useEffect, useRef, useState } from "react"; |
|---|
| 1 | +import React, { useCallback, useRef, useState } from "react"; |
|---|
| 2 | 2 | import { Animated, Pressable, Text, View } from "react-native"; |
|---|
| 3 | 3 | import * as Haptics from "expo-haptics"; |
|---|
| 4 | 4 | import { |
|---|
| 5 | | - ExpoSpeechRecognitionModule, |
|---|
| 6 | | - useSpeechRecognitionEvent, |
|---|
| 7 | | -} from "expo-speech-recognition"; |
|---|
| 5 | + useAudioRecorder, |
|---|
| 6 | + RecordingPresets, |
|---|
| 7 | + requestRecordingPermissionsAsync, |
|---|
| 8 | + setAudioModeAsync, |
|---|
| 9 | +} from "expo-audio"; |
|---|
| 10 | +import { stopPlayback } from "../../services/audio"; |
|---|
| 8 | 11 | |
|---|
| 9 | 12 | interface VoiceButtonProps { |
|---|
| 10 | | - onTranscript: (text: string) => void; |
|---|
| 13 | + onVoiceRecorded: (uri: string) => void; |
|---|
| 11 | 14 | } |
|---|
| 12 | 15 | |
|---|
| 13 | 16 | const VOICE_BUTTON_SIZE = 72; |
|---|
| 14 | 17 | |
|---|
| 15 | 18 | /** |
|---|
| 16 | | - * Tap-to-toggle voice button using on-device speech recognition. |
|---|
| 17 | | - * - Tap once: start listening |
|---|
| 18 | | - * - Tap again: stop and send transcript |
|---|
| 19 | | - * - Long-press while listening: cancel (discard) |
|---|
| 19 | + * Tap-to-toggle voice button using expo-audio recording. |
|---|
| 20 | + * Records audio and returns the file URI for the caller to send. |
|---|
| 21 | + * - Tap once: start recording |
|---|
| 22 | + * - Tap again: stop and send |
|---|
| 23 | + * - Long-press while recording: cancel (discard) |
|---|
| 20 | 24 | */ |
|---|
| 21 | | -export function VoiceButton({ onTranscript }: VoiceButtonProps) { |
|---|
| 22 | | - const [isListening, setIsListening] = useState(false); |
|---|
| 23 | | - const [transcript, setTranscript] = useState(""); |
|---|
| 25 | +export function VoiceButton({ onVoiceRecorded }: VoiceButtonProps) { |
|---|
| 26 | + const [isRecording, setIsRecording] = useState(false); |
|---|
| 24 | 27 | const pulseAnim = useRef(new Animated.Value(1)).current; |
|---|
| 25 | 28 | const glowAnim = useRef(new Animated.Value(0)).current; |
|---|
| 26 | 29 | const pulseLoop = useRef<Animated.CompositeAnimation | null>(null); |
|---|
| 27 | | - const cancelledRef = useRef(false); |
|---|
| 28 | 30 | |
|---|
| 29 | | - // Speech recognition events |
|---|
| 30 | | - useSpeechRecognitionEvent("start", () => { |
|---|
| 31 | | - setIsListening(true); |
|---|
| 32 | | - }); |
|---|
| 33 | | - |
|---|
| 34 | | - useSpeechRecognitionEvent("end", () => { |
|---|
| 35 | | - setIsListening(false); |
|---|
| 36 | | - stopPulse(); |
|---|
| 37 | | - |
|---|
| 38 | | - // Send transcript if we have one and weren't cancelled |
|---|
| 39 | | - if (!cancelledRef.current && transcript.trim()) { |
|---|
| 40 | | - onTranscript(transcript.trim()); |
|---|
| 41 | | - } |
|---|
| 42 | | - setTranscript(""); |
|---|
| 43 | | - cancelledRef.current = false; |
|---|
| 44 | | - }); |
|---|
| 45 | | - |
|---|
| 46 | | - useSpeechRecognitionEvent("result", (event) => { |
|---|
| 47 | | - const text = event.results[0]?.transcript ?? ""; |
|---|
| 48 | | - setTranscript(text); |
|---|
| 49 | | - }); |
|---|
| 50 | | - |
|---|
| 51 | | - useSpeechRecognitionEvent("error", (event) => { |
|---|
| 52 | | - console.error("Speech recognition error:", event.error, event.message); |
|---|
| 53 | | - setIsListening(false); |
|---|
| 54 | | - stopPulse(); |
|---|
| 55 | | - setTranscript(""); |
|---|
| 56 | | - }); |
|---|
| 31 | + const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY); |
|---|
| 57 | 32 | |
|---|
| 58 | 33 | const startPulse = useCallback(() => { |
|---|
| 59 | 34 | pulseLoop.current = Animated.loop( |
|---|
| .. | .. |
|---|
| 88 | 63 | }).start(); |
|---|
| 89 | 64 | }, [pulseAnim, glowAnim]); |
|---|
| 90 | 65 | |
|---|
| 91 | | - const startListening = useCallback(async () => { |
|---|
| 92 | | - const result = await ExpoSpeechRecognitionModule.requestPermissionsAsync(); |
|---|
| 93 | | - if (!result.granted) return; |
|---|
| 66 | + const startRecording = useCallback(async () => { |
|---|
| 67 | + try { |
|---|
| 68 | + await stopPlayback(); |
|---|
| 94 | 69 | |
|---|
| 95 | | - cancelledRef.current = false; |
|---|
| 96 | | - setTranscript(""); |
|---|
| 97 | | - startPulse(); |
|---|
| 70 | + const { granted } = await requestRecordingPermissionsAsync(); |
|---|
| 71 | + if (!granted) return; |
|---|
| 98 | 72 | |
|---|
| 99 | | - ExpoSpeechRecognitionModule.start({ |
|---|
| 100 | | - lang: "en-US", |
|---|
| 101 | | - interimResults: true, |
|---|
| 102 | | - continuous: true, |
|---|
| 103 | | - }); |
|---|
| 104 | | - }, [startPulse]); |
|---|
| 73 | + await setAudioModeAsync({ |
|---|
| 74 | + allowsRecording: true, |
|---|
| 75 | + playsInSilentMode: true, |
|---|
| 76 | + }); |
|---|
| 105 | 77 | |
|---|
| 106 | | - const stopAndSend = useCallback(() => { |
|---|
| 78 | + startPulse(); |
|---|
| 79 | + await recorder.prepareToRecordAsync(); |
|---|
| 80 | + recorder.record(); |
|---|
| 81 | + setIsRecording(true); |
|---|
| 82 | + } catch (err) { |
|---|
| 83 | + console.error("Failed to start recording:", err); |
|---|
| 84 | + stopPulse(); |
|---|
| 85 | + setIsRecording(false); |
|---|
| 86 | + } |
|---|
| 87 | + }, [recorder, startPulse, stopPulse]); |
|---|
| 88 | + |
|---|
| 89 | + const stopAndSend = useCallback(async () => { |
|---|
| 107 | 90 | stopPulse(); |
|---|
| 108 | | - cancelledRef.current = false; |
|---|
| 109 | | - ExpoSpeechRecognitionModule.stop(); |
|---|
| 110 | | - }, [stopPulse]); |
|---|
| 91 | + setIsRecording(false); |
|---|
| 92 | + try { |
|---|
| 93 | + await recorder.stop(); |
|---|
| 94 | + // Reset audio mode for playback |
|---|
| 95 | + await setAudioModeAsync({ |
|---|
| 96 | + allowsRecording: false, |
|---|
| 97 | + playsInSilentMode: true, |
|---|
| 98 | + }); |
|---|
| 99 | + const uri = recorder.uri; |
|---|
| 100 | + if (uri) { |
|---|
| 101 | + onVoiceRecorded(uri); |
|---|
| 102 | + } |
|---|
| 103 | + } catch (err) { |
|---|
| 104 | + console.error("Failed to stop recording:", err); |
|---|
| 105 | + } |
|---|
| 106 | + }, [recorder, stopPulse, onVoiceRecorded]); |
|---|
| 111 | 107 | |
|---|
| 112 | | - const cancelListening = useCallback(() => { |
|---|
| 108 | + const cancelRecording = useCallback(async () => { |
|---|
| 113 | 109 | Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning); |
|---|
| 114 | 110 | stopPulse(); |
|---|
| 115 | | - cancelledRef.current = true; |
|---|
| 116 | | - setTranscript(""); |
|---|
| 117 | | - ExpoSpeechRecognitionModule.abort(); |
|---|
| 118 | | - }, [stopPulse]); |
|---|
| 111 | + setIsRecording(false); |
|---|
| 112 | + try { |
|---|
| 113 | + await recorder.stop(); |
|---|
| 114 | + } catch { |
|---|
| 115 | + // ignore |
|---|
| 116 | + } |
|---|
| 117 | + }, [recorder, stopPulse]); |
|---|
| 119 | 118 | |
|---|
| 120 | 119 | const handleTap = useCallback(async () => { |
|---|
| 121 | 120 | Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); |
|---|
| 122 | | - if (isListening) { |
|---|
| 123 | | - stopAndSend(); |
|---|
| 121 | + if (isRecording) { |
|---|
| 122 | + await stopAndSend(); |
|---|
| 124 | 123 | } else { |
|---|
| 125 | | - await startListening(); |
|---|
| 124 | + await startRecording(); |
|---|
| 126 | 125 | } |
|---|
| 127 | | - }, [isListening, stopAndSend, startListening]); |
|---|
| 126 | + }, [isRecording, stopAndSend, startRecording]); |
|---|
| 128 | 127 | |
|---|
| 129 | 128 | const handleLongPress = useCallback(() => { |
|---|
| 130 | | - if (isListening) { |
|---|
| 131 | | - cancelListening(); |
|---|
| 129 | + if (isRecording) { |
|---|
| 130 | + cancelRecording(); |
|---|
| 132 | 131 | } |
|---|
| 133 | | - }, [isListening, cancelListening]); |
|---|
| 132 | + }, [isRecording, cancelRecording]); |
|---|
| 134 | 133 | |
|---|
| 135 | 134 | return ( |
|---|
| 136 | 135 | <View style={{ alignItems: "center", justifyContent: "center" }}> |
|---|
| .. | .. |
|---|
| 141 | 140 | width: VOICE_BUTTON_SIZE + 24, |
|---|
| 142 | 141 | height: VOICE_BUTTON_SIZE + 24, |
|---|
| 143 | 142 | borderRadius: (VOICE_BUTTON_SIZE + 24) / 2, |
|---|
| 144 | | - backgroundColor: isListening ? "rgba(255, 159, 67, 0.12)" : "transparent", |
|---|
| 143 | + backgroundColor: isRecording ? "rgba(255, 159, 67, 0.12)" : "transparent", |
|---|
| 145 | 144 | transform: [{ scale: pulseAnim }], |
|---|
| 146 | 145 | opacity: glowAnim, |
|---|
| 147 | 146 | }} |
|---|
| .. | .. |
|---|
| 158 | 157 | width: VOICE_BUTTON_SIZE, |
|---|
| 159 | 158 | height: VOICE_BUTTON_SIZE, |
|---|
| 160 | 159 | borderRadius: VOICE_BUTTON_SIZE / 2, |
|---|
| 161 | | - backgroundColor: isListening ? "#FF9F43" : "#4A9EFF", |
|---|
| 160 | + backgroundColor: isRecording ? "#FF9F43" : "#4A9EFF", |
|---|
| 162 | 161 | alignItems: "center", |
|---|
| 163 | 162 | justifyContent: "center", |
|---|
| 164 | | - shadowColor: isListening ? "#FF9F43" : "#4A9EFF", |
|---|
| 163 | + shadowColor: isRecording ? "#FF9F43" : "#4A9EFF", |
|---|
| 165 | 164 | shadowOffset: { width: 0, height: 4 }, |
|---|
| 166 | 165 | shadowOpacity: 0.4, |
|---|
| 167 | 166 | shadowRadius: 12, |
|---|
| 168 | 167 | elevation: 8, |
|---|
| 169 | 168 | }} |
|---|
| 170 | 169 | > |
|---|
| 171 | | - <Text style={{ fontSize: 28 }}>{isListening ? "⏹" : "🎤"}</Text> |
|---|
| 170 | + <Text style={{ fontSize: 28 }}>{isRecording ? "⏹" : "🎤"}</Text> |
|---|
| 172 | 171 | </View> |
|---|
| 173 | 172 | </Pressable> |
|---|
| 174 | 173 | |
|---|
| 175 | | - {/* Label / transcript preview */} |
|---|
| 174 | + {/* Label */} |
|---|
| 176 | 175 | <Text |
|---|
| 177 | 176 | style={{ |
|---|
| 178 | | - color: isListening ? "#FF9F43" : "#5A5A78", |
|---|
| 177 | + color: isRecording ? "#FF9F43" : "#5A5A78", |
|---|
| 179 | 178 | fontSize: 11, |
|---|
| 180 | 179 | marginTop: 4, |
|---|
| 181 | | - fontWeight: isListening ? "600" : "400", |
|---|
| 182 | | - maxWidth: 200, |
|---|
| 183 | | - textAlign: "center", |
|---|
| 180 | + fontWeight: isRecording ? "600" : "400", |
|---|
| 184 | 181 | }} |
|---|
| 185 | | - numberOfLines={2} |
|---|
| 186 | 182 | > |
|---|
| 187 | | - {isListening |
|---|
| 188 | | - ? transcript || "Listening..." |
|---|
| 189 | | - : "Tap to talk"} |
|---|
| 183 | + {isRecording ? "Recording..." : "Tap to talk"} |
|---|
| 190 | 184 | </Text> |
|---|
| 191 | 185 | </View> |
|---|
| 192 | 186 | ); |
|---|
| .. | .. |
|---|
| 1 | 1 | import React from "react"; |
|---|
| 2 | 2 | import { Pressable, Text, ViewStyle } from "react-native"; |
|---|
| 3 | +import { useTheme } from "../../contexts/ThemeContext"; |
|---|
| 3 | 4 | |
|---|
| 4 | 5 | interface IconButtonProps { |
|---|
| 5 | 6 | onPress: () => void; |
|---|
| 6 | 7 | label: string; |
|---|
| 7 | 8 | size?: number; |
|---|
| 8 | 9 | style?: ViewStyle; |
|---|
| 9 | | - className?: string; |
|---|
| 10 | 10 | } |
|---|
| 11 | 11 | |
|---|
| 12 | 12 | export function IconButton({ |
|---|
| 13 | 13 | onPress, |
|---|
| 14 | 14 | label, |
|---|
| 15 | 15 | size = 24, |
|---|
| 16 | | - className = "", |
|---|
| 17 | 16 | }: IconButtonProps) { |
|---|
| 17 | + const { colors } = useTheme(); |
|---|
| 18 | + |
|---|
| 18 | 19 | return ( |
|---|
| 19 | 20 | <Pressable |
|---|
| 20 | 21 | onPress={onPress} |
|---|
| 21 | | - className={`items-center justify-center ${className}`} |
|---|
| 22 | | - style={{ width: size, height: size }} |
|---|
| 22 | + style={{ width: size, height: size, alignItems: "center", justifyContent: "center" }} |
|---|
| 23 | 23 | hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }} |
|---|
| 24 | 24 | > |
|---|
| 25 | | - <Text className="text-pai-text-secondary" style={{ fontSize: size * 0.7 }}> |
|---|
| 25 | + <Text style={{ color: colors.textSecondary, fontSize: size * 0.7 }}> |
|---|
| 26 | 26 | {label} |
|---|
| 27 | 27 | </Text> |
|---|
| 28 | 28 | </Pressable> |
|---|
| .. | .. |
|---|
| 8 | 8 | } |
|---|
| 9 | 9 | |
|---|
| 10 | 10 | export function StatusDot({ status, size = 10 }: StatusDotProps) { |
|---|
| 11 | | - const colorClass = |
|---|
| 11 | + const color = |
|---|
| 12 | 12 | status === "connected" |
|---|
| 13 | | - ? "bg-pai-success" |
|---|
| 13 | + ? "#22c55e" |
|---|
| 14 | + : status === "compacting" |
|---|
| 15 | + ? "#3b82f6" |
|---|
| 14 | 16 | : status === "connecting" |
|---|
| 15 | | - ? "bg-pai-warning" |
|---|
| 16 | | - : "bg-pai-error"; |
|---|
| 17 | + ? "#eab308" |
|---|
| 18 | + : "#ef4444"; |
|---|
| 17 | 19 | |
|---|
| 18 | 20 | return ( |
|---|
| 19 | 21 | <View |
|---|
| 20 | | - className={`rounded-full ${colorClass}`} |
|---|
| 21 | | - style={{ width: size, height: size }} |
|---|
| 22 | + className="rounded-full" |
|---|
| 23 | + style={{ width: size, height: size, backgroundColor: color }} |
|---|
| 22 | 24 | /> |
|---|
| 23 | 25 | ); |
|---|
| 24 | 26 | } |
|---|
| .. | .. |
|---|
| 8 | 8 | } from "react"; |
|---|
| 9 | 9 | import { Message, WsIncoming, WsSession } from "../types"; |
|---|
| 10 | 10 | import { useConnection } from "./ConnectionContext"; |
|---|
| 11 | | -import { playAudio, encodeAudioToBase64 } from "../services/audio"; |
|---|
| 11 | +import { playAudio, encodeAudioToBase64, saveBase64Audio } from "../services/audio"; |
|---|
| 12 | +import { requestNotificationPermissions, notifyIncomingMessage } from "../services/notifications"; |
|---|
| 12 | 13 | |
|---|
| 13 | 14 | function generateId(): string { |
|---|
| 14 | 15 | return Date.now().toString(36) + Math.random().toString(36).slice(2); |
|---|
| 15 | 16 | } |
|---|
| 16 | 17 | |
|---|
| 18 | +// --- Message persistence --- |
|---|
| 19 | +// Lazily import expo-file-system/legacy so a missing native module doesn't crash the app. |
|---|
| 20 | + |
|---|
| 21 | +let _fsReady: Promise<typeof import("expo-file-system/legacy")> | null = null; |
|---|
| 22 | +function getFs() { |
|---|
| 23 | + if (!_fsReady) _fsReady = import("expo-file-system/legacy"); |
|---|
| 24 | + return _fsReady; |
|---|
| 25 | +} |
|---|
| 26 | + |
|---|
| 27 | +const MESSAGES_DIR = "pailot-messages"; |
|---|
| 28 | + |
|---|
| 29 | +/** Strip heavy fields (base64 images, audio URIs) before persisting. */ |
|---|
| 30 | +function lightMessage(m: Message): Message { |
|---|
| 31 | + const light = { ...m }; |
|---|
| 32 | + if (light.imageBase64) light.imageBase64 = undefined; |
|---|
| 33 | + if (light.audioUri) light.audioUri = undefined; |
|---|
| 34 | + return light; |
|---|
| 35 | +} |
|---|
| 36 | + |
|---|
| 37 | +async function persistMessages(map: Record<string, Message[]>): Promise<void> { |
|---|
| 38 | + try { |
|---|
| 39 | + const fs = await getFs(); |
|---|
| 40 | + const dir = `${fs.documentDirectory}${MESSAGES_DIR}/`; |
|---|
| 41 | + const dirInfo = await fs.getInfoAsync(dir); |
|---|
| 42 | + if (!dirInfo.exists) await fs.makeDirectoryAsync(dir, { intermediates: true }); |
|---|
| 43 | + // Save each session's messages |
|---|
| 44 | + for (const [sessionId, msgs] of Object.entries(map)) { |
|---|
| 45 | + if (msgs.length === 0) continue; |
|---|
| 46 | + const light = msgs.map(lightMessage); |
|---|
| 47 | + await fs.writeAsStringAsync(`${dir}${sessionId}.json`, JSON.stringify(light)); |
|---|
| 48 | + } |
|---|
| 49 | + } catch { |
|---|
| 50 | + // Persistence is best-effort |
|---|
| 51 | + } |
|---|
| 52 | +} |
|---|
| 53 | + |
|---|
| 54 | +async function loadMessages(): Promise<Record<string, Message[]>> { |
|---|
| 55 | + try { |
|---|
| 56 | + const fs = await getFs(); |
|---|
| 57 | + const dir = `${fs.documentDirectory}${MESSAGES_DIR}/`; |
|---|
| 58 | + const dirInfo = await fs.getInfoAsync(dir); |
|---|
| 59 | + if (!dirInfo.exists) return {}; |
|---|
| 60 | + const files = await fs.readDirectoryAsync(dir); |
|---|
| 61 | + const result: Record<string, Message[]> = {}; |
|---|
| 62 | + for (const file of files) { |
|---|
| 63 | + if (!file.endsWith(".json")) continue; |
|---|
| 64 | + const sessionId = file.replace(".json", ""); |
|---|
| 65 | + const content = await fs.readAsStringAsync(`${dir}${file}`); |
|---|
| 66 | + result[sessionId] = JSON.parse(content) as Message[]; |
|---|
| 67 | + } |
|---|
| 68 | + return result; |
|---|
| 69 | + } catch { |
|---|
| 70 | + return {}; |
|---|
| 71 | + } |
|---|
| 72 | +} |
|---|
| 73 | + |
|---|
| 74 | +async function deletePersistedSession(sessionId: string): Promise<void> { |
|---|
| 75 | + try { |
|---|
| 76 | + const fs = await getFs(); |
|---|
| 77 | + const path = `${fs.documentDirectory}${MESSAGES_DIR}/${sessionId}.json`; |
|---|
| 78 | + const info = await fs.getInfoAsync(path); |
|---|
| 79 | + if (info.exists) await fs.deleteAsync(path); |
|---|
| 80 | + } catch { |
|---|
| 81 | + // Best-effort |
|---|
| 82 | + } |
|---|
| 83 | +} |
|---|
| 84 | + |
|---|
| 85 | +async function clearPersistedMessages(sessionId: string): Promise<void> { |
|---|
| 86 | + try { |
|---|
| 87 | + const fs = await getFs(); |
|---|
| 88 | + await fs.writeAsStringAsync( |
|---|
| 89 | + `${fs.documentDirectory}${MESSAGES_DIR}/${sessionId}.json`, |
|---|
| 90 | + "[]" |
|---|
| 91 | + ); |
|---|
| 92 | + } catch { |
|---|
| 93 | + // Best-effort |
|---|
| 94 | + } |
|---|
| 95 | +} |
|---|
| 96 | + |
|---|
| 97 | +// --- Debounced save --- |
|---|
| 98 | +let saveTimer: ReturnType<typeof setTimeout> | null = null; |
|---|
| 99 | +function debouncedSave(map: Record<string, Message[]>): void { |
|---|
| 100 | + if (saveTimer) clearTimeout(saveTimer); |
|---|
| 101 | + saveTimer = setTimeout(() => persistMessages(map), 1000); |
|---|
| 102 | +} |
|---|
| 103 | + |
|---|
| 104 | +// --- Context --- |
|---|
| 105 | + |
|---|
| 17 | 106 | interface ChatContextValue { |
|---|
| 18 | 107 | messages: Message[]; |
|---|
| 19 | 108 | sendTextMessage: (text: string) => void; |
|---|
| 20 | 109 | sendVoiceMessage: (audioUri: string, durationMs?: number) => void; |
|---|
| 110 | + sendImageMessage: (imageBase64: string, caption: string, mimeType: string) => void; |
|---|
| 21 | 111 | clearMessages: () => void; |
|---|
| 22 | | - // Session management |
|---|
| 23 | 112 | sessions: WsSession[]; |
|---|
| 113 | + activeSessionId: string | null; |
|---|
| 24 | 114 | requestSessions: () => void; |
|---|
| 25 | 115 | switchSession: (sessionId: string) => void; |
|---|
| 26 | 116 | renameSession: (sessionId: string, name: string) => void; |
|---|
| 27 | | - // Screenshot / navigation |
|---|
| 117 | + removeSession: (sessionId: string) => void; |
|---|
| 118 | + createSession: () => void; |
|---|
| 119 | + unreadCounts: Record<string, number>; |
|---|
| 28 | 120 | latestScreenshot: string | null; |
|---|
| 29 | 121 | requestScreenshot: () => void; |
|---|
| 30 | 122 | sendNavKey: (key: string) => void; |
|---|
| .. | .. |
|---|
| 33 | 125 | const ChatContext = createContext<ChatContextValue | null>(null); |
|---|
| 34 | 126 | |
|---|
| 35 | 127 | export function ChatProvider({ children }: { children: React.ReactNode }) { |
|---|
| 36 | | - const [messages, setMessages] = useState<Message[]>([]); |
|---|
| 37 | 128 | const [sessions, setSessions] = useState<WsSession[]>([]); |
|---|
| 129 | + const [activeSessionId, setActiveSessionId] = useState<string | null>(null); |
|---|
| 38 | 130 | const [latestScreenshot, setLatestScreenshot] = useState<string | null>(null); |
|---|
| 131 | + const needsSync = useRef(true); |
|---|
| 132 | + |
|---|
| 133 | + // Per-session message storage |
|---|
| 134 | + const messagesMapRef = useRef<Record<string, Message[]>>({}); |
|---|
| 135 | + // Messages for the active session (drives re-renders) |
|---|
| 136 | + const [messages, setMessages] = useState<Message[]>([]); |
|---|
| 137 | + // Unread counts for non-active sessions |
|---|
| 138 | + const [unreadCounts, setUnreadCounts] = useState<Record<string, number>>({}); |
|---|
| 139 | + |
|---|
| 39 | 140 | const { |
|---|
| 141 | + status, |
|---|
| 40 | 142 | sendTextMessage: wsSend, |
|---|
| 41 | 143 | sendVoiceMessage: wsVoice, |
|---|
| 144 | + sendImageMessage: wsImageSend, |
|---|
| 42 | 145 | sendCommand, |
|---|
| 43 | 146 | onMessageReceived, |
|---|
| 44 | 147 | } = useConnection(); |
|---|
| 45 | 148 | |
|---|
| 46 | | - const addMessage = useCallback((msg: Message) => { |
|---|
| 47 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 149 | + // Restore persisted messages on mount + request notification permissions |
|---|
| 150 | + useEffect(() => { |
|---|
| 151 | + loadMessages().then((loaded) => { |
|---|
| 152 | + if (Object.keys(loaded).length > 0) { |
|---|
| 153 | + messagesMapRef.current = loaded; |
|---|
| 154 | + } |
|---|
| 155 | + }); |
|---|
| 156 | + requestNotificationPermissions(); |
|---|
| 157 | + }, []); |
|---|
| 158 | + |
|---|
| 159 | + // Derive active session ID from sessions list when it arrives |
|---|
| 160 | + const syncActiveFromSessions = useCallback((incoming: WsSession[]) => { |
|---|
| 161 | + const active = incoming.find((s) => s.isActive); |
|---|
| 162 | + if (active) { |
|---|
| 163 | + setActiveSessionId((prev) => { |
|---|
| 164 | + if (prev !== active.id) { |
|---|
| 165 | + if (prev) { |
|---|
| 166 | + messagesMapRef.current[prev] = messages; |
|---|
| 167 | + } |
|---|
| 168 | + const stored = messagesMapRef.current[active.id] ?? []; |
|---|
| 169 | + setMessages(stored); |
|---|
| 170 | + setUnreadCounts((u) => { |
|---|
| 171 | + if (!u[active.id]) return u; |
|---|
| 172 | + const next = { ...u }; |
|---|
| 173 | + delete next[active.id]; |
|---|
| 174 | + return next; |
|---|
| 175 | + }); |
|---|
| 176 | + } |
|---|
| 177 | + return active.id; |
|---|
| 178 | + }); |
|---|
| 179 | + } |
|---|
| 180 | + }, [messages]); |
|---|
| 181 | + |
|---|
| 182 | + // On connect: ask gateway to detect the focused iTerm2 session and sync |
|---|
| 183 | + useEffect(() => { |
|---|
| 184 | + if (status === "connected") { |
|---|
| 185 | + needsSync.current = true; |
|---|
| 186 | + sendCommand("sync"); |
|---|
| 187 | + } |
|---|
| 188 | + }, [status, sendCommand]); |
|---|
| 189 | + |
|---|
| 190 | + // Helper: add a message to the active session |
|---|
| 191 | + const addMessageToActive = useCallback((msg: Message) => { |
|---|
| 192 | + setMessages((prev) => { |
|---|
| 193 | + const next = [...prev, msg]; |
|---|
| 194 | + setActiveSessionId((id) => { |
|---|
| 195 | + if (id) { |
|---|
| 196 | + messagesMapRef.current[id] = next; |
|---|
| 197 | + debouncedSave(messagesMapRef.current); |
|---|
| 198 | + } |
|---|
| 199 | + return id; |
|---|
| 200 | + }); |
|---|
| 201 | + return next; |
|---|
| 202 | + }); |
|---|
| 203 | + }, []); |
|---|
| 204 | + |
|---|
| 205 | + // Helper: add a message to a specific session (may not be active) |
|---|
| 206 | + const addMessageToSession = useCallback((sessionId: string, msg: Message) => { |
|---|
| 207 | + setActiveSessionId((currentActive) => { |
|---|
| 208 | + if (sessionId === currentActive) { |
|---|
| 209 | + setMessages((prev) => { |
|---|
| 210 | + const next = [...prev, msg]; |
|---|
| 211 | + messagesMapRef.current[sessionId] = next; |
|---|
| 212 | + debouncedSave(messagesMapRef.current); |
|---|
| 213 | + return next; |
|---|
| 214 | + }); |
|---|
| 215 | + } else { |
|---|
| 216 | + const existing = messagesMapRef.current[sessionId] ?? []; |
|---|
| 217 | + messagesMapRef.current[sessionId] = [...existing, msg]; |
|---|
| 218 | + debouncedSave(messagesMapRef.current); |
|---|
| 219 | + setUnreadCounts((u) => ({ |
|---|
| 220 | + ...u, |
|---|
| 221 | + [sessionId]: (u[sessionId] ?? 0) + 1, |
|---|
| 222 | + })); |
|---|
| 223 | + } |
|---|
| 224 | + return currentActive; |
|---|
| 225 | + }); |
|---|
| 48 | 226 | }, []); |
|---|
| 49 | 227 | |
|---|
| 50 | 228 | const updateMessageStatus = useCallback( |
|---|
| .. | .. |
|---|
| 58 | 236 | |
|---|
| 59 | 237 | // Handle incoming WebSocket messages |
|---|
| 60 | 238 | useEffect(() => { |
|---|
| 61 | | - onMessageReceived.current = (data: WsIncoming) => { |
|---|
| 239 | + onMessageReceived.current = async (data: WsIncoming) => { |
|---|
| 62 | 240 | switch (data.type) { |
|---|
| 63 | 241 | case "text": { |
|---|
| 64 | 242 | const msg: Message = { |
|---|
| .. | .. |
|---|
| 69 | 247 | timestamp: Date.now(), |
|---|
| 70 | 248 | status: "sent", |
|---|
| 71 | 249 | }; |
|---|
| 72 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 250 | + addMessageToActive(msg); |
|---|
| 251 | + notifyIncomingMessage("PAILot", data.content ?? "New message"); |
|---|
| 73 | 252 | break; |
|---|
| 74 | 253 | } |
|---|
| 75 | 254 | case "voice": { |
|---|
| 255 | + let audioUri: string | undefined; |
|---|
| 256 | + if (data.audioBase64) { |
|---|
| 257 | + try { |
|---|
| 258 | + audioUri = await saveBase64Audio(data.audioBase64); |
|---|
| 259 | + } catch { |
|---|
| 260 | + // fallback: no playable audio |
|---|
| 261 | + } |
|---|
| 262 | + } |
|---|
| 76 | 263 | const msg: Message = { |
|---|
| 77 | 264 | id: generateId(), |
|---|
| 78 | 265 | role: "assistant", |
|---|
| 79 | 266 | type: "voice", |
|---|
| 80 | 267 | content: data.content ?? "", |
|---|
| 81 | | - audioUri: data.audioBase64 |
|---|
| 82 | | - ? `data:audio/mp4;base64,${data.audioBase64}` |
|---|
| 83 | | - : undefined, |
|---|
| 268 | + audioUri, |
|---|
| 84 | 269 | timestamp: Date.now(), |
|---|
| 85 | 270 | status: "sent", |
|---|
| 86 | 271 | }; |
|---|
| 87 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 272 | + addMessageToActive(msg); |
|---|
| 273 | + notifyIncomingMessage("PAILot", data.content ?? "Voice message"); |
|---|
| 88 | 274 | if (msg.audioUri) { |
|---|
| 89 | 275 | playAudio(msg.audioUri).catch(() => {}); |
|---|
| 90 | 276 | } |
|---|
| 91 | 277 | break; |
|---|
| 92 | 278 | } |
|---|
| 93 | 279 | case "image": { |
|---|
| 94 | | - // Store as latest screenshot for navigation mode |
|---|
| 95 | 280 | setLatestScreenshot(data.imageBase64); |
|---|
| 96 | | - // Also add to chat as an image message |
|---|
| 97 | 281 | const msg: Message = { |
|---|
| 98 | 282 | id: generateId(), |
|---|
| 99 | 283 | role: "assistant", |
|---|
| .. | .. |
|---|
| 103 | 287 | timestamp: Date.now(), |
|---|
| 104 | 288 | status: "sent", |
|---|
| 105 | 289 | }; |
|---|
| 106 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 290 | + addMessageToActive(msg); |
|---|
| 291 | + notifyIncomingMessage("PAILot", data.caption ?? "New image"); |
|---|
| 107 | 292 | break; |
|---|
| 108 | 293 | } |
|---|
| 109 | 294 | case "sessions": { |
|---|
| 110 | | - setSessions(data.sessions); |
|---|
| 295 | + const incoming = data.sessions as WsSession[]; |
|---|
| 296 | + setSessions(incoming); |
|---|
| 297 | + syncActiveFromSessions(incoming); |
|---|
| 298 | + needsSync.current = false; |
|---|
| 111 | 299 | break; |
|---|
| 112 | 300 | } |
|---|
| 113 | 301 | case "session_switched": { |
|---|
| .. | .. |
|---|
| 118 | 306 | content: `Switched to ${data.name}`, |
|---|
| 119 | 307 | timestamp: Date.now(), |
|---|
| 120 | 308 | }; |
|---|
| 121 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 309 | + addMessageToActive(msg); |
|---|
| 310 | + sendCommand("sessions"); |
|---|
| 122 | 311 | break; |
|---|
| 123 | 312 | } |
|---|
| 124 | 313 | case "session_renamed": { |
|---|
| .. | .. |
|---|
| 129 | 318 | content: `Renamed to ${data.name}`, |
|---|
| 130 | 319 | timestamp: Date.now(), |
|---|
| 131 | 320 | }; |
|---|
| 132 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 133 | | - // Refresh sessions to show updated name |
|---|
| 321 | + addMessageToActive(msg); |
|---|
| 134 | 322 | sendCommand("sessions"); |
|---|
| 135 | 323 | break; |
|---|
| 136 | 324 | } |
|---|
| .. | .. |
|---|
| 142 | 330 | content: data.message, |
|---|
| 143 | 331 | timestamp: Date.now(), |
|---|
| 144 | 332 | }; |
|---|
| 145 | | - setMessages((prev) => [...prev, msg]); |
|---|
| 333 | + addMessageToActive(msg); |
|---|
| 146 | 334 | break; |
|---|
| 147 | 335 | } |
|---|
| 148 | 336 | } |
|---|
| .. | .. |
|---|
| 151 | 339 | return () => { |
|---|
| 152 | 340 | onMessageReceived.current = null; |
|---|
| 153 | 341 | }; |
|---|
| 154 | | - }, [onMessageReceived, sendCommand]); |
|---|
| 342 | + }, [onMessageReceived, sendCommand, addMessageToActive, syncActiveFromSessions]); |
|---|
| 155 | 343 | |
|---|
| 156 | 344 | const sendTextMessage = useCallback( |
|---|
| 157 | 345 | (text: string) => { |
|---|
| .. | .. |
|---|
| 164 | 352 | timestamp: Date.now(), |
|---|
| 165 | 353 | status: "sending", |
|---|
| 166 | 354 | }; |
|---|
| 167 | | - addMessage(msg); |
|---|
| 355 | + addMessageToActive(msg); |
|---|
| 168 | 356 | const sent = wsSend(text); |
|---|
| 169 | 357 | updateMessageStatus(id, sent ? "sent" : "error"); |
|---|
| 170 | 358 | }, |
|---|
| 171 | | - [wsSend, addMessage, updateMessageStatus] |
|---|
| 359 | + [wsSend, addMessageToActive, updateMessageStatus] |
|---|
| 172 | 360 | ); |
|---|
| 173 | 361 | |
|---|
| 174 | 362 | const sendVoiceMessage = useCallback( |
|---|
| .. | .. |
|---|
| 184 | 372 | status: "sending", |
|---|
| 185 | 373 | duration: durationMs, |
|---|
| 186 | 374 | }; |
|---|
| 187 | | - addMessage(msg); |
|---|
| 375 | + addMessageToActive(msg); |
|---|
| 188 | 376 | try { |
|---|
| 189 | 377 | const base64 = await encodeAudioToBase64(audioUri); |
|---|
| 190 | 378 | const sent = wsVoice(base64); |
|---|
| .. | .. |
|---|
| 194 | 382 | updateMessageStatus(id, "error"); |
|---|
| 195 | 383 | } |
|---|
| 196 | 384 | }, |
|---|
| 197 | | - [wsVoice, addMessage, updateMessageStatus] |
|---|
| 385 | + [wsVoice, addMessageToActive, updateMessageStatus] |
|---|
| 386 | + ); |
|---|
| 387 | + |
|---|
| 388 | + const sendImageMessage = useCallback( |
|---|
| 389 | + (imageBase64: string, caption: string, mimeType: string) => { |
|---|
| 390 | + const id = generateId(); |
|---|
| 391 | + const msg: Message = { |
|---|
| 392 | + id, |
|---|
| 393 | + role: "user", |
|---|
| 394 | + type: "image", |
|---|
| 395 | + content: caption || "Photo", |
|---|
| 396 | + imageBase64, |
|---|
| 397 | + timestamp: Date.now(), |
|---|
| 398 | + status: "sending", |
|---|
| 399 | + }; |
|---|
| 400 | + addMessageToActive(msg); |
|---|
| 401 | + const sent = wsImageSend(imageBase64, caption, mimeType); |
|---|
| 402 | + updateMessageStatus(id, sent ? "sent" : "error"); |
|---|
| 403 | + }, |
|---|
| 404 | + [wsImageSend, addMessageToActive, updateMessageStatus] |
|---|
| 198 | 405 | ); |
|---|
| 199 | 406 | |
|---|
| 200 | 407 | const clearMessages = useCallback(() => { |
|---|
| 201 | 408 | setMessages([]); |
|---|
| 409 | + setActiveSessionId((id) => { |
|---|
| 410 | + if (id) { |
|---|
| 411 | + messagesMapRef.current[id] = []; |
|---|
| 412 | + clearPersistedMessages(id); |
|---|
| 413 | + } |
|---|
| 414 | + return id; |
|---|
| 415 | + }); |
|---|
| 202 | 416 | }, []); |
|---|
| 203 | 417 | |
|---|
| 204 | 418 | // --- Session management --- |
|---|
| .. | .. |
|---|
| 208 | 422 | |
|---|
| 209 | 423 | const switchSession = useCallback( |
|---|
| 210 | 424 | (sessionId: string) => { |
|---|
| 425 | + setActiveSessionId((prev) => { |
|---|
| 426 | + if (prev) { |
|---|
| 427 | + messagesMapRef.current[prev] = messages; |
|---|
| 428 | + debouncedSave(messagesMapRef.current); |
|---|
| 429 | + } |
|---|
| 430 | + return prev; |
|---|
| 431 | + }); |
|---|
| 211 | 432 | sendCommand("switch", { sessionId }); |
|---|
| 212 | 433 | }, |
|---|
| 213 | | - [sendCommand] |
|---|
| 434 | + [sendCommand, messages] |
|---|
| 214 | 435 | ); |
|---|
| 215 | 436 | |
|---|
| 216 | 437 | const renameSession = useCallback( |
|---|
| .. | .. |
|---|
| 219 | 440 | }, |
|---|
| 220 | 441 | [sendCommand] |
|---|
| 221 | 442 | ); |
|---|
| 443 | + |
|---|
| 444 | + const removeSession = useCallback( |
|---|
| 445 | + (sessionId: string) => { |
|---|
| 446 | + sendCommand("remove", { sessionId }); |
|---|
| 447 | + delete messagesMapRef.current[sessionId]; |
|---|
| 448 | + deletePersistedSession(sessionId); |
|---|
| 449 | + setUnreadCounts((u) => { |
|---|
| 450 | + if (!u[sessionId]) return u; |
|---|
| 451 | + const next = { ...u }; |
|---|
| 452 | + delete next[sessionId]; |
|---|
| 453 | + return next; |
|---|
| 454 | + }); |
|---|
| 455 | + }, |
|---|
| 456 | + [sendCommand] |
|---|
| 457 | + ); |
|---|
| 458 | + |
|---|
| 459 | + const createSession = useCallback(() => { |
|---|
| 460 | + sendCommand("create"); |
|---|
| 461 | + }, [sendCommand]); |
|---|
| 222 | 462 | |
|---|
| 223 | 463 | // --- Screenshot / navigation --- |
|---|
| 224 | 464 | const requestScreenshot = useCallback(() => { |
|---|
| .. | .. |
|---|
| 238 | 478 | messages, |
|---|
| 239 | 479 | sendTextMessage, |
|---|
| 240 | 480 | sendVoiceMessage, |
|---|
| 481 | + sendImageMessage, |
|---|
| 241 | 482 | clearMessages, |
|---|
| 242 | 483 | sessions, |
|---|
| 484 | + activeSessionId, |
|---|
| 243 | 485 | requestSessions, |
|---|
| 244 | 486 | switchSession, |
|---|
| 245 | 487 | renameSession, |
|---|
| 488 | + removeSession, |
|---|
| 489 | + createSession, |
|---|
| 490 | + unreadCounts, |
|---|
| 246 | 491 | latestScreenshot, |
|---|
| 247 | 492 | requestScreenshot, |
|---|
| 248 | 493 | sendNavKey, |
|---|
| .. | .. |
|---|
| 14 | 14 | WsOutgoing, |
|---|
| 15 | 15 | } from "../types"; |
|---|
| 16 | 16 | import { wsClient } from "../services/websocket"; |
|---|
| 17 | +import { sendWol, isValidMac } from "../services/wol"; |
|---|
| 17 | 18 | |
|---|
| 18 | 19 | const SECURE_STORE_KEY = "pailot_server_config"; |
|---|
| 19 | 20 | |
|---|
| .. | .. |
|---|
| 24 | 25 | disconnect: () => void; |
|---|
| 25 | 26 | sendTextMessage: (text: string) => boolean; |
|---|
| 26 | 27 | sendVoiceMessage: (audioBase64: string, transcript?: string) => boolean; |
|---|
| 28 | + sendImageMessage: (imageBase64: string, caption: string, mimeType: string) => boolean; |
|---|
| 27 | 29 | sendCommand: (command: string, args?: Record<string, unknown>) => boolean; |
|---|
| 28 | 30 | saveServerConfig: (config: ServerConfig) => Promise<void>; |
|---|
| 29 | 31 | onMessageReceived: React.MutableRefObject< |
|---|
| .. | .. |
|---|
| 52 | 54 | onClose: () => setStatus("disconnected"), |
|---|
| 53 | 55 | onError: () => setStatus("disconnected"), |
|---|
| 54 | 56 | onMessage: (data) => { |
|---|
| 55 | | - onMessageReceived.current?.(data as WsIncoming); |
|---|
| 57 | + const msg = data as unknown as WsIncoming; |
|---|
| 58 | + // Handle server-side status changes (compaction indicator) |
|---|
| 59 | + if (msg.type === "status") { |
|---|
| 60 | + if (msg.status === "compacting") setStatus("compacting"); |
|---|
| 61 | + else if (msg.status === "online") setStatus("connected"); |
|---|
| 62 | + return; |
|---|
| 63 | + } |
|---|
| 64 | + onMessageReceived.current?.(msg); |
|---|
| 56 | 65 | }, |
|---|
| 57 | 66 | }); |
|---|
| 58 | 67 | }, []); |
|---|
| .. | .. |
|---|
| 70 | 79 | } |
|---|
| 71 | 80 | } |
|---|
| 72 | 81 | |
|---|
| 73 | | - function connectToServer(config: ServerConfig) { |
|---|
| 82 | + async function connectToServer(config: ServerConfig) { |
|---|
| 74 | 83 | setStatus("connecting"); |
|---|
| 75 | | - const url = `ws://${config.host}:${config.port}`; |
|---|
| 76 | | - wsClient.connect(url); |
|---|
| 84 | + |
|---|
| 85 | + // Fire-and-forget WoL — never block the WebSocket connection |
|---|
| 86 | + if (config.macAddress && isValidMac(config.macAddress)) { |
|---|
| 87 | + sendWol(config.macAddress, config.host).catch(() => {}); |
|---|
| 88 | + } |
|---|
| 89 | + |
|---|
| 90 | + // Build URL list: local first (preferred), then remote |
|---|
| 91 | + const urls: string[] = []; |
|---|
| 92 | + if (config.localHost) { |
|---|
| 93 | + urls.push(`ws://${config.localHost}:${config.port}`); |
|---|
| 94 | + } |
|---|
| 95 | + urls.push(`ws://${config.host}:${config.port}`); |
|---|
| 96 | + wsClient.connect(urls); |
|---|
| 77 | 97 | } |
|---|
| 78 | 98 | |
|---|
| 79 | 99 | const connect = useCallback( |
|---|
| .. | .. |
|---|
| 110 | 130 | [] |
|---|
| 111 | 131 | ); |
|---|
| 112 | 132 | |
|---|
| 133 | + const sendImageMessage = useCallback( |
|---|
| 134 | + (imageBase64: string, caption: string = "", mimeType: string = "image/jpeg"): boolean => { |
|---|
| 135 | + return wsClient.send({ type: "image", imageBase64, caption, mimeType }); |
|---|
| 136 | + }, |
|---|
| 137 | + [] |
|---|
| 138 | + ); |
|---|
| 139 | + |
|---|
| 113 | 140 | const sendCommand = useCallback( |
|---|
| 114 | 141 | (command: string, args?: Record<string, unknown>): boolean => { |
|---|
| 115 | 142 | const msg: WsOutgoing = { type: "command", command, args }; |
|---|
| .. | .. |
|---|
| 127 | 154 | disconnect, |
|---|
| 128 | 155 | sendTextMessage, |
|---|
| 129 | 156 | sendVoiceMessage, |
|---|
| 157 | + sendImageMessage, |
|---|
| 130 | 158 | sendCommand, |
|---|
| 131 | 159 | saveServerConfig, |
|---|
| 132 | 160 | onMessageReceived, |
|---|
| .. | .. |
|---|
| 1 | +import React, { createContext, useCallback, useContext, useEffect, useState } from "react"; |
|---|
| 2 | +import { useColorScheme } from "react-native"; |
|---|
| 3 | +import * as SecureStore from "expo-secure-store"; |
|---|
| 4 | + |
|---|
| 5 | +const THEME_KEY = "pailot_theme"; |
|---|
| 6 | + |
|---|
| 7 | +type ThemeMode = "light" | "dark" | "system"; |
|---|
| 8 | + |
|---|
| 9 | +export interface ThemeColors { |
|---|
| 10 | + bg: string; |
|---|
| 11 | + bgSecondary: string; |
|---|
| 12 | + bgTertiary: string; |
|---|
| 13 | + text: string; |
|---|
| 14 | + textSecondary: string; |
|---|
| 15 | + textMuted: string; |
|---|
| 16 | + border: string; |
|---|
| 17 | + accent: string; |
|---|
| 18 | + accentBg: string; |
|---|
| 19 | + danger: string; |
|---|
| 20 | +} |
|---|
| 21 | + |
|---|
| 22 | +const darkColors: ThemeColors = { |
|---|
| 23 | + bg: "#0A0A0F", |
|---|
| 24 | + bgSecondary: "#14141F", |
|---|
| 25 | + bgTertiary: "#1E1E2E", |
|---|
| 26 | + text: "#E8E8F0", |
|---|
| 27 | + textSecondary: "#9898B0", |
|---|
| 28 | + textMuted: "#5A5A78", |
|---|
| 29 | + border: "#2E2E45", |
|---|
| 30 | + accent: "#4A9EFF", |
|---|
| 31 | + accentBg: "#4A9EFF18", |
|---|
| 32 | + danger: "#FF3B30", |
|---|
| 33 | +}; |
|---|
| 34 | + |
|---|
| 35 | +const lightColors: ThemeColors = { |
|---|
| 36 | + bg: "#FFFFFF", |
|---|
| 37 | + bgSecondary: "#F5F5F7", |
|---|
| 38 | + bgTertiary: "#EEEEF0", |
|---|
| 39 | + text: "#1C1C1E", |
|---|
| 40 | + textSecondary: "#636366", |
|---|
| 41 | + textMuted: "#AEAEB2", |
|---|
| 42 | + border: "#D1D1D6", |
|---|
| 43 | + accent: "#007AFF", |
|---|
| 44 | + accentBg: "#007AFF14", |
|---|
| 45 | + danger: "#FF3B30", |
|---|
| 46 | +}; |
|---|
| 47 | + |
|---|
| 48 | +interface ThemeContextValue { |
|---|
| 49 | + mode: ThemeMode; |
|---|
| 50 | + isDark: boolean; |
|---|
| 51 | + colors: ThemeColors; |
|---|
| 52 | + setMode: (mode: ThemeMode) => void; |
|---|
| 53 | + cycleMode: () => void; |
|---|
| 54 | +} |
|---|
| 55 | + |
|---|
| 56 | +const ThemeContext = createContext<ThemeContextValue | null>(null); |
|---|
| 57 | + |
|---|
| 58 | +export function ThemeProvider({ children }: { children: React.ReactNode }) { |
|---|
| 59 | + const systemScheme = useColorScheme(); |
|---|
| 60 | + const [mode, setModeState] = useState<ThemeMode>("dark"); |
|---|
| 61 | + |
|---|
| 62 | + useEffect(() => { |
|---|
| 63 | + SecureStore.getItemAsync(THEME_KEY).then((stored) => { |
|---|
| 64 | + if (stored === "light" || stored === "dark" || stored === "system") { |
|---|
| 65 | + setModeState(stored); |
|---|
| 66 | + } |
|---|
| 67 | + }); |
|---|
| 68 | + }, []); |
|---|
| 69 | + |
|---|
| 70 | + const setMode = useCallback((m: ThemeMode) => { |
|---|
| 71 | + setModeState(m); |
|---|
| 72 | + SecureStore.setItemAsync(THEME_KEY, m); |
|---|
| 73 | + }, []); |
|---|
| 74 | + |
|---|
| 75 | + const cycleMode = useCallback(() => { |
|---|
| 76 | + setModeState((prev) => { |
|---|
| 77 | + const next = prev === "dark" ? "light" : prev === "light" ? "system" : "dark"; |
|---|
| 78 | + SecureStore.setItemAsync(THEME_KEY, next); |
|---|
| 79 | + return next; |
|---|
| 80 | + }); |
|---|
| 81 | + }, []); |
|---|
| 82 | + |
|---|
| 83 | + const isDark = mode === "dark" || (mode === "system" && systemScheme !== "light"); |
|---|
| 84 | + const colors = isDark ? darkColors : lightColors; |
|---|
| 85 | + |
|---|
| 86 | + return ( |
|---|
| 87 | + <ThemeContext.Provider value={{ mode, isDark, colors, setMode, cycleMode }}> |
|---|
| 88 | + {children} |
|---|
| 89 | + </ThemeContext.Provider> |
|---|
| 90 | + ); |
|---|
| 91 | +} |
|---|
| 92 | + |
|---|
| 93 | +export function useTheme() { |
|---|
| 94 | + const ctx = useContext(ThemeContext); |
|---|
| 95 | + if (!ctx) throw new Error("useTheme must be used within ThemeProvider"); |
|---|
| 96 | + return ctx; |
|---|
| 97 | +} |
|---|
| .. | .. |
|---|
| 1 | +# Memory |
|---|
| 2 | + |
|---|
| 3 | +Project-specific memory for PAI sessions. |
|---|
| 4 | +Add persistent notes, reminders, and context here. |
|---|
| .. | .. |
|---|
| 15 | 15 | "expo-constants": "~55.0.7", |
|---|
| 16 | 16 | "expo-file-system": "~55.0.10", |
|---|
| 17 | 17 | "expo-haptics": "~55.0.8", |
|---|
| 18 | + "expo-image-picker": "~55.0.11", |
|---|
| 18 | 19 | "expo-linking": "~55.0.7", |
|---|
| 19 | 20 | "expo-router": "~55.0.3", |
|---|
| 20 | 21 | "expo-secure-store": "~55.0.8", |
|---|
| 21 | | - "expo-speech-recognition": "^3.1.1", |
|---|
| 22 | + "expo-sharing": "~55.0.11", |
|---|
| 22 | 23 | "expo-splash-screen": "~55.0.10", |
|---|
| 23 | 24 | "expo-status-bar": "~55.0.4", |
|---|
| 24 | 25 | "expo-system-ui": "~55.0.9", |
|---|
| .. | .. |
|---|
| 27 | 28 | "react": "19.2.0", |
|---|
| 28 | 29 | "react-dom": "^19.2.4", |
|---|
| 29 | 30 | "react-native": "0.83.2", |
|---|
| 31 | + "react-native-draggable-flatlist": "^4.0.3", |
|---|
| 30 | 32 | "react-native-gesture-handler": "~2.30.0", |
|---|
| 31 | 33 | "react-native-reanimated": "4.2.1", |
|---|
| 32 | 34 | "react-native-safe-area-context": "~5.6.2", |
|---|
| 33 | 35 | "react-native-screens": "~4.23.0", |
|---|
| 34 | 36 | "react-native-svg": "15.15.3", |
|---|
| 37 | + "react-native-udp": "^4.1.7", |
|---|
| 35 | 38 | "react-native-web": "^0.21.0", |
|---|
| 36 | 39 | "react-native-worklets": "0.7.2" |
|---|
| 37 | 40 | }, |
|---|
| .. | .. |
|---|
| 3764 | 3767 | "node-int64": "^0.4.0" |
|---|
| 3765 | 3768 | } |
|---|
| 3766 | 3769 | }, |
|---|
| 3770 | + "node_modules/buffer": { |
|---|
| 3771 | + "version": "5.7.1", |
|---|
| 3772 | + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", |
|---|
| 3773 | + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", |
|---|
| 3774 | + "funding": [ |
|---|
| 3775 | + { |
|---|
| 3776 | + "type": "github", |
|---|
| 3777 | + "url": "https://github.com/sponsors/feross" |
|---|
| 3778 | + }, |
|---|
| 3779 | + { |
|---|
| 3780 | + "type": "patreon", |
|---|
| 3781 | + "url": "https://www.patreon.com/feross" |
|---|
| 3782 | + }, |
|---|
| 3783 | + { |
|---|
| 3784 | + "type": "consulting", |
|---|
| 3785 | + "url": "https://feross.org/support" |
|---|
| 3786 | + } |
|---|
| 3787 | + ], |
|---|
| 3788 | + "license": "MIT", |
|---|
| 3789 | + "dependencies": { |
|---|
| 3790 | + "base64-js": "^1.3.1", |
|---|
| 3791 | + "ieee754": "^1.1.13" |
|---|
| 3792 | + } |
|---|
| 3793 | + }, |
|---|
| 3767 | 3794 | "node_modules/buffer-from": { |
|---|
| 3768 | 3795 | "version": "1.1.2", |
|---|
| 3769 | 3796 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", |
|---|
| .. | .. |
|---|
| 4518 | 4545 | "node": ">=6" |
|---|
| 4519 | 4546 | } |
|---|
| 4520 | 4547 | }, |
|---|
| 4548 | + "node_modules/events": { |
|---|
| 4549 | + "version": "3.3.0", |
|---|
| 4550 | + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", |
|---|
| 4551 | + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", |
|---|
| 4552 | + "license": "MIT", |
|---|
| 4553 | + "engines": { |
|---|
| 4554 | + "node": ">=0.8.x" |
|---|
| 4555 | + } |
|---|
| 4556 | + }, |
|---|
| 4521 | 4557 | "node_modules/expo": { |
|---|
| 4522 | 4558 | "version": "55.0.4", |
|---|
| 4523 | 4559 | "resolved": "https://registry.npmjs.org/expo/-/expo-55.0.4.tgz", |
|---|
| .. | .. |
|---|
| 4660 | 4696 | "react-native-web": { |
|---|
| 4661 | 4697 | "optional": true |
|---|
| 4662 | 4698 | } |
|---|
| 4699 | + } |
|---|
| 4700 | + }, |
|---|
| 4701 | + "node_modules/expo-image-loader": { |
|---|
| 4702 | + "version": "55.0.0", |
|---|
| 4703 | + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-55.0.0.tgz", |
|---|
| 4704 | + "integrity": "sha512-NOjp56wDrfuA5aiNAybBIjqIn1IxKeGJ8CECWZncQ/GzjZfyTYAHTCyeApYkdKkMBLHINzI4BbTGSlbCa0fXXQ==", |
|---|
| 4705 | + "license": "MIT", |
|---|
| 4706 | + "peerDependencies": { |
|---|
| 4707 | + "expo": "*" |
|---|
| 4708 | + } |
|---|
| 4709 | + }, |
|---|
| 4710 | + "node_modules/expo-image-picker": { |
|---|
| 4711 | + "version": "55.0.11", |
|---|
| 4712 | + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-55.0.11.tgz", |
|---|
| 4713 | + "integrity": "sha512-geJklIGdAR2N16iSk86oyJe7QgX5RpqDX1FjKpxO53fF4D0eBmg5Irm6gRwT0b+DHP1kJevZgzzbVJsRAV362g==", |
|---|
| 4714 | + "license": "MIT", |
|---|
| 4715 | + "dependencies": { |
|---|
| 4716 | + "expo-image-loader": "~55.0.0" |
|---|
| 4717 | + }, |
|---|
| 4718 | + "peerDependencies": { |
|---|
| 4719 | + "expo": "*" |
|---|
| 4663 | 4720 | } |
|---|
| 4664 | 4721 | }, |
|---|
| 4665 | 4722 | "node_modules/expo-linking": { |
|---|
| .. | .. |
|---|
| 4863 | 4920 | "node": ">=20.16.0" |
|---|
| 4864 | 4921 | } |
|---|
| 4865 | 4922 | }, |
|---|
| 4866 | | - "node_modules/expo-speech-recognition": { |
|---|
| 4867 | | - "version": "3.1.1", |
|---|
| 4868 | | - "resolved": "https://registry.npmjs.org/expo-speech-recognition/-/expo-speech-recognition-3.1.1.tgz", |
|---|
| 4869 | | - "integrity": "sha512-+1rviv+ZecAokY8PUfr3XJuhS4t0uKccewIPPUk5ooeEt5xKEWr6XYpKm3ggapPdJQbgMTjWbmSPT1ahTMyIqA==", |
|---|
| 4923 | + "node_modules/expo-sharing": { |
|---|
| 4924 | + "version": "55.0.11", |
|---|
| 4925 | + "resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-55.0.11.tgz", |
|---|
| 4926 | + "integrity": "sha512-YlVez832W0sYR2KJY4Dr8ON9aC+Wp8a/r40eQyhoHT9Tetkr2KBM7tWLT0CGKRuTTnrqJL1C51UacLkHJ9zmNA==", |
|---|
| 4870 | 4927 | "license": "MIT", |
|---|
| 4928 | + "dependencies": { |
|---|
| 4929 | + "@expo/config-plugins": "^55.0.6", |
|---|
| 4930 | + "@expo/config-types": "^55.0.5", |
|---|
| 4931 | + "@expo/plist": "^0.5.2" |
|---|
| 4932 | + }, |
|---|
| 4871 | 4933 | "peerDependencies": { |
|---|
| 4872 | 4934 | "expo": "*", |
|---|
| 4873 | 4935 | "react": "*", |
|---|
| .. | .. |
|---|
| 5623 | 5685 | "version": "1.1.0", |
|---|
| 5624 | 5686 | "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", |
|---|
| 5625 | 5687 | "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", |
|---|
| 5688 | + "license": "BSD-3-Clause" |
|---|
| 5689 | + }, |
|---|
| 5690 | + "node_modules/ieee754": { |
|---|
| 5691 | + "version": "1.2.1", |
|---|
| 5692 | + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", |
|---|
| 5693 | + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", |
|---|
| 5694 | + "funding": [ |
|---|
| 5695 | + { |
|---|
| 5696 | + "type": "github", |
|---|
| 5697 | + "url": "https://github.com/sponsors/feross" |
|---|
| 5698 | + }, |
|---|
| 5699 | + { |
|---|
| 5700 | + "type": "patreon", |
|---|
| 5701 | + "url": "https://www.patreon.com/feross" |
|---|
| 5702 | + }, |
|---|
| 5703 | + { |
|---|
| 5704 | + "type": "consulting", |
|---|
| 5705 | + "url": "https://feross.org/support" |
|---|
| 5706 | + } |
|---|
| 5707 | + ], |
|---|
| 5626 | 5708 | "license": "BSD-3-Clause" |
|---|
| 5627 | 5709 | }, |
|---|
| 5628 | 5710 | "node_modules/ignore": { |
|---|
| .. | .. |
|---|
| 8180 | 8262 | "url": "https://opencollective.com/parcel" |
|---|
| 8181 | 8263 | } |
|---|
| 8182 | 8264 | }, |
|---|
| 8265 | + "node_modules/react-native-draggable-flatlist": { |
|---|
| 8266 | + "version": "4.0.3", |
|---|
| 8267 | + "resolved": "https://registry.npmjs.org/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.3.tgz", |
|---|
| 8268 | + "integrity": "sha512-2F4x5BFieWdGq9SetD2nSAR7s7oQCSgNllYgERRXXtNfSOuAGAVbDb/3H3lP0y5f7rEyNwabKorZAD/SyyNbDw==", |
|---|
| 8269 | + "license": "MIT", |
|---|
| 8270 | + "dependencies": { |
|---|
| 8271 | + "@babel/preset-typescript": "^7.17.12" |
|---|
| 8272 | + }, |
|---|
| 8273 | + "peerDependencies": { |
|---|
| 8274 | + "react-native": ">=0.64.0", |
|---|
| 8275 | + "react-native-gesture-handler": ">=2.0.0", |
|---|
| 8276 | + "react-native-reanimated": ">=2.8.0" |
|---|
| 8277 | + } |
|---|
| 8278 | + }, |
|---|
| 8183 | 8279 | "node_modules/react-native-gesture-handler": { |
|---|
| 8184 | 8280 | "version": "2.30.0", |
|---|
| 8185 | 8281 | "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.30.0.tgz", |
|---|
| .. | .. |
|---|
| 8271 | 8367 | "react-native": "*" |
|---|
| 8272 | 8368 | } |
|---|
| 8273 | 8369 | }, |
|---|
| 8370 | + "node_modules/react-native-udp": { |
|---|
| 8371 | + "version": "4.1.7", |
|---|
| 8372 | + "resolved": "https://registry.npmjs.org/react-native-udp/-/react-native-udp-4.1.7.tgz", |
|---|
| 8373 | + "integrity": "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA==", |
|---|
| 8374 | + "license": "MIT", |
|---|
| 8375 | + "dependencies": { |
|---|
| 8376 | + "buffer": "^5.6.0", |
|---|
| 8377 | + "events": "^3.1.0" |
|---|
| 8378 | + } |
|---|
| 8379 | + }, |
|---|
| 8274 | 8380 | "node_modules/react-native-web": { |
|---|
| 8275 | 8381 | "version": "0.21.2", |
|---|
| 8276 | 8382 | "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", |
|---|
| .. | .. |
|---|
| 16 | 16 | "expo-constants": "~55.0.7", |
|---|
| 17 | 17 | "expo-file-system": "~55.0.10", |
|---|
| 18 | 18 | "expo-haptics": "~55.0.8", |
|---|
| 19 | + "expo-image-picker": "~55.0.11", |
|---|
| 19 | 20 | "expo-linking": "~55.0.7", |
|---|
| 20 | 21 | "expo-router": "~55.0.3", |
|---|
| 21 | 22 | "expo-secure-store": "~55.0.8", |
|---|
| 22 | | - "expo-speech-recognition": "^3.1.1", |
|---|
| 23 | + "expo-sharing": "~55.0.11", |
|---|
| 23 | 24 | "expo-splash-screen": "~55.0.10", |
|---|
| 24 | 25 | "expo-status-bar": "~55.0.4", |
|---|
| 25 | 26 | "expo-system-ui": "~55.0.9", |
|---|
| .. | .. |
|---|
| 28 | 29 | "react": "19.2.0", |
|---|
| 29 | 30 | "react-dom": "^19.2.4", |
|---|
| 30 | 31 | "react-native": "0.83.2", |
|---|
| 32 | + "react-native-draggable-flatlist": "^4.0.3", |
|---|
| 31 | 33 | "react-native-gesture-handler": "~2.30.0", |
|---|
| 32 | 34 | "react-native-reanimated": "4.2.1", |
|---|
| 33 | 35 | "react-native-safe-area-context": "~5.6.2", |
|---|
| 34 | 36 | "react-native-screens": "~4.23.0", |
|---|
| 35 | 37 | "react-native-svg": "15.15.3", |
|---|
| 38 | + "react-native-udp": "^4.1.7", |
|---|
| 36 | 39 | "react-native-web": "^0.21.0", |
|---|
| 37 | 40 | "react-native-worklets": "0.7.2" |
|---|
| 38 | 41 | }, |
|---|
| .. | .. |
|---|
| 3 | 3 | requestRecordingPermissionsAsync, |
|---|
| 4 | 4 | setAudioModeAsync, |
|---|
| 5 | 5 | } from "expo-audio"; |
|---|
| 6 | +import * as LegacyFileSystem from "expo-file-system/legacy"; |
|---|
| 6 | 7 | |
|---|
| 7 | 8 | export interface RecordingResult { |
|---|
| 8 | 9 | uri: string; |
|---|
| .. | .. |
|---|
| 10 | 11 | } |
|---|
| 11 | 12 | |
|---|
| 12 | 13 | let currentPlayer: ReturnType<typeof createAudioPlayer> | null = null; |
|---|
| 14 | +const playingListeners = new Set<(playing: boolean) => void>(); |
|---|
| 15 | + |
|---|
| 16 | +// Audio queue for chaining sequential voice notes |
|---|
| 17 | +const audioQueue: Array<{ uri: string; onFinish?: () => void }> = []; |
|---|
| 18 | +let processingQueue = false; |
|---|
| 19 | + |
|---|
| 20 | +function notifyListeners(playing: boolean): void { |
|---|
| 21 | + for (const cb of playingListeners) cb(playing); |
|---|
| 22 | +} |
|---|
| 23 | + |
|---|
| 24 | +export function onPlayingChange(cb: (playing: boolean) => void): () => void { |
|---|
| 25 | + playingListeners.add(cb); |
|---|
| 26 | + return () => { playingListeners.delete(cb); }; |
|---|
| 27 | +} |
|---|
| 13 | 28 | |
|---|
| 14 | 29 | export async function requestPermissions(): Promise<boolean> { |
|---|
| 15 | 30 | const { status } = await requestRecordingPermissionsAsync(); |
|---|
| 16 | 31 | return status === "granted"; |
|---|
| 17 | 32 | } |
|---|
| 18 | 33 | |
|---|
| 34 | +let audioCounter = 0; |
|---|
| 35 | + |
|---|
| 36 | +/** |
|---|
| 37 | + * Convert a base64 audio string to a file URI. |
|---|
| 38 | + */ |
|---|
| 39 | +export async function saveBase64Audio(base64: string, ext = "m4a"): Promise<string> { |
|---|
| 40 | + const tmpPath = `${LegacyFileSystem.cacheDirectory}pailot-voice-${++audioCounter}.${ext}`; |
|---|
| 41 | + await LegacyFileSystem.writeAsStringAsync(tmpPath, base64, { |
|---|
| 42 | + encoding: LegacyFileSystem.EncodingType.Base64, |
|---|
| 43 | + }); |
|---|
| 44 | + return tmpPath; |
|---|
| 45 | +} |
|---|
| 46 | + |
|---|
| 47 | +/** |
|---|
| 48 | + * Queue audio for playback. Multiple calls chain sequentially — |
|---|
| 49 | + * the next voice note plays only after the current one finishes. |
|---|
| 50 | + */ |
|---|
| 19 | 51 | export async function playAudio( |
|---|
| 20 | 52 | uri: string, |
|---|
| 21 | 53 | onFinish?: () => void |
|---|
| 22 | 54 | ): Promise<void> { |
|---|
| 23 | | - try { |
|---|
| 24 | | - await stopPlayback(); |
|---|
| 25 | | - |
|---|
| 26 | | - await setAudioModeAsync({ |
|---|
| 27 | | - playsInSilentMode: true, |
|---|
| 28 | | - }); |
|---|
| 29 | | - |
|---|
| 30 | | - const player = createAudioPlayer(uri); |
|---|
| 31 | | - currentPlayer = player; |
|---|
| 32 | | - |
|---|
| 33 | | - player.addListener("playbackStatusUpdate", (status) => { |
|---|
| 34 | | - if (!status.playing && status.currentTime >= status.duration && status.duration > 0) { |
|---|
| 35 | | - onFinish?.(); |
|---|
| 36 | | - player.remove(); |
|---|
| 37 | | - if (currentPlayer === player) currentPlayer = null; |
|---|
| 38 | | - } |
|---|
| 39 | | - }); |
|---|
| 40 | | - |
|---|
| 41 | | - player.play(); |
|---|
| 42 | | - } catch (error) { |
|---|
| 43 | | - console.error("Failed to play audio:", error); |
|---|
| 55 | + audioQueue.push({ uri, onFinish }); |
|---|
| 56 | + if (!processingQueue) { |
|---|
| 57 | + processAudioQueue(); |
|---|
| 44 | 58 | } |
|---|
| 45 | 59 | } |
|---|
| 46 | 60 | |
|---|
| 61 | +async function processAudioQueue(): Promise<void> { |
|---|
| 62 | + if (processingQueue) return; |
|---|
| 63 | + processingQueue = true; |
|---|
| 64 | + |
|---|
| 65 | + while (audioQueue.length > 0) { |
|---|
| 66 | + const item = audioQueue.shift()!; |
|---|
| 67 | + await playOneAudio(item.uri, item.onFinish); |
|---|
| 68 | + } |
|---|
| 69 | + |
|---|
| 70 | + processingQueue = false; |
|---|
| 71 | +} |
|---|
| 72 | + |
|---|
| 73 | +function playOneAudio(uri: string, onFinish?: () => void): Promise<void> { |
|---|
| 74 | + return new Promise<void>(async (resolve) => { |
|---|
| 75 | + try { |
|---|
| 76 | + await setAudioModeAsync({ playsInSilentMode: true }); |
|---|
| 77 | + |
|---|
| 78 | + const player = createAudioPlayer(uri); |
|---|
| 79 | + currentPlayer = player; |
|---|
| 80 | + notifyListeners(true); |
|---|
| 81 | + |
|---|
| 82 | + player.addListener("playbackStatusUpdate", (status) => { |
|---|
| 83 | + if (!status.playing && status.currentTime >= status.duration && status.duration > 0) { |
|---|
| 84 | + onFinish?.(); |
|---|
| 85 | + player.remove(); |
|---|
| 86 | + if (currentPlayer === player) { |
|---|
| 87 | + currentPlayer = null; |
|---|
| 88 | + if (audioQueue.length === 0) notifyListeners(false); |
|---|
| 89 | + } |
|---|
| 90 | + resolve(); |
|---|
| 91 | + } |
|---|
| 92 | + }); |
|---|
| 93 | + |
|---|
| 94 | + player.play(); |
|---|
| 95 | + } catch (error) { |
|---|
| 96 | + console.error("Failed to play audio:", error); |
|---|
| 97 | + resolve(); |
|---|
| 98 | + } |
|---|
| 99 | + }); |
|---|
| 100 | +} |
|---|
| 101 | + |
|---|
| 102 | +export function isPlaying(): boolean { |
|---|
| 103 | + return currentPlayer !== null; |
|---|
| 104 | +} |
|---|
| 105 | + |
|---|
| 106 | +/** |
|---|
| 107 | + * Stop current playback and clear the queue. |
|---|
| 108 | + */ |
|---|
| 47 | 109 | export async function stopPlayback(): Promise<void> { |
|---|
| 110 | + audioQueue.length = 0; |
|---|
| 48 | 111 | if (currentPlayer) { |
|---|
| 49 | 112 | try { |
|---|
| 50 | 113 | currentPlayer.pause(); |
|---|
| .. | .. |
|---|
| 53 | 116 | // Ignore cleanup errors |
|---|
| 54 | 117 | } |
|---|
| 55 | 118 | currentPlayer = null; |
|---|
| 119 | + notifyListeners(false); |
|---|
| 56 | 120 | } |
|---|
| 57 | 121 | } |
|---|
| 58 | 122 | |
|---|
| 59 | 123 | export async function encodeAudioToBase64(uri: string): Promise<string> { |
|---|
| 60 | | - const FileSystem = await import("expo-file-system"); |
|---|
| 61 | | - const result = await FileSystem.readAsStringAsync(uri, { |
|---|
| 62 | | - encoding: FileSystem.EncodingType.Base64, |
|---|
| 124 | + const result = await LegacyFileSystem.readAsStringAsync(uri, { |
|---|
| 125 | + encoding: LegacyFileSystem.EncodingType.Base64, |
|---|
| 63 | 126 | }); |
|---|
| 64 | 127 | return result; |
|---|
| 65 | 128 | } |
|---|
| .. | .. |
|---|
| 1 | +/** |
|---|
| 2 | + * Local push notifications for background message delivery. |
|---|
| 3 | + * |
|---|
| 4 | + * Uses a minimal Objective-C native module (ios/LocalNotifications/) that wraps |
|---|
| 5 | + * UNUserNotificationCenter directly. No aps-environment entitlement needed. |
|---|
| 6 | + */ |
|---|
| 7 | +import { AppState, NativeModules } from "react-native"; |
|---|
| 8 | + |
|---|
| 9 | +const { LocalNotifications } = NativeModules; |
|---|
| 10 | + |
|---|
| 11 | +let permissionGranted = false; |
|---|
| 12 | + |
|---|
| 13 | +/** Request notification permissions. Call once at app startup. */ |
|---|
| 14 | +export async function requestNotificationPermissions(): Promise<boolean> { |
|---|
| 15 | + try { |
|---|
| 16 | + if (!LocalNotifications) return false; |
|---|
| 17 | + permissionGranted = await LocalNotifications.requestPermissions(); |
|---|
| 18 | + } catch { |
|---|
| 19 | + permissionGranted = false; |
|---|
| 20 | + } |
|---|
| 21 | + return permissionGranted; |
|---|
| 22 | +} |
|---|
| 23 | + |
|---|
| 24 | +/** Returns true if the app is currently in the background or inactive. */ |
|---|
| 25 | +export function isAppBackgrounded(): boolean { |
|---|
| 26 | + return AppState.currentState !== "active"; |
|---|
| 27 | +} |
|---|
| 28 | + |
|---|
| 29 | +/** Fire a local notification for an incoming message. */ |
|---|
| 30 | +export async function notifyIncomingMessage( |
|---|
| 31 | + title: string, |
|---|
| 32 | + body: string, |
|---|
| 33 | +): Promise<void> { |
|---|
| 34 | + if (!permissionGranted || !isAppBackgrounded() || !LocalNotifications) return; |
|---|
| 35 | + try { |
|---|
| 36 | + await LocalNotifications.notify(title, body); |
|---|
| 37 | + } catch { |
|---|
| 38 | + // Best-effort |
|---|
| 39 | + } |
|---|
| 40 | +} |
|---|
| .. | .. |
|---|
| 1 | | -import { WebSocketMessage } from "../types"; |
|---|
| 1 | +import { WsOutgoing } from "../types"; |
|---|
| 2 | 2 | |
|---|
| 3 | +type WebSocketMessage = Record<string, unknown>; |
|---|
| 3 | 4 | type MessageCallback = (data: WebSocketMessage) => void; |
|---|
| 4 | 5 | type StatusCallback = () => void; |
|---|
| 5 | 6 | type ErrorCallback = (error: Event) => void; |
|---|
| .. | .. |
|---|
| 14 | 15 | const INITIAL_RECONNECT_DELAY = 1000; |
|---|
| 15 | 16 | const MAX_RECONNECT_DELAY = 30000; |
|---|
| 16 | 17 | const RECONNECT_MULTIPLIER = 2; |
|---|
| 18 | +const LOCAL_TIMEOUT = 2500; |
|---|
| 17 | 19 | |
|---|
| 18 | 20 | export class WebSocketClient { |
|---|
| 19 | 21 | private ws: WebSocket | null = null; |
|---|
| 20 | | - private url: string = ""; |
|---|
| 22 | + private urls: string[] = []; |
|---|
| 23 | + private urlIndex: number = 0; |
|---|
| 21 | 24 | private reconnectDelay: number = INITIAL_RECONNECT_DELAY; |
|---|
| 22 | 25 | private reconnectTimer: ReturnType<typeof setTimeout> | null = null; |
|---|
| 26 | + private localTimer: ReturnType<typeof setTimeout> | null = null; |
|---|
| 23 | 27 | private shouldReconnect: boolean = false; |
|---|
| 28 | + private connected: boolean = false; |
|---|
| 24 | 29 | private callbacks: WebSocketClientOptions = {}; |
|---|
| 25 | 30 | |
|---|
| 26 | 31 | setCallbacks(callbacks: WebSocketClientOptions) { |
|---|
| 27 | 32 | this.callbacks = callbacks; |
|---|
| 28 | 33 | } |
|---|
| 29 | 34 | |
|---|
| 30 | | - connect(url: string) { |
|---|
| 31 | | - this.url = url; |
|---|
| 35 | + connect(urls: string[]) { |
|---|
| 36 | + this.urls = urls.filter(Boolean); |
|---|
| 37 | + if (this.urls.length === 0) return; |
|---|
| 32 | 38 | this.shouldReconnect = true; |
|---|
| 33 | 39 | this.reconnectDelay = INITIAL_RECONNECT_DELAY; |
|---|
| 34 | | - this.openConnection(); |
|---|
| 40 | + this.urlIndex = 0; |
|---|
| 41 | + this.connected = false; |
|---|
| 42 | + this.tryUrl(); |
|---|
| 35 | 43 | } |
|---|
| 36 | 44 | |
|---|
| 37 | | - private openConnection() { |
|---|
| 45 | + private cleanup() { |
|---|
| 46 | + if (this.localTimer) { clearTimeout(this.localTimer); this.localTimer = null; } |
|---|
| 47 | + if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } |
|---|
| 38 | 48 | if (this.ws) { |
|---|
| 39 | | - this.ws.close(); |
|---|
| 49 | + const old = this.ws; |
|---|
| 40 | 50 | this.ws = null; |
|---|
| 51 | + old.onopen = null; |
|---|
| 52 | + old.onclose = null; |
|---|
| 53 | + old.onerror = null; |
|---|
| 54 | + old.onmessage = null; |
|---|
| 55 | + try { old.close(); } catch { /* ignore */ } |
|---|
| 56 | + } |
|---|
| 57 | + } |
|---|
| 58 | + |
|---|
| 59 | + private tryUrl() { |
|---|
| 60 | + this.cleanup(); |
|---|
| 61 | + |
|---|
| 62 | + const url = this.urls[this.urlIndex]; |
|---|
| 63 | + if (!url) return; |
|---|
| 64 | + |
|---|
| 65 | + const ws = new WebSocket(url); |
|---|
| 66 | + this.ws = ws; |
|---|
| 67 | + |
|---|
| 68 | + // If trying local (index 0) and we have a remote fallback, |
|---|
| 69 | + // give local 2.5s before switching to remote |
|---|
| 70 | + if (this.urlIndex === 0 && this.urls.length > 1) { |
|---|
| 71 | + this.localTimer = setTimeout(() => { |
|---|
| 72 | + this.localTimer = null; |
|---|
| 73 | + if (this.connected) return; // already connected, ignore |
|---|
| 74 | + // Local didn't connect in time — try remote |
|---|
| 75 | + this.urlIndex = 1; |
|---|
| 76 | + this.tryUrl(); |
|---|
| 77 | + }, LOCAL_TIMEOUT); |
|---|
| 41 | 78 | } |
|---|
| 42 | 79 | |
|---|
| 43 | | - try { |
|---|
| 44 | | - this.ws = new WebSocket(this.url); |
|---|
| 80 | + ws.onopen = () => { |
|---|
| 81 | + if (ws !== this.ws) return; // stale |
|---|
| 82 | + this.connected = true; |
|---|
| 83 | + if (this.localTimer) { clearTimeout(this.localTimer); this.localTimer = null; } |
|---|
| 84 | + this.reconnectDelay = INITIAL_RECONNECT_DELAY; |
|---|
| 85 | + this.callbacks.onOpen?.(); |
|---|
| 86 | + }; |
|---|
| 45 | 87 | |
|---|
| 46 | | - this.ws.onopen = () => { |
|---|
| 47 | | - this.reconnectDelay = INITIAL_RECONNECT_DELAY; |
|---|
| 48 | | - this.callbacks.onOpen?.(); |
|---|
| 49 | | - }; |
|---|
| 88 | + ws.onmessage = (event) => { |
|---|
| 89 | + if (ws !== this.ws) return; // stale |
|---|
| 90 | + try { |
|---|
| 91 | + const data = JSON.parse(event.data) as WebSocketMessage; |
|---|
| 92 | + this.callbacks.onMessage?.(data); |
|---|
| 93 | + } catch { |
|---|
| 94 | + this.callbacks.onMessage?.({ type: "text", content: String(event.data) }); |
|---|
| 95 | + } |
|---|
| 96 | + }; |
|---|
| 50 | 97 | |
|---|
| 51 | | - this.ws.onmessage = (event) => { |
|---|
| 52 | | - try { |
|---|
| 53 | | - const data = JSON.parse(event.data) as WebSocketMessage; |
|---|
| 54 | | - this.callbacks.onMessage?.(data); |
|---|
| 55 | | - } catch { |
|---|
| 56 | | - // Non-JSON message — treat as plain text |
|---|
| 57 | | - const data: WebSocketMessage = { |
|---|
| 58 | | - type: "text", |
|---|
| 59 | | - content: String(event.data), |
|---|
| 60 | | - }; |
|---|
| 61 | | - this.callbacks.onMessage?.(data); |
|---|
| 62 | | - } |
|---|
| 63 | | - }; |
|---|
| 64 | | - |
|---|
| 65 | | - this.ws.onclose = () => { |
|---|
| 66 | | - this.callbacks.onClose?.(); |
|---|
| 67 | | - if (this.shouldReconnect) { |
|---|
| 68 | | - this.scheduleReconnect(); |
|---|
| 69 | | - } |
|---|
| 70 | | - }; |
|---|
| 71 | | - |
|---|
| 72 | | - this.ws.onerror = (error) => { |
|---|
| 73 | | - this.callbacks.onError?.(error); |
|---|
| 74 | | - }; |
|---|
| 75 | | - } catch { |
|---|
| 98 | + ws.onclose = () => { |
|---|
| 99 | + if (ws !== this.ws) return; // stale |
|---|
| 100 | + this.connected = false; |
|---|
| 101 | + this.callbacks.onClose?.(); |
|---|
| 76 | 102 | if (this.shouldReconnect) { |
|---|
| 77 | 103 | this.scheduleReconnect(); |
|---|
| 78 | 104 | } |
|---|
| 79 | | - } |
|---|
| 105 | + }; |
|---|
| 106 | + |
|---|
| 107 | + ws.onerror = () => { |
|---|
| 108 | + if (ws !== this.ws) return; // stale |
|---|
| 109 | + // Don't do anything here — onclose always fires after onerror |
|---|
| 110 | + // and handles reconnect. Just swallow the error event. |
|---|
| 111 | + }; |
|---|
| 80 | 112 | } |
|---|
| 81 | 113 | |
|---|
| 82 | 114 | private scheduleReconnect() { |
|---|
| 83 | | - if (this.reconnectTimer) { |
|---|
| 84 | | - clearTimeout(this.reconnectTimer); |
|---|
| 85 | | - } |
|---|
| 115 | + if (this.reconnectTimer) clearTimeout(this.reconnectTimer); |
|---|
| 86 | 116 | this.reconnectTimer = setTimeout(() => { |
|---|
| 117 | + this.reconnectTimer = null; |
|---|
| 87 | 118 | this.reconnectDelay = Math.min( |
|---|
| 88 | 119 | this.reconnectDelay * RECONNECT_MULTIPLIER, |
|---|
| 89 | 120 | MAX_RECONNECT_DELAY |
|---|
| 90 | 121 | ); |
|---|
| 91 | | - this.openConnection(); |
|---|
| 122 | + // Alternate between URLs on each reconnect attempt |
|---|
| 123 | + if (this.urls.length > 1) { |
|---|
| 124 | + this.urlIndex = this.urlIndex === 0 ? 1 : 0; |
|---|
| 125 | + } |
|---|
| 126 | + this.tryUrl(); |
|---|
| 92 | 127 | }, this.reconnectDelay); |
|---|
| 93 | 128 | } |
|---|
| 94 | 129 | |
|---|
| 95 | 130 | disconnect() { |
|---|
| 96 | 131 | this.shouldReconnect = false; |
|---|
| 97 | | - if (this.reconnectTimer) { |
|---|
| 98 | | - clearTimeout(this.reconnectTimer); |
|---|
| 99 | | - this.reconnectTimer = null; |
|---|
| 100 | | - } |
|---|
| 101 | | - if (this.ws) { |
|---|
| 102 | | - this.ws.close(); |
|---|
| 103 | | - this.ws = null; |
|---|
| 104 | | - } |
|---|
| 132 | + this.connected = false; |
|---|
| 133 | + this.cleanup(); |
|---|
| 105 | 134 | } |
|---|
| 106 | 135 | |
|---|
| 107 | | - send(message: WebSocketMessage) { |
|---|
| 136 | + send(message: WsOutgoing) { |
|---|
| 108 | 137 | if (this.ws && this.ws.readyState === WebSocket.OPEN) { |
|---|
| 109 | 138 | this.ws.send(JSON.stringify(message)); |
|---|
| 110 | 139 | return true; |
|---|
| .. | .. |
|---|
| 117 | 146 | } |
|---|
| 118 | 147 | |
|---|
| 119 | 148 | get isConnected(): boolean { |
|---|
| 120 | | - return this.ws?.readyState === WebSocket.OPEN; |
|---|
| 149 | + return this.connected; |
|---|
| 150 | + } |
|---|
| 151 | + |
|---|
| 152 | + get currentUrl(): string { |
|---|
| 153 | + return this.urls[this.urlIndex] ?? ""; |
|---|
| 121 | 154 | } |
|---|
| 122 | 155 | } |
|---|
| 123 | 156 | |
|---|
| .. | .. |
|---|
| 1 | +/** |
|---|
| 2 | + * Wake-on-LAN service — sends a magic packet to wake a sleeping Mac. |
|---|
| 3 | + * |
|---|
| 4 | + * The magic packet is 6 bytes of 0xFF followed by the target MAC address |
|---|
| 5 | + * repeated 16 times, sent as a UDP broadcast on port 9. |
|---|
| 6 | + */ |
|---|
| 7 | +import dgram from "react-native-udp"; |
|---|
| 8 | + |
|---|
| 9 | +function parseMac(mac: string): number[] { |
|---|
| 10 | + const parts = mac |
|---|
| 11 | + .replace(/[:-]/g, "") |
|---|
| 12 | + .match(/.{2}/g); |
|---|
| 13 | + if (!parts || parts.length !== 6) { |
|---|
| 14 | + throw new Error(`Invalid MAC address: ${mac}`); |
|---|
| 15 | + } |
|---|
| 16 | + return parts.map((h) => parseInt(h, 16)); |
|---|
| 17 | +} |
|---|
| 18 | + |
|---|
| 19 | +function buildMagicPacket(mac: string): Uint8Array { |
|---|
| 20 | + const macBytes = parseMac(mac); |
|---|
| 21 | + const packet = new Uint8Array(102); |
|---|
| 22 | + |
|---|
| 23 | + // 6 bytes of 0xFF |
|---|
| 24 | + for (let i = 0; i < 6; i++) { |
|---|
| 25 | + packet[i] = 0xff; |
|---|
| 26 | + } |
|---|
| 27 | + |
|---|
| 28 | + // MAC address repeated 16 times |
|---|
| 29 | + for (let i = 0; i < 16; i++) { |
|---|
| 30 | + const offset = 6 + i * 6; |
|---|
| 31 | + for (let j = 0; j < 6; j++) { |
|---|
| 32 | + packet[offset + j] = macBytes[j]; |
|---|
| 33 | + } |
|---|
| 34 | + } |
|---|
| 35 | + |
|---|
| 36 | + return packet; |
|---|
| 37 | +} |
|---|
| 38 | + |
|---|
| 39 | +/** |
|---|
| 40 | + * Send a Wake-on-LAN magic packet to the given MAC address. |
|---|
| 41 | + * Sends to both the subnet broadcast (derived from host) and 255.255.255.255. |
|---|
| 42 | + */ |
|---|
| 43 | +export async function sendWol(mac: string, host?: string): Promise<void> { |
|---|
| 44 | + const packet = buildMagicPacket(mac); |
|---|
| 45 | + |
|---|
| 46 | + // Derive broadcast address from host IP (replace last octet with 255) |
|---|
| 47 | + const broadcastAddresses = ["255.255.255.255"]; |
|---|
| 48 | + if (host) { |
|---|
| 49 | + const parts = host.split("."); |
|---|
| 50 | + if (parts.length === 4) { |
|---|
| 51 | + parts[3] = "255"; |
|---|
| 52 | + const subnetBroadcast = parts.join("."); |
|---|
| 53 | + if (!broadcastAddresses.includes(subnetBroadcast)) { |
|---|
| 54 | + broadcastAddresses.push(subnetBroadcast); |
|---|
| 55 | + } |
|---|
| 56 | + } |
|---|
| 57 | + } |
|---|
| 58 | + |
|---|
| 59 | + return new Promise<void>((resolve, reject) => { |
|---|
| 60 | + const socket = dgram.createSocket({ type: "udp4" }); |
|---|
| 61 | + |
|---|
| 62 | + socket.once("error", (err: Error) => { |
|---|
| 63 | + try { socket.close(); } catch { /* ignore */ } |
|---|
| 64 | + reject(err); |
|---|
| 65 | + }); |
|---|
| 66 | + |
|---|
| 67 | + socket.bind(0, () => { |
|---|
| 68 | + try { |
|---|
| 69 | + socket.setBroadcast(true); |
|---|
| 70 | + } catch { |
|---|
| 71 | + // Some platforms don't support setBroadcast — continue anyway |
|---|
| 72 | + } |
|---|
| 73 | + |
|---|
| 74 | + let pending = broadcastAddresses.length; |
|---|
| 75 | + let failed = false; |
|---|
| 76 | + |
|---|
| 77 | + for (const addr of broadcastAddresses) { |
|---|
| 78 | + socket.send(packet, 0, packet.length, 9, addr, (err?: Error) => { |
|---|
| 79 | + if (err && !failed) { |
|---|
| 80 | + failed = true; |
|---|
| 81 | + try { socket.close(); } catch { /* ignore */ } |
|---|
| 82 | + reject(err); |
|---|
| 83 | + return; |
|---|
| 84 | + } |
|---|
| 85 | + pending--; |
|---|
| 86 | + if (pending === 0) { |
|---|
| 87 | + try { socket.close(); } catch { /* ignore */ } |
|---|
| 88 | + resolve(); |
|---|
| 89 | + } |
|---|
| 90 | + }); |
|---|
| 91 | + } |
|---|
| 92 | + }); |
|---|
| 93 | + }); |
|---|
| 94 | +} |
|---|
| 95 | + |
|---|
| 96 | +/** |
|---|
| 97 | + * Validate a MAC address string. |
|---|
| 98 | + */ |
|---|
| 99 | +export function isValidMac(mac: string): boolean { |
|---|
| 100 | + return /^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/.test(mac.trim()); |
|---|
| 101 | +} |
|---|
| .. | .. |
|---|
| 16 | 16 | export interface ServerConfig { |
|---|
| 17 | 17 | host: string; |
|---|
| 18 | 18 | port: number; |
|---|
| 19 | + localHost?: string; |
|---|
| 20 | + macAddress?: string; |
|---|
| 19 | 21 | } |
|---|
| 20 | 22 | |
|---|
| 21 | | -export type ConnectionStatus = "disconnected" | "connecting" | "connected"; |
|---|
| 23 | +export type ConnectionStatus = "disconnected" | "connecting" | "connected" | "compacting"; |
|---|
| 22 | 24 | |
|---|
| 23 | 25 | // --- WebSocket protocol --- |
|---|
| 24 | 26 | |
|---|
| .. | .. |
|---|
| 34 | 36 | content: string; |
|---|
| 35 | 37 | } |
|---|
| 36 | 38 | |
|---|
| 39 | +export interface WsImageMessage { |
|---|
| 40 | + type: "image"; |
|---|
| 41 | + imageBase64: string; |
|---|
| 42 | + caption: string; |
|---|
| 43 | + mimeType: string; |
|---|
| 44 | +} |
|---|
| 45 | + |
|---|
| 37 | 46 | export interface WsCommandMessage { |
|---|
| 38 | 47 | type: "command"; |
|---|
| 39 | 48 | command: string; |
|---|
| 40 | 49 | args?: Record<string, unknown>; |
|---|
| 41 | 50 | } |
|---|
| 42 | 51 | |
|---|
| 43 | | -export type WsOutgoing = WsTextMessage | WsVoiceMessage | WsCommandMessage; |
|---|
| 52 | +export type WsOutgoing = WsTextMessage | WsVoiceMessage | WsImageMessage | WsCommandMessage; |
|---|
| 44 | 53 | |
|---|
| 45 | 54 | /** Incoming from watcher to app */ |
|---|
| 46 | 55 | export interface WsIncomingText { |
|---|
| .. | .. |
|---|
| 91 | 100 | message: string; |
|---|
| 92 | 101 | } |
|---|
| 93 | 102 | |
|---|
| 103 | +export interface WsIncomingStatus { |
|---|
| 104 | + type: "status"; |
|---|
| 105 | + status: string; |
|---|
| 106 | +} |
|---|
| 107 | + |
|---|
| 94 | 108 | export type WsIncoming = |
|---|
| 95 | 109 | | WsIncomingText |
|---|
| 96 | 110 | | WsIncomingVoice |
|---|
| .. | .. |
|---|
| 98 | 112 | | WsIncomingSessions |
|---|
| 99 | 113 | | WsIncomingSessionSwitched |
|---|
| 100 | 114 | | WsIncomingSessionRenamed |
|---|
| 101 | | - | WsIncomingError; |
|---|
| 115 | + | WsIncomingError |
|---|
| 116 | + | WsIncomingStatus; |
|---|