diff --git a/apps/computer-vision/app/_layout.tsx b/apps/computer-vision/app/_layout.tsx index f62075ea8..35a0cc0da 100644 --- a/apps/computer-vision/app/_layout.tsx +++ b/apps/computer-vision/app/_layout.tsx @@ -1,73 +1,133 @@ import { Drawer } from 'expo-router/drawer'; import ColorPalette from '../colors'; -import React from 'react'; +import React, { useState } from 'react'; +import { Text, StyleSheet, View } from 'react-native'; + +import { + DrawerContentComponentProps, + DrawerContentScrollView, + DrawerItemList, +} from '@react-navigation/drawer'; +import { GeneratingContext } from '../context'; + +interface CustomDrawerProps extends DrawerContentComponentProps { + isGenerating: boolean; +} + +function CustomDrawerContent(props: CustomDrawerProps) { + const { isGenerating, ...otherProps } = props; + return ( + + {!isGenerating ? ( + + ) : ( + + Model is generating... + Interrupt before switching model + + )} + + ); +} export default function _layout() { + const [isGenerating, setIsGenerating] = useState(false); + return ( - { + setIsGenerating(newState); + }, }} > - ( + + )} + screenOptions={{ + drawerActiveTintColor: ColorPalette.primary, + drawerInactiveTintColor: '#888', + headerTintColor: ColorPalette.primary, headerTitleStyle: { color: ColorPalette.primary }, }} - /> - - - - - - - + > + + + + + + + null, + title: 'Main Menu', + drawerItemStyle: { display: 'none' }, + }} + /> + + ); } + +const styles = StyleSheet.create({ + centerContent: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + padding: 20, + }, + mainText: { + fontSize: 18, + fontWeight: 'bold', + marginBottom: 10, + color: ColorPalette.primary, + }, + subText: { + fontSize: 14, + color: ColorPalette.strongPrimary, + }, +}); diff --git a/apps/computer-vision/app/classification/index.tsx b/apps/computer-vision/app/classification/index.tsx index 2e0ab4a1f..949c8a0da 100644 --- a/apps/computer-vision/app/classification/index.tsx +++ b/apps/computer-vision/app/classification/index.tsx @@ -1,9 +1,11 @@ -import { useState } from 'react'; import Spinner from 'react-native-loading-spinner-overlay'; import { getImage } from '../../utils'; import { useClassification, EFFICIENTNET_V2_S } from 'react-native-executorch'; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; import { BottomBar } from '../../components/BottomBar'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; export default function ClassificationScreen() { const [results, setResults] = useState<{ label: string; score: number }[]>( @@ -14,6 +16,10 @@ export default function ClassificationScreen() { const model = useClassification({ modelSource: EFFICIENTNET_V2_S, }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(model.isGenerating); + }, [model.isGenerating, setGlobalGenerating]); const handleCameraPress = async (isCamera: boolean) => { const image = await getImage(isCamera); @@ -48,7 +54,7 @@ export default function ClassificationScreen() { ); } return ( - <> + - + ); } diff --git a/apps/computer-vision/app/image_segmentation/index.tsx b/apps/computer-vision/app/image_segmentation/index.tsx index 48292e0fc..3b0685073 100644 --- a/apps/computer-vision/app/image_segmentation/index.tsx +++ b/apps/computer-vision/app/image_segmentation/index.tsx @@ -14,7 +14,9 @@ import { ColorType, } from '@shopify/react-native-skia'; import { View, StyleSheet, Image } from 'react-native'; -import { useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; const width = 224; const height = 224; @@ -62,6 +64,10 @@ export default function ImageSegmentationScreen() { const model = useImageSegmentation({ modelSource: DEEPLAB_V3_RESNET50, }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(model.isGenerating); + }, [model.isGenerating, setGlobalGenerating]); const [imageUri, setImageUri] = useState(''); const handleCameraPress = async (isCamera: boolean) => { @@ -118,7 +124,7 @@ export default function ImageSegmentationScreen() { } return ( - <> + - + ); } diff --git a/apps/computer-vision/app/object_detection/index.tsx b/apps/computer-vision/app/object_detection/index.tsx index be8e31196..8124f9cfe 100644 --- a/apps/computer-vision/app/object_detection/index.tsx +++ b/apps/computer-vision/app/object_detection/index.tsx @@ -1,4 +1,3 @@ -import { useState } from 'react'; import Spinner from 'react-native-loading-spinner-overlay'; import { BottomBar } from '../../components/BottomBar'; import { getImage } from '../../utils'; @@ -9,6 +8,9 @@ import { } from 'react-native-executorch'; import { View, StyleSheet, Image } from 'react-native'; import ImageWithBboxes from '../../components/ImageWithBboxes'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; export default function ObjectDetectionScreen() { const [imageUri, setImageUri] = useState(''); @@ -21,6 +23,10 @@ export default function ObjectDetectionScreen() { const ssdLite = useObjectDetection({ modelSource: SSDLITE_320_MOBILENET_V3_LARGE, }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(ssdLite.isGenerating); + }, [ssdLite.isGenerating, setGlobalGenerating]); const handleCameraPress = async (isCamera: boolean) => { const image = await getImage(isCamera); @@ -57,7 +63,7 @@ export default function ObjectDetectionScreen() { } return ( - <> + {imageUri && imageDimensions?.width && imageDimensions?.height ? ( @@ -82,7 +88,7 @@ export default function ObjectDetectionScreen() { handleCameraPress={handleCameraPress} runForward={runForward} /> - + ); } diff --git a/apps/computer-vision/app/ocr/index.tsx b/apps/computer-vision/app/ocr/index.tsx index f81216e5d..73c13915a 100644 --- a/apps/computer-vision/app/ocr/index.tsx +++ b/apps/computer-vision/app/ocr/index.tsx @@ -9,8 +9,10 @@ import { useOCR, } from 'react-native-executorch'; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; -import { useState } from 'react'; import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; export default function OCRScreen() { const [imageUri, setImageUri] = useState(''); @@ -29,6 +31,10 @@ export default function OCRScreen() { }, language: 'en', }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(model.isGenerating); + }, [model.isGenerating, setGlobalGenerating]); const handleCameraPress = async (isCamera: boolean) => { const image = await getImage(isCamera); @@ -62,7 +68,7 @@ export default function OCRScreen() { } return ( - <> + {imageUri && imageDimensions?.width && imageDimensions?.height ? ( @@ -100,7 +106,7 @@ export default function OCRScreen() { handleCameraPress={handleCameraPress} runForward={runForward} /> - + ); } diff --git a/apps/computer-vision/app/ocr_vertical/index.tsx b/apps/computer-vision/app/ocr_vertical/index.tsx index 7857e59c5..325bf7ac9 100644 --- a/apps/computer-vision/app/ocr_vertical/index.tsx +++ b/apps/computer-vision/app/ocr_vertical/index.tsx @@ -9,8 +9,10 @@ import { useVerticalOCR, } from 'react-native-executorch'; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; -import { useState } from 'react'; import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; export default function VerticalOCRScree() { const [imageUri, setImageUri] = useState(''); @@ -31,6 +33,10 @@ export default function VerticalOCRScree() { language: 'en', independentCharacters: true, }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(model.isGenerating); + }, [model.isGenerating, setGlobalGenerating]); const handleCameraPress = async (isCamera: boolean) => { const image = await getImage(isCamera); @@ -64,7 +70,7 @@ export default function VerticalOCRScree() { } return ( - <> + {imageUri && imageDimensions?.width && imageDimensions?.height ? ( @@ -102,7 +108,7 @@ export default function VerticalOCRScree() { handleCameraPress={handleCameraPress} runForward={runForward} /> - + ); } diff --git a/apps/computer-vision/app/style_transfer/index.tsx b/apps/computer-vision/app/style_transfer/index.tsx index 6c227b5a3..ba6d837ad 100644 --- a/apps/computer-vision/app/style_transfer/index.tsx +++ b/apps/computer-vision/app/style_transfer/index.tsx @@ -6,12 +6,18 @@ import { STYLE_TRANSFER_CANDY, } from 'react-native-executorch'; import { View, StyleSheet, Image } from 'react-native'; -import React, { useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; +import { GeneratingContext } from '../../context'; +import ScreenWrapper from '../../screenWrapper'; export default function StyleTransferScreen() { const model = useStyleTransfer({ modelSource: STYLE_TRANSFER_CANDY, }); + const { setGlobalGenerating } = useContext(GeneratingContext); + useEffect(() => { + setGlobalGenerating(model.isGenerating); + }, [model.isGenerating, setGlobalGenerating]); const [imageUri, setImageUri] = useState(''); const handleCameraPress = async (isCamera: boolean) => { const image = await getImage(isCamera); @@ -42,7 +48,7 @@ export default function StyleTransferScreen() { } return ( - <> + - + ); } diff --git a/apps/computer-vision/context.ts b/apps/computer-vision/context.ts new file mode 100644 index 000000000..0eb056076 --- /dev/null +++ b/apps/computer-vision/context.ts @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +export const GeneratingContext = createContext({ + setGlobalGenerating: (_newState: boolean) => {}, +}); diff --git a/apps/computer-vision/screenWrapper.tsx b/apps/computer-vision/screenWrapper.tsx new file mode 100644 index 000000000..0d1a9dae5 --- /dev/null +++ b/apps/computer-vision/screenWrapper.tsx @@ -0,0 +1,8 @@ +import { useIsFocused } from '@react-navigation/native'; +import { PropsWithChildren } from 'react'; + +export default function ScreenWrapper({ children }: PropsWithChildren) { + const isFocused = useIsFocused(); + + return isFocused ? <>{children} : null; +} diff --git a/apps/llm/app/_layout.tsx b/apps/llm/app/_layout.tsx index 31cac307f..786cb2de1 100644 --- a/apps/llm/app/_layout.tsx +++ b/apps/llm/app/_layout.tsx @@ -1,53 +1,109 @@ import { Drawer } from 'expo-router/drawer'; import ColorPalette from '../colors'; -import React from 'react'; +import React, { useState } from 'react'; +import { Text, StyleSheet, View } from 'react-native'; + +import { + DrawerContentComponentProps, + DrawerContentScrollView, + DrawerItemList, +} from '@react-navigation/drawer'; +import { GeneratingContext } from '../context'; + +interface CustomDrawerProps extends DrawerContentComponentProps { + isGenerating: boolean; +} + +function CustomDrawerContent(props: CustomDrawerProps) { + const { isGenerating, ...otherProps } = props; + return ( + + {!isGenerating ? ( + + ) : ( + + Model is generating... + Interrupt before switching model + + )} + + ); +} + +export default function _layout() { + const [isGenerating, setIsGenerating] = useState(false); -function DrawerWithScreens() { return ( - { + setIsGenerating(newState); + }, }} > - ( + + )} + screenOptions={{ + drawerActiveTintColor: ColorPalette.primary, + drawerInactiveTintColor: '#888', + headerTintColor: ColorPalette.primary, headerTitleStyle: { color: ColorPalette.primary }, }} - /> - - - - + > + + + + null, + title: 'Main Menu', + drawerItemStyle: { display: 'none' }, + }} + /> + + ); } -export default function _layout() { - return ; -} +const styles = StyleSheet.create({ + centerContent: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + padding: 20, + }, + mainText: { + fontSize: 18, + fontWeight: 'bold', + marginBottom: 10, + color: ColorPalette.primary, + }, + subText: { + fontSize: 14, + color: ColorPalette.strongPrimary, + }, +}); diff --git a/apps/llm/app/llm/index.tsx b/apps/llm/app/llm/index.tsx index f406b3c4a..35892c15d 100644 --- a/apps/llm/app/llm/index.tsx +++ b/apps/llm/app/llm/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import { Keyboard, KeyboardAvoidingView, @@ -21,11 +21,20 @@ import { import PauseIcon from '../../assets/icons/pause_icon.svg'; import ColorPalette from '../../colors'; import Messages from '../../components/Messages'; +import { useIsFocused } from '@react-navigation/native'; +import { GeneratingContext } from '../../context'; -export default function LLMScreen() { +export default function LLMScreenWrapper() { + const isFocused = useIsFocused(); + + return isFocused ? : null; +} + +function LLMScreen() { const [isTextInputFocused, setIsTextInputFocused] = useState(false); const [userInput, setUserInput] = useState(''); const textInputRef = useRef(null); + const { setGlobalGenerating } = useContext(GeneratingContext); const llm = useLLM({ modelSource: LLAMA3_2_1B_QLORA, @@ -39,6 +48,10 @@ export default function LLMScreen() { } }, [llm.error]); + useEffect(() => { + setGlobalGenerating(llm.isGenerating); + }, [llm.isGenerating, setGlobalGenerating]); + const sendMessage = async () => { setUserInput(''); textInputRef.current?.clear(); diff --git a/apps/llm/app/llm_tool_calling/index.tsx b/apps/llm/app/llm_tool_calling/index.tsx index fe767997c..831fed224 100644 --- a/apps/llm/app/llm_tool_calling/index.tsx +++ b/apps/llm/app/llm_tool_calling/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import { Keyboard, KeyboardAvoidingView, @@ -26,11 +26,20 @@ import Messages from '../../components/Messages'; import * as Brightness from 'expo-brightness'; import * as Calendar from 'expo-calendar'; import { executeTool, TOOL_DEFINITIONS_PHONE } from '../../utils/tools'; +import { useIsFocused } from '@react-navigation/native'; +import { GeneratingContext } from '../../context'; -export default function LLMToolCallingScreen() { +export default function LLMToolCallingScreenWrapper() { + const isFocused = useIsFocused(); + + return isFocused ? : null; +} + +function LLMToolCallingScreen() { const [isTextInputFocused, setIsTextInputFocused] = useState(false); const [userInput, setUserInput] = useState(''); const textInputRef = useRef(null); + const { setGlobalGenerating } = useContext(GeneratingContext); const llm = useLLM({ modelSource: HAMMER2_1_1_5B, @@ -38,6 +47,10 @@ export default function LLMToolCallingScreen() { tokenizerConfigSource: HAMMER2_1_TOKENIZER_CONFIG, }); + useEffect(() => { + setGlobalGenerating(llm.isGenerating); + }, [llm.isGenerating, setGlobalGenerating]); + const { configure } = llm; useEffect(() => { configure({ diff --git a/apps/llm/app/voice_chat/index.tsx b/apps/llm/app/voice_chat/index.tsx index fe3c19b73..30683fec6 100644 --- a/apps/llm/app/voice_chat/index.tsx +++ b/apps/llm/app/voice_chat/index.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import { Keyboard, KeyboardAvoidingView, @@ -27,6 +27,8 @@ import Messages from '../../components/Messages'; import LiveAudioStream from 'react-native-live-audio-stream'; import DeviceInfo from 'react-native-device-info'; import { Buffer } from 'buffer'; +import { useIsFocused } from '@react-navigation/native'; +import { GeneratingContext } from '../../context'; const audioStreamOptions = { sampleRate: 16000, channels: 1, @@ -55,9 +57,16 @@ const float32ArrayFromPCMBinaryBuffer = (b64EncodedBuffer: string) => { return float32Array; }; -export default function VoiceChatScreen() { +export default function VoiceChatScreenWrapper() { + const isFocused = useIsFocused(); + + return isFocused ? : null; +} + +function VoiceChatScreen() { const [isRecording, setIsRecording] = useState(false); const messageRecorded = useRef(false); + const { setGlobalGenerating } = useContext(GeneratingContext); const llm = useLLM({ modelSource: QWEN3_0_6B_QUANTIZED, @@ -70,6 +79,10 @@ export default function VoiceChatScreen() { overlapSeconds: 1.2, }); + useEffect(() => { + setGlobalGenerating(llm.isGenerating || speechToText.isGenerating); + }, [llm.isGenerating, speechToText.isGenerating, setGlobalGenerating]); + const onChunk = (data: string) => { const float32Chunk = float32ArrayFromPCMBinaryBuffer(data); speechToText.streamingTranscribe( diff --git a/apps/llm/context.ts b/apps/llm/context.ts new file mode 100644 index 000000000..0eb056076 --- /dev/null +++ b/apps/llm/context.ts @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +export const GeneratingContext = createContext({ + setGlobalGenerating: (_newState: boolean) => {}, +}); diff --git a/apps/llm/ios/Podfile.lock b/apps/llm/ios/Podfile.lock index 3278a532c..16a673f2a 100644 --- a/apps/llm/ios/Podfile.lock +++ b/apps/llm/ios/Podfile.lock @@ -2444,97 +2444,97 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb - EXConstants: 9f310f44bfedba09087042756802040e464323c0 - Expo: 4e8bda07d30b024b1732f87843a5349a3ecc1316 - ExpoAsset: 3bc9adb7dbbf27ae82c18ca97eb988a3ae7e73b1 - ExpoBrightness: c335c6ccc082d5249a4b38dba5cd9a08aa0bf62b - ExpoCalendar: f5f94ea8dcd957b1434beb4e1c0da1af063322e6 - ExpoFileSystem: c36eb8155eb2381c83dda7dc210e3eec332368b6 - ExpoFont: abbb91a911eb961652c2b0a22eef801860425ed6 - ExpoHead: af044f3e9c99e7d8d21bf653b4c2f2ef53a7f082 - ExpoKeepAwake: bf0811570c8da182bfb879169437d4de298376e7 - ExpoLinking: b85ff4eafeae6fc638c6cace60007ae521af0ef4 - ExpoModulesCore: d431ffe83c8673d02cb38425594a5f5480fd3061 + EXConstants: be238322d57d084dc055dbd5d6fe6479510504ce + Expo: 77b39f42396989cbe6fbef9f6fafc9b35186a95b + ExpoAsset: 3ea3275cca6a7793b3d36fbf1075c590f803fbcb + ExpoBrightness: 05e750736f8886dcf235212b0caf85b0f605fc88 + ExpoCalendar: 660542dc1c5ef98f46bedcc8745aa707df5d501a + ExpoFileSystem: 3a98ca2a6f13674ecfd97327d1b44a8ace444cbd + ExpoFont: 312c73403bbd4f98e1d6a5330641a56292583cd2 + ExpoHead: 5df88545652c2d3a3ea50bcd7f6be6ca935ac997 + ExpoKeepAwake: e8dedc115d9f6f24b153ccd2d1d8efcdfd68a527 + ExpoLinking: 5d151d4a497d7e375308602f0a89b4e8acf7b5f8 + ExpoModulesCore: e2e363bcdee87b46f858586d1887ebb215582001 fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6 FBLazyVector: 84b955f7b4da8b895faf5946f73748267347c975 fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 314be5250afa5692b57b4dd1705959e1973a8ebe opencv-rne: 2305807573b6e29c8c87e3416ab096d09047a7a0 - RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 + RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 RCTDeprecation: 83ffb90c23ee5cea353bd32008a7bca100908f8c RCTRequired: eb7c0aba998009f47a540bec9e9d69a54f68136e RCTTypeSafety: 659ae318c09de0477fd27bbc9e140071c7ea5c93 React: c2d3aa44c49bb34e4dfd49d3ee92da5ebacc1c1c React-callinvoker: 1bdfb7549b5af266d85757193b5069f60659ef9d - React-Core: 10597593fdbae06f0089881e025a172e51d4a769 - React-CoreModules: 6907b255529dd46895cf687daa67b24484a612c2 - React-cxxreact: a9f5b8180d6955bc3f6a3fcd657c4d9b4d95c1f6 + React-Core: 7150cf9b6a5af063b37003062689f1691e79c020 + React-CoreModules: 15a85e6665d61678942da6ae485b351f4c699049 + React-cxxreact: 74f9de59259ac951923f5726aa14f0398f167af9 React-debug: e74e76912b91e08d580c481c34881899ccf63da9 - React-defaultsnativemodule: 11f6ee2cf69bf3af9d0f28a6253def33d21b5266 - React-domnativemodule: f940bbc4fa9e134190acbf3a4a9f95621b5a8f51 - React-Fabric: 6f5c357bf3a42ff11f8844ad3fc7a1eb04f4b9de - React-FabricComponents: 10e0c0209822ac9e69412913a8af1ca33573379b - React-FabricImage: f582e764072dfa4715ae8c42979a5bace9cbcc12 + React-defaultsnativemodule: 628285212bbd65417d40ad6a9f8781830fda6c98 + React-domnativemodule: 185d9808198405c176784aaf33403d713bd24fb7 + React-Fabric: c814804affbe1952e16149ddd20256e1bccae67e + React-FabricComponents: 81ef47d596966121784afec9924f9562a29b1691 + React-FabricImage: f14f371d678aa557101def954ac3ba27e48948ff React-featureflags: d5facceff8f8f6de430e0acecf4979a9a0839ba9 - React-featureflagsnativemodule: a7dd141f1ef4b7c1331af0035689fbc742a49ff4 - React-graphics: 36ae3407172c1c77cea29265d2b12b90aaef6aa0 - React-hermes: 9116d4e6d07abeb519a2852672de087f44da8f12 - React-idlecallbacksnativemodule: ae7f5ffc6cf2d2058b007b78248e5b08172ad5c3 - React-ImageManager: 9daee0dc99ad6a001d4b9e691fbf37107e2b7b54 - React-jserrorhandler: 1e6211581071edaf4ecd5303147328120c73f4dc - React-jsi: 753ba30c902f3a41fa7f956aca8eea3317a44ee6 - React-jsiexecutor: 47520714aa7d9589c51c0f3713dfbfca4895d4f9 - React-jsinspector: cfd27107f6d6f1076a57d88c932401251560fe5f - React-jsinspectortracing: 76a7d791f3c0c09a0d2bf6f46dfb0e79a4fcc0ac - React-jsitooling: 995e826570dd58f802251490486ebd3244a037ab - React-jsitracing: 094ae3d8c123cea67b50211c945b7c0443d3e97b - React-logger: 8edfcedc100544791cd82692ca5a574240a16219 - React-Mapbuffer: c3f4b608e4a59dd2f6a416ef4d47a14400194468 - React-microtasksnativemodule: 054f34e9b82f02bd40f09cebd4083828b5b2beb6 - react-native-executorch: 9e4c26039a419f8b79c040571e80617c1114ca26 - react-native-safe-area-context: 562163222d999b79a51577eda2ea8ad2c32b4d06 - React-NativeModulesApple: 2c4377e139522c3d73f5df582e4f051a838ff25e + React-featureflagsnativemodule: 96f0ab285382d95c90f663e02526a5ceefa95a11 + React-graphics: 1a66ee0a3f093b125b853f6370296fadcaf6f233 + React-hermes: 8b86e5f54a65ecb69cdf22b3a00a11562eda82d2 + React-idlecallbacksnativemodule: 5c25ab145c602264d00cb26a397ab52e0efa031c + React-ImageManager: 15e34bd5ef1ac4a18e96660817ef70a7f99ee8c2 + React-jserrorhandler: 02cdf2cd45350108be1ffd2b164578936dbbdff7 + React-jsi: 6af1987cfbb1b6621664fdbf6c7b62bd4d38c923 + React-jsiexecutor: 51f372998e0303585cb0317232b938d694663cbd + React-jsinspector: 3539ad976d073bfaa8a7d2fa9bef35e70e55033e + React-jsinspectortracing: e8dbacaf67c201f23052ca1c2bae2f7b84dec443 + React-jsitooling: 95a34f41e3c249d42181de13b4f8d854f178ca9f + React-jsitracing: 25b029cf5cad488252d46da19dd8c4c134fd5fe4 + React-logger: 368570a253f00879a1e4fea24ed4047e72e7bbf3 + React-Mapbuffer: c04fcda1c6281fc0a6824c7dcc1633dd217ac1ec + React-microtasksnativemodule: ca2804a25fdcefffa0aa942aa23ab53b99614a34 + react-native-executorch: 66ffc33df70ec85bc591f9ee34c862835966ead3 + react-native-safe-area-context: 00d03dc688ba86664be66f9e3f203fc7d747d899 + React-NativeModulesApple: 452b86b29fae99ed0a4015dca3ad9cd222f88abf React-oscompat: ef5df1c734f19b8003e149317d041b8ce1f7d29c - React-perflogger: 9a151e0b4c933c9205fd648c246506a83f31395d - React-performancetimeline: 5b0dfc0acba29ea0269ddb34cd6dd59d3b8a1c66 + React-perflogger: 6fd2f6811533e9c19a61e855c3033eecbf4ad2a0 + React-performancetimeline: abf31259d794c9274b3ea19c5016186925eec6c4 React-RCTActionSheet: a499b0d6d9793886b67ba3e16046a3fef2cdbbc3 - React-RCTAnimation: cc64adc259aabc3354b73065e2231d796dfce576 - React-RCTAppDelegate: 9d523da768f1c9e84c5f3b7e3624d097dfb0e16b - React-RCTBlob: e727f53eeefded7e6432eb76bd22b57bc880e5d1 - React-RCTFabric: 58590aa4fdb4ad546c06a7449b486cf6844e991f - React-RCTFBReactNativeSpec: 9064c63d99e467a3893e328ba3612745c3c3a338 - React-RCTImage: 7159cbdbb18a09d97ba1a611416eced75b3ccb29 - React-RCTLinking: 46293afdb859bccc63e1d3dedc6901a3c04ef360 - React-RCTNetwork: 4a6cd18f5bcd0363657789c64043123a896b1170 - React-RCTRuntime: 5ab904fd749aa52f267ef771d265612582a17880 - React-RCTSettings: 61e361dc85136d1cb0e148b7541993d2ee950ea7 - React-RCTText: abd1e196c3167175e6baef18199c6d9d8ac54b4e - React-RCTVibration: 490e0dcb01a3fe4a0dfb7bc51ad5856d8b84f343 + React-RCTAnimation: 2595dcb10a82216a511b54742f8c28d793852ac6 + React-RCTAppDelegate: f03604b70f57c9469a84a159d8abecf793a5bcff + React-RCTBlob: e00f9b4e2f151938f4d9864cf33ebf24ac03328a + React-RCTFabric: 3945d116fd271598db262d4e6ed5691d431ed9e8 + React-RCTFBReactNativeSpec: 0f4d4f0da938101f2ca9d5333a8f46e527ad2819 + React-RCTImage: dac5e9f8ec476aefe6e60ee640ebc1dfaf1a4dbe + React-RCTLinking: 494b785a40d952a1dfbe712f43214376e5f0e408 + React-RCTNetwork: b3d7c30cd21793e268db107dd0980cb61b3c1c44 + React-RCTRuntime: a8ff419d437228e7b8a793b14f9d711e1cbb82af + React-RCTSettings: a060c7e381a3896104761b8eed7e284d95e37df3 + React-RCTText: 4f272b72dbb61f390d8c8274528f9fdbff983806 + React-RCTVibration: 0e5326220719aca12473d703aa46693e3b4ce67a React-rendererconsistency: 351fdbc5c1fe4da24243d939094a80f0e149c7a1 - React-renderercss: 3438814bee838ae7840a633ab085ac81699fd5cf - React-rendererdebug: 0ac2b9419ad6f88444f066d4b476180af311fb1e + React-renderercss: d333f2ada83969591100d91ec6b23ca2e17e1507 + React-rendererdebug: 039e5949b72ba63c703de020701e3fd152434c61 React-rncore: 57ed480649bb678d8bdc386d20fee8bf2b0c307c - React-RuntimeApple: 8b7a9788f31548298ba1990620fe06b40de65ad7 - React-RuntimeCore: e03d96fbd57ce69fd9bca8c925942194a5126dbc + React-RuntimeApple: 344a5e1105256000afabaa8df12c3e4cab880340 + React-RuntimeCore: 0e48fb5e5160acc0334c7a723a42d42cef4b58b6 React-runtimeexecutor: d60846710facedd1edb70c08b738119b3ee2c6c2 - React-RuntimeHermes: aab794755d9f6efd249b61f3af4417296904e3ba - React-runtimescheduler: c3cd124fa5db7c37f601ee49ca0d97019acd8788 + React-RuntimeHermes: 064286a03871d932c99738e0f8ef854962ab4b99 + React-runtimescheduler: e917ab17ae08c204af1ebf8f669b7e411b0220c8 React-timing: a90f4654cbda9c628614f9bee68967f1768bd6a5 - React-utils: a612d50555b6f0f90c74b7d79954019ad47f5de6 - ReactAppDependencyProvider: 04d5eb15eb46be6720e17a4a7fa92940a776e584 - ReactCodegen: 7ea266ccd94436294f516247db7402b57b1214af - ReactCommon: 76d2dc87136d0a667678668b86f0fca0c16fdeb0 - RNAudioAPI: 2e3fd4bf75aa5717791babb30126707504996f09 - RNDeviceInfo: d863506092aef7e7af3a1c350c913d867d795047 - RNGestureHandler: 7d0931a61d7ba0259f32db0ba7d0963c3ed15d2b - RNLiveAudioStream: 93ac2bb6065be9018d0b00157b220f11cebc1513 - RNReanimated: afd6a269a47d6f13ba295c46c6c0e14e3cbd0d8a - RNScreens: 482e9707f9826230810c92e765751af53826d509 - RNSVG: 794f269526df9ddc1f79b3d1a202b619df0368e3 + React-utils: 51c4e71608b8133fecc9a15801d244ae7bdf3758 + ReactAppDependencyProvider: d5dcc564f129632276bd3184e60f053fcd574d6b + ReactCodegen: c9a256facbe4996140f3fb95c7f03ba61c12acc9 + ReactCommon: 4d0da92a5eb8da86c08e3ec34bd23ab439fb2461 + RNAudioAPI: f93e51adeee0911c8c6629a56f6df35edc60c084 + RNDeviceInfo: feea80a690d2bde1fe51461cf548039258bd03f2 + RNGestureHandler: ccf4105b125002bd88e39d2a1f2b7e6001bcdf34 + RNLiveAudioStream: 02584d52711b6b9f268cb371a4b1bdd76ab3e079 + RNReanimated: c567de23384730756bb19ff55490819980536b09 + RNScreens: c2e3cc506212228c607b4785b315205e28acbf0f + RNSVG: ee32efbed652c5151fd3f98bed13c68af285bc38 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5 - Yoga: c758bfb934100bb4bf9cbaccb52557cee35e8bdf + Yoga: 9f110fc4b7aa538663cba3c14cbb1c335f43c13f PODFILE CHECKSUM: bba19a069e673f2259009e9d2caab44374fdebcf