diff --git a/__mocks__/react-native-vision-camera.ts b/__mocks__/react-native-vision-camera.ts
deleted file mode 100644
index 632a902e6bbd..000000000000
--- a/__mocks__/react-native-vision-camera.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-const useCameraDevice = jest.fn(() => null);
-const useCameraFormat = jest.fn(() => null);
-const useCameraPermission = jest.fn(() => ({hasPermission: false, requestPermission: jest.fn(() => Promise.resolve(false))}));
-
-const Camera = Object.assign(
-    jest.fn(() => null),
-    {
-        getCameraPermissionStatus: jest.fn(() => 'not-determined'),
-        requestCameraPermission: jest.fn(() => Promise.resolve('granted')),
-    },
-);
-
-export {Camera, useCameraDevice, useCameraFormat, useCameraPermission};
diff --git a/assets/images/camera-flip.svg b/assets/images/camera-flip.svg
deleted file mode 100644
index 2c3baf717701..000000000000
--- a/assets/images/camera-flip.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Layer_1" x="0" y="0" viewBox="0 0 20 20"><style>.st0{fill-rule:evenodd;clip-rule:evenodd}</style><path d="M12.65 1.5a1.5 1.5 0 0 1 1.286.729L15 4h3a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h3l1.063-1.771c.272-.452.76-.729 1.287-.729zm-1.9 9.5a.75.75 0 0 0 0 1.5h.902c-.406.566-1.027.902-1.686.902-.797 0-1.535-.491-1.911-1.287a.823.823 0 0 0-1.082-.39.79.79 0 0 0-.398 1.061C7.18 14.068 8.449 15 9.967 15c.989 0 1.871-.395 2.533-1.025v.275a.75.75 0 0 0 1.5 0V11zm-.717-4c-.989 0-1.871.395-2.533 1.025V7.75a.75.75 0 0 0-1.5 0V11h3.25a.75.75 0 0 0 0-1.5h-.901c.407-.566 1.026-.902 1.685-.902.797 0 1.535.491 1.911 1.287.189.4.674.575 1.083.39a.793.793 0 0 0 .398-1.061C12.82 7.932 11.551 7 10.033 7" class="st0"/></svg>
\ No newline at end of file
diff --git a/src/components/AttachmentPicker/AttachmentCamera.tsx b/src/components/AttachmentPicker/AttachmentCamera.tsx
deleted file mode 100644
index 4ecbf78bfdc3..000000000000
--- a/src/components/AttachmentPicker/AttachmentCamera.tsx
+++ /dev/null
@@ -1,315 +0,0 @@
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
-import {Modal, View} from 'react-native';
-import {GestureDetector} from 'react-native-gesture-handler';
-import {RESULTS} from 'react-native-permissions';
-import Animated from 'react-native-reanimated';
-import type {Camera, PhotoFile} from 'react-native-vision-camera';
-import {useCameraDevice, useCameraFormat, Camera as VisionCamera} from 'react-native-vision-camera';
-import ActivityIndicator from '@components/ActivityIndicator';
-import Button from '@components/Button';
-import Icon from '@components/Icon';
-import ImageSVG from '@components/ImageSVG';
-import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
-import Text from '@components/Text';
-import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import {useTapToFocusGesture} from '@hooks/useNativeCamera';
-import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {showCameraPermissionsAlert} from '@libs/fileDownload/FileUtils';
-import getPhotoSource from '@libs/fileDownload/getPhotoSource';
-import getReceiptsUploadFolderPath from '@libs/getReceiptsUploadFolderPath';
-import Log from '@libs/Log';
-import CameraPermission from '@pages/iou/request/step/IOURequestStepScan/CameraPermission';
-import variables from '@styles/variables';
-import CONST from '@src/CONST';
-
-type CapturedPhoto = {
-    uri: string;
-    fileName: string;
-    type: string;
-    width: number;
-    height: number;
-};
-
-type AttachmentCameraProps = {
-    /** Whether the camera modal is visible */
-    isVisible: boolean;
-
-    /** Callback when a photo is captured */
-    onCapture: (photos: CapturedPhoto[]) => void;
-
-    /** Callback when the camera is closed */
-    onClose: () => void;
-};
-
-function AttachmentCamera({isVisible, onCapture, onClose}: AttachmentCameraProps) {
-    const theme = useTheme();
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const insets = useSafeAreaInsets();
-    const StyleUtils = useStyleUtils();
-    const lazyIcons = useMemoizedLazyExpensifyIcons(['Bolt', 'boltSlash', 'CameraFlip', 'Close']);
-    const lazyIllustrations = useMemoizedLazyIllustrations(['Shutter', 'Hand']);
-
-    const [cameraPosition, setCameraPosition] = useState<'back' | 'front'>('back');
-    const [flash, setFlash] = useState(false);
-    const [cameraPermissionStatus, setCameraPermissionStatus] = useState<string | null>(null);
-    const isCapturing = useRef(false);
-    const isActiveRef = useRef(false);
-    const cameraRef = useRef<Camera>(null);
-
-    const device = useCameraDevice(cameraPosition, {
-        physicalDevices: ['wide-angle-camera', 'ultra-wide-angle-camera'],
-    });
-
-    const format = useCameraFormat(device, [
-        {photoAspectRatio: CONST.RECEIPT_CAMERA.PHOTO_ASPECT_RATIO},
-        {photoResolution: {width: CONST.RECEIPT_CAMERA.PHOTO_WIDTH, height: CONST.RECEIPT_CAMERA.PHOTO_HEIGHT}},
-    ]);
-    const hasFlash = !!device?.hasFlash;
-    // Format dimensions are in landscape orientation, so height/width gives portrait aspect ratio
-    const cameraAspectRatio = useMemo(() => (format ? format.photoHeight / format.photoWidth : undefined), [format]);
-
-    const {tapGesture, cameraFocusIndicatorAnimatedStyle} = useTapToFocusGesture(cameraRef, device?.supportsFocus ?? false);
-
-    // Permission management
-    const askForPermissions = useCallback(() => {
-        CameraPermission.requestCameraPermission?.()
-            .then((status: string) => {
-                setCameraPermissionStatus(status);
-                if (status === RESULTS.BLOCKED) {
-                    showCameraPermissionsAlert(translate);
-                }
-            })
-            .catch(() => {
-                setCameraPermissionStatus(RESULTS.UNAVAILABLE);
-            });
-    }, [translate]);
-
-    // Track visibility in a ref so async takePhoto callbacks can detect stale sessions
-    useEffect(() => {
-        isActiveRef.current = isVisible;
-    }, [isVisible]);
-
-    // Refresh permissions when modal becomes visible and auto-request if denied
-    useEffect(() => {
-        if (!isVisible) {
-            return;
-        }
-
-        let ignore = false;
-        CameraPermission?.getCameraPermissionStatus?.()
-            .then((status: string) => {
-                if (ignore) {
-                    return;
-                }
-                setCameraPermissionStatus(status);
-                if (status === RESULTS.DENIED) {
-                    askForPermissions();
-                }
-            })
-            .catch(() => {
-                if (ignore) {
-                    return;
-                }
-                setCameraPermissionStatus(RESULTS.UNAVAILABLE);
-            });
-        return () => {
-            ignore = true;
-        };
-    }, [isVisible, askForPermissions]);
-
-    const capturePhoto = useCallback(() => {
-        if (cameraPermissionStatus !== RESULTS.GRANTED) {
-            askForPermissions();
-            return;
-        }
-
-        if (!cameraRef.current || isCapturing.current) {
-            return;
-        }
-
-        isCapturing.current = true;
-
-        const path = getReceiptsUploadFolderPath();
-
-        cameraRef.current
-            .takePhoto({
-                flash: flash && hasFlash ? 'on' : 'off',
-                path,
-            })
-            .then((photo: PhotoFile) => {
-                // Discard capture if the camera was closed while takePhoto was in-flight
-                if (!isActiveRef.current) {
-                    return;
-                }
-                const uri = getPhotoSource(photo.path);
-                const fileName = photo.path.substring(photo.path.lastIndexOf('/') + 1) || `photo_${Date.now()}.jpg`;
-
-                onCapture([
-                    {
-                        uri,
-                        fileName,
-                        type: 'image/jpeg',
-                        width: photo.width,
-                        height: photo.height,
-                    },
-                ]);
-            })
-            .catch((error: Error) => {
-                Log.warn('Error capturing photo', {error: error.message});
-            })
-            .finally(() => {
-                isCapturing.current = false;
-            });
-    }, [askForPermissions, cameraPermissionStatus, flash, hasFlash, onCapture]);
-
-    const handleClose = useCallback(() => {
-        isCapturing.current = false;
-        setFlash(false);
-        setCameraPosition('back');
-        onClose();
-    }, [onClose]);
-
-    return (
-        <Modal
-            visible={isVisible}
-            animationType="slide"
-            transparent={false}
-            onRequestClose={handleClose}
-            supportedOrientations={['portrait']}
-            statusBarTranslucent
-        >
-            <View style={[styles.flex1, {backgroundColor: theme.appBG}, StyleUtils.getPlatformSafeAreaPadding(insets)]}>
-                {/* Close button */}
-                <View style={[styles.flexRow, styles.justifyContentEnd, styles.ph3, styles.pv2]}>
-                    <PressableWithFeedback
-                        role={CONST.ROLE.BUTTON}
-                        accessibilityLabel={translate('common.close')}
-                        onPress={handleClose}
-                        sentryLabel="AttachmentCamera-Close"
-                    >
-                        <Icon
-                            height={variables.iconSizeNormal}
-                            width={variables.iconSizeNormal}
-                            src={lazyIcons.Close}
-                            fill={theme.icon}
-                        />
-                    </PressableWithFeedback>
-                </View>
-
-                {/* Camera area */}
-                <View style={[styles.flex1]}>
-                    {cameraPermissionStatus !== RESULTS.GRANTED && (
-                        <View style={[styles.cameraView, styles.permissionView, styles.userSelectNone]}>
-                            <ImageSVG
-                                contentFit="contain"
-                                src={lazyIllustrations.Hand}
-                                width={CONST.RECEIPT.HAND_ICON_WIDTH}
-                                height={CONST.RECEIPT.HAND_ICON_HEIGHT}
-                                style={styles.pb5}
-                            />
-                            <Text style={[styles.textFileUpload]}>{translate('receipt.takePhoto')}</Text>
-                            <Text style={[styles.subTextFileUpload]}>{translate('receipt.cameraAccess')}</Text>
-                            <Button
-                                success
-                                text={translate('common.continue')}
-                                accessibilityLabel={translate('common.continue')}
-                                style={[styles.p9, styles.pt5]}
-                                onPress={askForPermissions}
-                            />
-                        </View>
-                    )}
-                    {cameraPermissionStatus === RESULTS.GRANTED && device == null && (
-                        <View style={[styles.cameraView, styles.justifyContentCenter, styles.alignItemsCenter]}>
-                            <ActivityIndicator
-                                size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
-                                style={[styles.flex1]}
-                                color={theme.textSupporting}
-                                reasonAttributes={{context: 'AttachmentCamera', deviceAvailable: false}}
-                            />
-                        </View>
-                    )}
-                    {cameraPermissionStatus === RESULTS.GRANTED && device != null && (
-                        <View style={[styles.cameraView, styles.alignItemsCenter]}>
-                            <GestureDetector gesture={tapGesture}>
-                                <View style={StyleUtils.getCameraViewfinderStyle(cameraAspectRatio, false)}>
-                                    <VisionCamera
-                                        ref={cameraRef}
-                                        device={device}
-                                        format={format ?? undefined}
-                                        style={styles.flex1}
-                                        zoom={device.neutralZoom}
-                                        photo
-                                        isActive={isVisible}
-                                        photoQualityBalance="quality"
-                                    />
-                                    <Animated.View style={[styles.cameraFocusIndicator, cameraFocusIndicatorAnimatedStyle]} />
-                                </View>
-                            </GestureDetector>
-                        </View>
-                    )}
-                </View>
-
-                {/* Bottom controls */}
-                <View style={[styles.flexRow, styles.justifyContentAround, styles.alignItemsCenter, styles.pv3]}>
-                    {/* Flash toggle */}
-                    <PressableWithFeedback
-                        role={CONST.ROLE.BUTTON}
-                        accessibilityLabel={translate('receipt.flash')}
-                        style={[styles.alignItemsStart, !hasFlash && styles.opacity0]}
-                        disabled={cameraPermissionStatus !== RESULTS.GRANTED || !hasFlash}
-                        onPress={() => setFlash((prevFlash) => !prevFlash)}
-                        sentryLabel="AttachmentCamera-Flash"
-                    >
-                        <Icon
-                            height={variables.iconSizeMenuItem}
-                            width={variables.iconSizeMenuItem}
-                            src={flash ? lazyIcons.Bolt : lazyIcons.boltSlash}
-                            fill={theme.textSupporting}
-                        />
-                    </PressableWithFeedback>
-
-                    {/* Shutter button */}
-                    <PressableWithFeedback
-                        role={CONST.ROLE.BUTTON}
-                        accessibilityLabel={translate('receipt.shutter')}
-                        style={[styles.alignItemsCenter]}
-                        onPress={capturePhoto}
-                        sentryLabel="AttachmentCamera-Shutter"
-                    >
-                        <ImageSVG
-                            contentFit="contain"
-                            src={lazyIllustrations.Shutter}
-                            width={CONST.RECEIPT.SHUTTER_SIZE}
-                            height={CONST.RECEIPT.SHUTTER_SIZE}
-                        />
-                    </PressableWithFeedback>
-
-                    {/* Camera flip */}
-                    <PressableWithFeedback
-                        role={CONST.ROLE.BUTTON}
-                        accessibilityLabel={translate('receipt.flipCamera')}
-                        style={[styles.alignItemsEnd]}
-                        disabled={cameraPermissionStatus !== RESULTS.GRANTED}
-                        onPress={() => setCameraPosition((prev) => (prev === 'back' ? 'front' : 'back'))}
-                        sentryLabel="AttachmentCamera-FlipCamera"
-                    >
-                        <Icon
-                            height={variables.iconSizeMenuItem}
-                            width={variables.iconSizeMenuItem}
-                            src={lazyIcons.CameraFlip}
-                            fill={theme.textSupporting}
-                        />
-                    </PressableWithFeedback>
-                </View>
-            </View>
-        </Modal>
-    );
-}
-
-export default AttachmentCamera;
-export type {CapturedPhoto};
diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx
index b8967fc296db..1b4a74e55441 100644
--- a/src/components/AttachmentPicker/index.native.tsx
+++ b/src/components/AttachmentPicker/index.native.tsx
@@ -24,8 +24,7 @@ import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import type {FileObject, ImagePickerResponse as FileResponse} from '@src/types/utils/Attachment';
 import type IconAsset from '@src/types/utils/IconAsset';
-import AttachmentCamera from './AttachmentCamera';
-import type {CapturedPhoto} from './AttachmentCamera';
+import launchCamera from './launchCamera/launchCamera';
 import type AttachmentPickerProps from './types';
 
 const EXTENSION_TO_NATIVE_TYPE: Record<string, string> = {
@@ -54,23 +53,14 @@ type LocalCopy = {
     type: string | null;
 };
 
-type Item =
-    | {
-          /** The icon associated with the item. */
-          icon: IconAsset;
-          /** The key in the translations file to use for the title */
-          textTranslationKey: TranslationPaths;
-          /** Function to call when the user clicks the item */
-          pickAttachment: () => Promise<Asset[] | void | LocalCopy[]>;
-      }
-    | {
-          /** The icon associated with the item. */
-          icon: IconAsset;
-          /** The key in the translations file to use for the title */
-          textTranslationKey: TranslationPaths;
-          /** Direct action that doesn't go through the promise-based selectItem flow */
-          onPress: () => void;
-      };
+type Item = {
+    /** The icon associated with the item. */
+    icon: IconAsset;
+    /** The key in the translations file to use for the title */
+    textTranslationKey: TranslationPaths;
+    /** Function to call when the user clicks the item */
+    pickAttachment: () => Promise<Asset[] | void | LocalCopy[]>;
+};
 
 /**
  * Ensures asset has proper fileName and type properties
@@ -158,7 +148,6 @@ function AttachmentPicker({
     const icons = useMemoizedLazyExpensifyIcons(['Camera', 'Gallery', 'Paperclip']);
     const styles = useThemeStyles();
     const [isVisible, setIsVisible] = useState(false);
-    const [showAttachmentCamera, setShowAttachmentCamera] = useState(false);
     const StyleUtils = useStyleUtils();
     const theme = useTheme();
 
@@ -181,20 +170,10 @@ function AttachmentPicker({
         [translate],
     );
 
-    /**
-     * Launch the in-app VisionCamera instead of the external system camera.
-     * Opens the camera modal directly — bypasses the promise-based selectItem flow.
-     * handleCameraCapture / handleCameraClose handle completion.
-     */
-    const launchInAppCamera = useCallback(() => {
-        onOpenPicker?.();
-        setShowAttachmentCamera(true);
-    }, [onOpenPicker]);
-
     /**
      * Common image picker handling
      *
-     * @param {function} imagePickerFunc - RNImagePicker.launchImageLibrary
+     * @param {function} imagePickerFunc - RNImagePicker.launchCamera or RNImagePicker.launchImageLibrary
      */
     const showImagePicker = useCallback(
         (imagePickerFunc: (options: CameraOptions, callback: Callback) => Promise<ImagePickerResponse>): Promise<Asset[] | void> =>
@@ -360,12 +339,12 @@ function AttachmentPicker({
             data.unshift({
                 icon: icons.Camera,
                 textTranslationKey: 'attachmentPicker.takePhoto',
-                onPress: launchInAppCamera,
+                pickAttachment: () => showImagePicker(launchCamera),
             });
         }
 
         return data;
-    }, [icons.Camera, icons.Paperclip, icons.Gallery, showDocumentPicker, shouldHideGalleryOption, shouldHideCameraOption, launchInAppCamera, showImagePicker]);
+    }, [icons.Camera, icons.Paperclip, icons.Gallery, showDocumentPicker, shouldHideGalleryOption, shouldHideCameraOption, showImagePicker]);
 
     const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: -1, maxIndex: menuItemData.length - 1, isActive: isVisible});
 
@@ -488,31 +467,6 @@ function AttachmentPicker({
         [handleImageProcessingError, shouldValidateImage, showGeneralAlert, showImageCorruptionAlert],
     );
 
-    const handleCameraCapture = useCallback(
-        (photos: CapturedPhoto[]) => {
-            setShowAttachmentCamera(false);
-            const assets: Asset[] = photos.map((photo) => ({
-                uri: photo.uri,
-                fileName: photo.fileName,
-                type: photo.type,
-                width: photo.width,
-                height: photo.height,
-            }));
-            Promise.resolve(pickAttachment(assets)).finally(() => {
-                onClosed.current();
-                delete onModalHide.current;
-            });
-        },
-        [pickAttachment],
-    );
-
-    const handleCameraClose = useCallback(() => {
-        setShowAttachmentCamera(false);
-        onCanceled.current();
-        onClosed.current();
-        delete onModalHide.current;
-    }, []);
-
     /**
      * Opens the attachment modal, or directly launches the document picker when shouldSkipAttachmentTypeModal is true.
      */
@@ -548,14 +502,6 @@ function AttachmentPicker({
      */
     const selectItem = useCallback(
         (item: Item) => {
-            /* Items with onPress (e.g. in-app camera) handle their own flow
-             * and don't go through the promise-based pickAttachment chain. */
-            if ('onPress' in item) {
-                close();
-                item.onPress();
-                return;
-            }
-
             onOpenPicker?.();
             /* setTimeout delays execution to the frame after the modal closes
              * without this on iOS closing the modal closes the gallery/camera as well */
@@ -632,11 +578,6 @@ function AttachmentPicker({
                     ))}
                 </View>
             </Popover>
-            <AttachmentCamera
-                isVisible={showAttachmentCamera}
-                onCapture={handleCameraCapture}
-                onClose={handleCameraClose}
-            />
             {renderChildren()}
         </>
     );
diff --git a/src/components/AttachmentPicker/launchCamera/launchCamera.android.ts b/src/components/AttachmentPicker/launchCamera/launchCamera.android.ts
new file mode 100644
index 000000000000..0f551d07019b
--- /dev/null
+++ b/src/components/AttachmentPicker/launchCamera/launchCamera.android.ts
@@ -0,0 +1,32 @@
+import {PermissionsAndroid} from 'react-native';
+import {launchCamera as launchCameraImagePicker} from 'react-native-image-picker';
+import type {LaunchCamera} from './types';
+import {ErrorLaunchCamera} from './types';
+
+/**
+ * Launching the camera for Android involves checking for permissions
+ * And only then starting the camera
+ * If the user deny permission the callback will be called with an error response
+ * in the same format as the error returned by react-native-image-picker
+ */
+const launchCamera: LaunchCamera = (options, callback) => {
+    // Checks current camera permissions and prompts the user in case they aren't granted
+    PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA)
+        .then((permission) => {
+            if (permission !== PermissionsAndroid.RESULTS.GRANTED) {
+                throw new ErrorLaunchCamera('User did not grant permissions', 'permission');
+            }
+
+            launchCameraImagePicker(options, callback);
+        })
+        .catch((error: ErrorLaunchCamera) => {
+            /* Intercept the permission error as well as any other errors and call the callback
+             * follow the same pattern expected for image picker results */
+            callback({
+                errorMessage: error.message,
+                errorCode: error.errorCode || 'others',
+            });
+        });
+};
+
+export default launchCamera;
diff --git a/src/components/AttachmentPicker/launchCamera/launchCamera.ios.ts b/src/components/AttachmentPicker/launchCamera/launchCamera.ios.ts
new file mode 100644
index 000000000000..c4983285b6c6
--- /dev/null
+++ b/src/components/AttachmentPicker/launchCamera/launchCamera.ios.ts
@@ -0,0 +1,32 @@
+import {launchCamera as launchCameraImagePicker} from 'react-native-image-picker';
+import {PERMISSIONS, request, RESULTS} from 'react-native-permissions';
+import type {LaunchCamera} from './types';
+import {ErrorLaunchCamera} from './types';
+
+/**
+ * Launching the camera for iOS involves checking for permissions
+ * And only then starting the camera
+ * If the user deny permission the callback will be called with an error response
+ * in the same format as the error returned by react-native-image-picker
+ */
+const launchCamera: LaunchCamera = (options, callback) => {
+    // Checks current camera permissions and prompts the user in case they aren't granted
+    request(PERMISSIONS.IOS.CAMERA)
+        .then((permission) => {
+            if (permission !== RESULTS.GRANTED) {
+                throw new ErrorLaunchCamera('User did not grant permissions', 'permission');
+            }
+
+            launchCameraImagePicker(options, callback);
+        })
+        .catch((error: ErrorLaunchCamera) => {
+            /* Intercept the permission error as well as any other errors and call the callback
+             * follow the same pattern expected for image picker results */
+            callback({
+                errorMessage: error.message,
+                errorCode: error.errorCode || 'others',
+            });
+        });
+};
+
+export default launchCamera;
diff --git a/src/components/AttachmentPicker/launchCamera/launchCamera.ts b/src/components/AttachmentPicker/launchCamera/launchCamera.ts
new file mode 100644
index 000000000000..dc1f921086de
--- /dev/null
+++ b/src/components/AttachmentPicker/launchCamera/launchCamera.ts
@@ -0,0 +1,3 @@
+import {launchCamera} from 'react-native-image-picker';
+
+export default launchCamera;
diff --git a/src/components/AttachmentPicker/launchCamera/types.ts b/src/components/AttachmentPicker/launchCamera/types.ts
new file mode 100644
index 000000000000..fee9268c2f98
--- /dev/null
+++ b/src/components/AttachmentPicker/launchCamera/types.ts
@@ -0,0 +1,109 @@
+/**
+ * A callback function used to handle the response from the image picker.
+ *
+ * @param response - The response object containing information about the picked images or any errors encountered.
+ */
+type Callback = (response: ImagePickerResponse) => void;
+
+type OptionsCommon = {
+    /** Specifies the type of media to be captured. */
+    mediaType: MediaType;
+    /** Specifies the maximum width of the media to be captured. */
+    maxWidth?: number;
+    /** Specifies the maximum height of the media to be captured. */
+    maxHeight?: number;
+    /** Specifies the quality of the photo to be captured. */
+    quality?: PhotoQuality;
+    /** Specifies the video quality for video capture. */
+    videoQuality?: AndroidVideoOptions | IOSVideoOptions;
+    /** Specifies whether to include the media in base64 format. */
+    includeBase64?: boolean;
+    /** Specifies whether to include extra information about the captured media. */
+    includeExtra?: boolean;
+    /** Specifies the presentation style for the media picker. */
+    presentationStyle?: 'currentContext' | 'fullScreen' | 'pageSheet' | 'formSheet' | 'popover' | 'overFullScreen' | 'overCurrentContext';
+};
+
+type CameraOptions = OptionsCommon & {
+    /** Specifies the maximum duration limit. */
+    durationLimit?: number;
+    /** Specifies whether to save captured media. */
+    saveToPhotos?: boolean;
+    /** Specifies the type of camera to be used. */
+    cameraType?: CameraType;
+};
+
+type Asset = {
+    /** Base64 representation of the asset. */
+    base64?: string;
+    /** URI pointing to the asset. */
+    uri?: string;
+    /** Width of the asset. */
+    width?: number;
+    /** Height of the asset. */
+    height?: number;
+    /** Size of the asset file in bytes. */
+    fileSize?: number;
+    /** Type of the asset. */
+    type?: string;
+    /** Name of the asset file. */
+    fileName?: string;
+    /** Duration of the asset. */
+    duration?: number;
+    /** Bitrate of the asset. */
+    bitrate?: number;
+    /** Timestamp of when the asset was created or modified. */
+    timestamp?: string;
+    /** ID of the asset. */
+    id?: string;
+};
+
+type ImagePickerResponse = {
+    /** Indicates whether the image picker operation was canceled. */
+    didCancel?: boolean;
+    /** The error code, if an error occurred during the image picking process. */
+    errorCode?: ErrorCode;
+    /** A descriptive error message, if an error occurred during the image picking process. */
+    errorMessage?: string;
+    /** An array of assets representing the picked images. */
+    assets?: Asset[];
+};
+
+/** Represents the quality options. */
+type PhotoQuality = 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1;
+
+/** Represents the type of camera to be used. */
+type CameraType = 'back' | 'front';
+
+/** Represents the type of media to be captured. */
+type MediaType = 'photo' | 'video' | 'mixed';
+
+/** Represents the quality options for video capture on Android devices. */
+type AndroidVideoOptions = 'low' | 'high';
+
+/** Represents the quality options for video capture on iOS devices. */
+type IOSVideoOptions = 'low' | 'medium' | 'high';
+
+/** Represents various error codes that may occur during camera operations. */
+type ErrorCode = 'camera_unavailable' | 'permission' | 'others';
+
+class ErrorLaunchCamera extends Error {
+    /** The error code associated with the error. */
+    errorCode: ErrorCode;
+
+    constructor(message: string, errorCode: ErrorCode) {
+        super(message);
+        this.errorCode = errorCode;
+    }
+}
+
+/**
+ * A function used to launch the camera with specified options and handle the callback.
+ *
+ * @param options - The options for the camera, specifying various settings.
+ * @param callback - The callback function to handle the response from the camera operation.
+ */
+type LaunchCamera = (options: CameraOptions, callback: Callback) => void;
+
+export {ErrorLaunchCamera};
+export type {LaunchCamera};
diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 441af58e797c..4b929e95dfec 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -37,7 +37,6 @@ import Building from '@assets/images/building.svg';
 import Buildings from '@assets/images/buildings.svg';
 import CalendarSolid from '@assets/images/calendar-solid.svg';
 import Calendar from '@assets/images/calendar.svg';
-import CameraFlip from '@assets/images/camera-flip.svg';
 import Camera from '@assets/images/camera.svg';
 import CarCircleSlash from '@assets/images/car-circle-slash.svg';
 import CarPlus from '@assets/images/car-plus.svg';
@@ -295,7 +294,6 @@ const Expensicons = {
     Buildings,
     Calendar,
     Camera,
-    CameraFlip,
     Car,
     CarPlus,
     Cash,
diff --git a/src/hooks/useNativeCamera.ts b/src/hooks/useNativeCamera.ts
index 4ca1913b8c10..f09d5a01fde0 100644
--- a/src/hooks/useNativeCamera.ts
+++ b/src/hooks/useNativeCamera.ts
@@ -1,5 +1,4 @@
 import {useFocusEffect} from '@react-navigation/core';
-import type React from 'react';
 import {useCallback, useRef, useState} from 'react';
 import {AppState} from 'react-native';
 import {Gesture} from 'react-native-gesture-handler';
@@ -67,7 +66,41 @@ function useNativeCamera({context, onFocusStart, onFocusCleanup}: UseNativeCamer
             });
     }, [translate]);
 
-    const {tapGesture, cameraFocusIndicatorAnimatedStyle} = useTapToFocusGesture(camera, device?.supportsFocus ?? false);
+    // Focus indicator animations
+    const focusIndicatorOpacity = useSharedValue(0);
+    const focusIndicatorScale = useSharedValue(2);
+    const focusIndicatorPosition = useSharedValue({x: 0, y: 0});
+
+    const cameraFocusIndicatorAnimatedStyle = useAnimatedStyle(() => ({
+        opacity: focusIndicatorOpacity.get(),
+        transform: [{translateX: focusIndicatorPosition.get().x}, {translateY: focusIndicatorPosition.get().y}, {scale: focusIndicatorScale.get()}],
+    }));
+
+    const focusCamera = useCallback((point: Point) => {
+        if (!camera.current) {
+            return;
+        }
+
+        camera.current.focus(point).catch((error: Record<string, unknown>) => {
+            if (error.message === '[unknown/unknown] Cancelled by another startFocusAndMetering()') {
+                return;
+            }
+            Log.warn('Error focusing camera', error);
+        });
+    }, []);
+
+    const tapGesture = Gesture.Tap()
+        .enabled(device?.supportsFocus ?? false)
+        .onStart((ev: {x: number; y: number}) => {
+            const point = {x: ev.x, y: ev.y};
+
+            focusIndicatorOpacity.set(withSequence(withTiming(0.8, {duration: 250}), withDelay(1000, withTiming(0, {duration: 250}))));
+            focusIndicatorScale.set(2);
+            focusIndicatorScale.set(withSpring(1, {damping: 10, stiffness: 200}));
+            focusIndicatorPosition.set(point);
+
+            scheduleOnRN(focusCamera, point);
+        });
 
     // Refresh camera permission on screen focus and app state changes
     useFocusEffect(
@@ -127,53 +160,4 @@ function useNativeCamera({context, onFocusStart, onFocusCleanup}: UseNativeCamer
     };
 }
 
-/**
- * Encapsulates tap-to-focus gesture handling for VisionCamera.
- * This hook reads camera refs inside gesture worklet callbacks, which is incompatible
- * with React Compiler's "no ref access during render" rule. Keeping it here (an already-
- * grandfathered file) avoids forcing callers to fail the compliance check.
- */
-function useTapToFocusGesture(cameraRef: React.RefObject<Camera | null>, supportsFocus: boolean) {
-    const focusIndicatorOpacity = useSharedValue(0);
-    const focusIndicatorScale = useSharedValue(2);
-    const focusIndicatorPosition = useSharedValue({x: 0, y: 0});
-
-    const cameraFocusIndicatorAnimatedStyle = useAnimatedStyle(() => ({
-        opacity: focusIndicatorOpacity.get(),
-        transform: [{translateX: focusIndicatorPosition.get().x}, {translateY: focusIndicatorPosition.get().y}, {scale: focusIndicatorScale.get()}],
-    }));
-
-    const focusCamera = useCallback(
-        (point: Point) => {
-            if (!cameraRef.current) {
-                return;
-            }
-
-            cameraRef.current.focus(point).catch((error: Record<string, unknown>) => {
-                if (error.message === '[unknown/unknown] Cancelled by another startFocusAndMetering()') {
-                    return;
-                }
-                Log.warn('Error focusing camera', error);
-            });
-        },
-        [cameraRef],
-    );
-
-    const tapGesture = Gesture.Tap()
-        .enabled(supportsFocus)
-        .onStart((ev: {x: number; y: number}) => {
-            const point = {x: ev.x, y: ev.y};
-
-            focusIndicatorOpacity.set(withSequence(withTiming(0.8, {duration: 250}), withDelay(1000, withTiming(0, {duration: 250}))));
-            focusIndicatorScale.set(2);
-            focusIndicatorScale.set(withSpring(1, {damping: 10, stiffness: 200}));
-            focusIndicatorPosition.set(point);
-
-            scheduleOnRN(focusCamera, point);
-        });
-
-    return {tapGesture, cameraFocusIndicatorAnimatedStyle};
-}
-
 export default useNativeCamera;
-export {useTapToFocusGesture};
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 4fe30524d50c..7f81100e14e9 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1138,7 +1138,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Lass es los',
         dropMessage: 'Datei hierher ziehen',
         flash: 'Blitz',
-        flipCamera: 'Kamera wechseln',
         multiScan: 'Mehrfachscan',
         shutter: 'Verschluss',
         gallery: 'Galerie',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 1296dd92ea6a..44b28481b573 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1193,7 +1193,6 @@ const translations = {
         dropTitle: 'Let it go',
         dropMessage: 'Drop your file here',
         flash: 'flash',
-        flipCamera: 'Flip camera',
         multiScan: 'multi-scan',
         shutter: 'shutter',
         gallery: 'gallery',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 85a1bf127a7f..f41c9347abf1 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1093,7 +1093,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Suéltalo',
         dropMessage: 'Suelta tu archivo aquí',
         flash: 'flash',
-        flipCamera: 'Cambiar cámara',
         multiScan: 'escaneo múltiple',
         shutter: 'obturador',
         gallery: 'galería',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 102aea456d28..162b4c975091 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1142,7 +1142,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Laisse tomber',
         dropMessage: 'Déposez votre fichier ici',
         flash: 'flash',
-        flipCamera: 'Retourner la caméra',
         multiScan: 'numérisation multiple',
         shutter: 'obturateur',
         gallery: 'galerie',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 998f94c40cc6..eab759e12605 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1138,7 +1138,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Lascia perdere',
         dropMessage: 'Rilascia qui il tuo file',
         flash: 'flash',
-        flipCamera: 'Cambia fotocamera',
         multiScan: 'scansione multipla',
         shutter: 'otturatore',
         gallery: 'galleria',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 44147c14b2dc..d62c5b3a1f23 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1121,7 +1121,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: '手放して',
         dropMessage: 'ここにファイルをドロップしてください',
         flash: 'フラッシュ',
-        flipCamera: 'カメラ切替',
         multiScan: 'マルチスキャン',
         shutter: 'シャッター',
         gallery: 'ギャラリー',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index e25120feabc4..b8a01b8f42df 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1136,7 +1136,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Laat het los',
         dropMessage: 'Zet je bestand hier neer',
         flash: 'flits',
-        flipCamera: 'Camera wisselen',
         multiScan: 'meerscannen',
         shutter: 'sluiter',
         gallery: 'galerij',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index aead035a6652..5a74c77283a4 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1136,7 +1136,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Odpuść to',
         dropMessage: 'Upuść tutaj plik',
         flash: 'błysk',
-        flipCamera: 'Przełącz kamerę',
         multiScan: 'wielokrotne skanowanie',
         shutter: 'migawka',
         gallery: 'galeria',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index d3e252e9753d..bc27e739a602 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1136,7 +1136,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: 'Deixe pra lá',
         dropMessage: 'Solte seu arquivo aqui',
         flash: 'flash',
-        flipCamera: 'Alternar câmera',
         multiScan: 'escaneamento múltiplo',
         shutter: 'obturador',
         gallery: 'galeria',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index d8869fcbe88e..3a839453946b 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1100,7 +1100,6 @@ const translations: TranslationDeepObject<typeof en> = {
         dropTitle: '随它去',
         dropMessage: '将文件拖放到此处',
         flash: '闪光',
-        flipCamera: '切换相机',
         multiScan: '多重扫描',
         shutter: '快门',
         gallery: '图库',
