diff --git a/App.tsx b/App.tsx index f0bb21f..421f062 100644 --- a/App.tsx +++ b/App.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef, useCallback } from 'react'; -import { View, StatusBar, Alert, ActivityIndicator, Text, AppState, Platform } from 'react-native'; +import { View, StatusBar, Alert, ActivityIndicator, Text, AppState, Platform, Keyboard } from 'react-native'; import { useCameraPermission, usePhotoOutput } from 'react-native-vision-camera'; import * as ImagePicker from 'expo-image-picker'; import * as FileSystem from 'expo-file-system/legacy'; @@ -49,6 +49,19 @@ export default function App() { // the hardware AE bias right before each capture (live slider drags never // touch the hardware — that flashed the Xiaomi preview). const viewfinderRef = useRef(null); + // Edge-to-edge (app.json/gradle edgeToEdgeEnabled) makes Android ignore the + // manifest's adjustResize, so the OS never shrinks the window for the IME and + // the bottom deck stays under the keyboard. Track the IME height ourselves and + // lift the deck by it (covers the custom-watermark text input). + const [keyboardHeight, setKeyboardHeight] = useState(0); + useEffect(() => { + const show = Keyboard.addListener('keyboardDidShow', (e) => setKeyboardHeight(e.endCoordinates.height)); + const hide = Keyboard.addListener('keyboardDidHide', () => setKeyboardHeight(0)); + return () => { + show.remove(); + hide.remove(); + }; + }, []); const [recipes, setRecipes] = useState([]); const [selectedRecipe, setSelectedRecipe] = useState(null); @@ -924,7 +937,7 @@ export default function App() { {/* Bottom deck: chip panel (progressive disclosure) -> tool rail -> shutter */} - + {openTab !== null && (