feat(map): preview mode + inline rename + floating actions tweaks

Comportement 2-clicks sur la liste des scans :
- 1er clic : map zoom sur le scan + sheet snap au plus bas + tile preview
  unique avec hint 'Appuyez à nouveau pour voir les détails'
- 2e clic même scan : navigate vers ScanDetail
- Clic autre scan en preview : switch preview + zoom

Rename inline dans le BottomSheet existant (plus de 2e sheet superposé) :
- Bouton retour (ChevronLeft) au lieu de croix
- Form (BottomSheetTextInput) avec keyboardBehavior='interactive' +
  android_keyboardInputMode='adjustResize' pour ne pas masquer l'input
- Boutons Annuler/Enregistrer avec icônes (X / Check), border 1.5px primary,
  shadow primary[900] sur le Save, minHeight 56px
- snapToIndex(2) à l'ouverture du form (85%) puis snapToIndex(0) après
  save/cancel pour redonner la map à voir
- containerStyle { zIndex:100, elevation:100 } pour passer au-dessus des
  FloatingActions quand le sheet s'expand

FloatingActions : couleur d'icône via prop color (className n'est pas
supporté pour la couleur sur lucide-react-native sans cssInterop).

actionsSlot : zIndex/elevation 1 pour passer derrière le sheet expanded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yanis 2026-05-01 00:03:18 +02:00
parent 7457e64996
commit 98c446cd35
3 changed files with 322 additions and 180 deletions

View file

@ -1,4 +1,5 @@
import { View, Pressable, StyleSheet } from "react-native"; import React from "react";
import { View, Pressable } from "react-native";
import { Layers, LocateFixed, Satellite } from "lucide-react-native"; import { Layers, LocateFixed, Satellite } from "lucide-react-native";
import { colors } from "@/theme/colors"; import { colors } from "@/theme/colors";
@ -12,6 +13,10 @@ interface FloatingActionsProps {
activeAction?: FloatingActionId; activeAction?: FloatingActionId;
} }
function getIconColor(isActive: boolean) {
return isActive ? "#FFFFFF" : colors.primary[800];
}
export function FloatingActions({ export function FloatingActions({
onLayers, onLayers,
onLocate, onLocate,
@ -19,25 +24,27 @@ export function FloatingActions({
activeAction, activeAction,
}: FloatingActionsProps) { }: FloatingActionsProps) {
return ( return (
<View style={styles.column} collapsable={false}> <View className="gap-3 shadow-2xl" collapsable={false}>
<ActionButton active={activeAction === "layers"} onPress={onLayers}> <ActionButton active={activeAction === "layers"} onPress={onLayers}>
<Layers <Layers
size={22} size={20}
color={activeAction === "layers" ? "#FFFFFF" : colors.primary[800]} color={getIconColor(activeAction === "layers")}
strokeWidth={2.2} strokeWidth={2.2}
/> />
</ActionButton> </ActionButton>
<ActionButton active={activeAction === "locate"} onPress={onLocate}> <ActionButton active={activeAction === "locate"} onPress={onLocate}>
<LocateFixed <LocateFixed
size={22} size={20}
color={activeAction === "locate" ? "#FFFFFF" : colors.primary[800]} color={getIconColor(activeAction === "locate")}
strokeWidth={2.2} strokeWidth={2.2}
/> />
</ActionButton> </ActionButton>
<ActionButton active={activeAction === "satellite"} onPress={onSatellite}> <ActionButton active={activeAction === "satellite"} onPress={onSatellite}>
<Satellite <Satellite
size={22} size={20}
color={activeAction === "satellite" ? "#FFFFFF" : colors.primary[800]} color={getIconColor(activeAction === "satellite")}
strokeWidth={2.2} strokeWidth={2.2}
/> />
</ActionButton> </ActionButton>
@ -55,45 +62,14 @@ function ActionButton({ children, onPress, active }: ActionButtonProps) {
return ( return (
<Pressable <Pressable
onPress={onPress} onPress={onPress}
className={`w-10 h-10 rounded-full items-center justify-center shadow-lg ${
active ? "bg-primary" : "bg-card border border-border"
}`}
style={({ pressed }) => [ style={({ pressed }) => [
styles.button, { transform: [{ scale: pressed ? 0.95 : 1 }] },
active ? styles.buttonActive : styles.buttonInactive,
pressed && { transform: [{ scale: 0.95 }] },
]} ]}
> >
{children} {children}
</Pressable> </Pressable>
); );
} }
const styles = StyleSheet.create({
column: {
gap: 12,
elevation: 24,
},
button: {
width: 56,
height: 56,
borderRadius: 999,
alignItems: "center",
justifyContent: "center",
},
buttonInactive: {
backgroundColor: "#FFFFFF",
borderWidth: 1,
borderColor: "#E5E7EB",
shadowColor: "#000",
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.18,
shadowRadius: 12,
elevation: 24,
},
buttonActive: {
backgroundColor: colors.primary[900],
shadowColor: colors.primary[900],
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.3,
shadowRadius: 12,
elevation: 24,
},
});

View file

@ -1,17 +1,25 @@
import { forwardRef, useMemo, useState } from "react"; import {
forwardRef,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from "react";
import { import {
View, View,
Pressable, Pressable,
StyleSheet, StyleSheet,
Modal, Text as RNText,
TextInput,
KeyboardAvoidingView,
Platform,
} from "react-native"; } from "react-native";
import BottomSheet, { BottomSheetScrollView } from "@gorhom/bottom-sheet"; import BottomSheet, {
BottomSheetScrollView,
BottomSheetTextInput,
} from "@gorhom/bottom-sheet";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import {
ChevronRight, ChevronRight,
ChevronLeft,
AlertTriangle, AlertTriangle,
Leaf, Leaf,
Clock, Clock,
@ -19,6 +27,7 @@ import {
X, X,
ScanLine, ScanLine,
MapPin, MapPin,
Check,
} from "lucide-react-native"; } from "lucide-react-native";
import { Text } from "@/components/ui/text"; import { Text } from "@/components/ui/text";
@ -29,6 +38,8 @@ import type { ScanRecord, ScanStatus } from "@/types/detection";
interface MapBottomSheetProps { interface MapBottomSheetProps {
scans: ScanRecord[]; scans: ScanRecord[];
previewScan?: ScanRecord | null;
onPreviewClose?: () => void;
onScanPress?: (scan: ScanRecord) => void; onScanPress?: (scan: ScanRecord) => void;
onRename?: (scanId: string, newName: string) => void; onRename?: (scanId: string, newName: string) => void;
onScanCta?: () => void; onScanCta?: () => void;
@ -36,15 +47,49 @@ interface MapBottomSheetProps {
} }
export const MapBottomSheet = forwardRef<BottomSheet, MapBottomSheetProps>( export const MapBottomSheet = forwardRef<BottomSheet, MapBottomSheetProps>(
function MapBottomSheet({ scans, onScanPress, onRename, onScanCta, defaultIndex = 0 }, ref) { function MapBottomSheet(
{
scans,
previewScan,
onPreviewClose,
onScanPress,
onRename,
onScanCta,
defaultIndex = 0,
},
ref,
) {
const { t } = useTranslation(); const { t } = useTranslation();
const snapPoints = useMemo(() => ["20%", "55%", "85%"], []); const snapPoints = useMemo(() => ["20%", "55%", "85%"], []);
const internalRef = useRef<BottomSheet>(null);
const [renamingScan, setRenamingScan] = useState<ScanRecord | null>(null); const [renamingScan, setRenamingScan] = useState<ScanRecord | null>(null);
const [draftName, setDraftName] = useState(""); const [draftName, setDraftName] = useState("");
useImperativeHandle(
ref,
() =>
({
snapToIndex: (i: number) => internalRef.current?.snapToIndex(i),
snapToPosition: (p: number | string) =>
internalRef.current?.snapToPosition(p),
expand: () => internalRef.current?.expand(),
collapse: () => internalRef.current?.collapse(),
close: () => internalRef.current?.close(),
forceClose: () => internalRef.current?.forceClose(),
}) as BottomSheet,
[],
);
useEffect(() => {
if (renamingScan) {
setDraftName(getScanDisplayName(renamingScan, t));
}
}, [renamingScan, t]);
function handleStartRename(scan: ScanRecord) { function handleStartRename(scan: ScanRecord) {
setRenamingScan(scan); setRenamingScan(scan);
setDraftName(getScanDisplayName(scan, t)); // remonte à 85% pour bien voir l'input + boutons au-dessus du clavier
internalRef.current?.snapToIndex(2);
} }
function handleConfirmRename() { function handleConfirmRename() {
@ -53,31 +98,137 @@ export const MapBottomSheet = forwardRef<BottomSheet, MapBottomSheetProps>(
} }
setRenamingScan(null); setRenamingScan(null);
setDraftName(""); setDraftName("");
// redescend pour voir la map
internalRef.current?.snapToIndex(0);
} }
function handleCancelRename() { function handleCancelRename() {
setRenamingScan(null); setRenamingScan(null);
setDraftName(""); setDraftName("");
// redescend pour voir la map
internalRef.current?.snapToIndex(0);
} }
return ( return (
<> <>
<BottomSheet <BottomSheet
ref={ref} ref={internalRef}
index={defaultIndex} index={defaultIndex}
snapPoints={snapPoints} snapPoints={snapPoints}
handleIndicatorStyle={styles.handleIndicator} handleIndicatorStyle={styles.handleIndicator}
backgroundStyle={styles.background} backgroundStyle={styles.background}
containerStyle={styles.sheetContainer}
enableDynamicSizing={false}
enablePanDownToClose={false} enablePanDownToClose={false}
keyboardBehavior="interactive"
keyboardBlurBehavior="restore"
android_keyboardInputMode="adjustResize"
> >
<View style={styles.header}> {renamingScan ? (
<Text style={styles.title}>{t("map.scannedPlants")}</Text> <BottomSheetScrollView
<Text style={styles.count}> contentContainerStyle={[
{t("map.plantCount", { count: scans.length })} styles.renameWrap,
</Text> { paddingBottom: 24 },
</View> ]}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<View style={styles.renameHeader}>
<Pressable
onPress={handleCancelRename}
hitSlop={10}
style={styles.backBtn}
>
<ChevronLeft size={20} color={colors.neutral[700]} />
</Pressable>
<Text style={styles.title}>{t("map.rename.title")}</Text>
<View style={styles.backBtnPlaceholder} />
</View>
<Text style={styles.renameSubtitle}>
{t("map.rename.subtitle")}
</Text>
<BottomSheetTextInput
value={draftName}
onChangeText={setDraftName}
placeholder={t("map.rename.placeholder")}
placeholderTextColor={colors.neutral[400]}
autoFocus
maxLength={64}
returnKeyType="done"
onSubmitEditing={handleConfirmRename}
style={styles.renameInput}
/>
<View style={styles.renameActions}>
<Pressable
onPress={handleCancelRename}
style={({ pressed }) => [
styles.renameBtn,
styles.renameBtnGhost,
pressed && { opacity: 0.7 },
]}
>
<View style={styles.renameBtnInner}>
<X
size={18}
color={colors.neutral[800]}
strokeWidth={2.4}
/>
<RNText style={styles.renameBtnGhostLabel}>
{t("common.cancel")}
</RNText>
</View>
</Pressable>
<Pressable
onPress={handleConfirmRename}
style={({ pressed }) => [
styles.renameBtn,
styles.renameBtnPrimary,
pressed && { opacity: 0.85 },
]}
>
<View style={styles.renameBtnInner}>
<Check size={18} color="#FFFFFF" strokeWidth={2.6} />
<RNText style={styles.renameBtnPrimaryLabel}>
{t("map.rename.save")}
</RNText>
</View>
</Pressable>
</View>
</BottomSheetScrollView>
) : previewScan ? (
<View>
<View style={styles.previewHeader}>
<Text style={styles.title}>{t("map.preview.title")}</Text>
<Pressable
onPress={onPreviewClose}
hitSlop={10}
style={styles.previewCloseBtn}
>
<X size={18} color={colors.neutral[600]} />
</Pressable>
</View>
<View style={styles.previewBody}>
<ScanRow
scan={previewScan}
isLast
onPress={() => onScanPress?.(previewScan)}
onEdit={() => handleStartRename(previewScan)}
/>
<Text style={styles.previewHint}>
{t("map.preview.tapHint")}
</Text>
</View>
</View>
) : (
<>
<View style={styles.header}>
<Text style={styles.title}>{t("map.scannedPlants")}</Text>
<Text style={styles.count}>
{t("map.plantCount", { count: scans.length })}
</Text>
</View>
{scans.length === 0 ? ( {scans.length === 0 ? (
<View style={styles.emptyState}> <View style={styles.emptyState}>
<View style={styles.emptyIconWrap}> <View style={styles.emptyIconWrap}>
<MapPin size={32} color={colors.primary[800]} strokeWidth={2} /> <MapPin size={32} color={colors.primary[800]} strokeWidth={2} />
@ -112,68 +263,10 @@ export const MapBottomSheet = forwardRef<BottomSheet, MapBottomSheetProps>(
/> />
))} ))}
</BottomSheetScrollView> </BottomSheetScrollView>
)}
</>
)} )}
</BottomSheet> </BottomSheet>
<Modal
visible={renamingScan !== null}
transparent
animationType="fade"
onRequestClose={handleCancelRename}
>
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : undefined}
style={styles.modalOverlay}
>
<Pressable style={styles.modalBackdrop} onPress={handleCancelRename} />
<View style={styles.modalCard}>
<View style={styles.modalHeader}>
<Text style={styles.modalTitle}>{t("map.rename.title")}</Text>
<Pressable onPress={handleCancelRename} hitSlop={10}>
<X size={20} color={colors.neutral[600]} />
</Pressable>
</View>
<Text style={styles.modalSubtitle}>{t("map.rename.subtitle")}</Text>
<TextInput
style={styles.modalInput}
value={draftName}
onChangeText={setDraftName}
placeholder={t("map.rename.placeholder")}
placeholderTextColor={colors.neutral[400]}
autoFocus
maxLength={64}
returnKeyType="done"
onSubmitEditing={handleConfirmRename}
/>
<View style={styles.modalActions}>
<Pressable
onPress={handleCancelRename}
style={({ pressed }) => [
styles.modalButton,
styles.modalButtonGhost,
pressed && { opacity: 0.7 },
]}
>
<Text style={styles.modalButtonGhostLabel}>
{t("common.cancel")}
</Text>
</Pressable>
<Pressable
onPress={handleConfirmRename}
style={({ pressed }) => [
styles.modalButton,
styles.modalButtonPrimary,
pressed && { opacity: 0.85 },
]}
>
<Text style={styles.modalButtonPrimaryLabel}>
{t("map.rename.save")}
</Text>
</Pressable>
</View>
</View>
</KeyboardAvoidingView>
</Modal>
</> </>
); );
} }
@ -235,6 +328,10 @@ function ScanRow({ scan, isLast, onPress, onEdit }: ScanRowProps) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
sheetContainer: {
zIndex: 100,
elevation: 100,
},
background: { background: {
backgroundColor: "#FFFFFF", backgroundColor: "#FFFFFF",
borderTopLeftRadius: 28, borderTopLeftRadius: 28,
@ -258,6 +355,34 @@ const styles = StyleSheet.create({
paddingTop: 8, paddingTop: 8,
paddingBottom: 12, paddingBottom: 12,
}, },
previewHeader: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: 20,
paddingTop: 8,
paddingBottom: 4,
},
previewCloseBtn: {
width: 32,
height: 32,
borderRadius: 999,
alignItems: "center",
justifyContent: "center",
backgroundColor: colors.neutral[100],
},
previewBody: {
paddingHorizontal: 20,
paddingBottom: 20,
gap: 8,
},
previewHint: {
fontSize: 12,
fontWeight: "500",
color: colors.neutral[500],
textAlign: "center",
paddingTop: 4,
},
title: { title: {
fontSize: 18, fontSize: 18,
fontWeight: "700", fontWeight: "700",
@ -359,75 +484,91 @@ const styles = StyleSheet.create({
fontSize: 14, fontSize: 14,
fontWeight: "600", fontWeight: "600",
}, },
modalOverlay: { // Rename inline form
flex: 1, renameWrap: {
justifyContent: "center", paddingHorizontal: 20,
alignItems: "center", paddingTop: 4,
paddingHorizontal: 24, paddingBottom: 24,
},
modalBackdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: "rgba(0,0,0,0.45)",
},
modalCard: {
width: "100%",
maxWidth: 400,
backgroundColor: "#FFFFFF",
borderRadius: 24,
padding: 20,
gap: 12, gap: 12,
}, },
modalHeader: { renameHeader: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
}, },
modalTitle: { backBtn: {
fontSize: 18, width: 36,
fontWeight: "700", height: 36,
color: colors.neutral[900], borderRadius: 999,
alignItems: "center",
justifyContent: "center",
backgroundColor: colors.neutral[100],
}, },
modalSubtitle: { backBtnPlaceholder: {
width: 36,
height: 36,
},
renameSubtitle: {
fontSize: 13, fontSize: 13,
color: colors.neutral[600], color: colors.neutral[600],
lineHeight: 18, lineHeight: 18,
paddingHorizontal: 4,
}, },
modalInput: { renameInput: {
borderWidth: 1, borderWidth: 1,
borderColor: colors.neutral[300], borderColor: colors.neutral[300],
borderRadius: 12, borderRadius: 14,
paddingHorizontal: 14, paddingHorizontal: 14,
paddingVertical: 12, paddingVertical: 14,
fontSize: 15, fontSize: 16,
color: colors.neutral[900], color: colors.neutral[900],
backgroundColor: "#FAFAFA", backgroundColor: "#FAFAFA",
}, },
modalActions: { renameActions: {
flexDirection: "row", flexDirection: "row",
gap: 10, paddingTop: 16,
marginTop: 4, gap: 12,
}, },
modalButton: { renameBtn: {
flex: 1, flexGrow: 1,
paddingVertical: 12, flexShrink: 1,
borderRadius: 12, flexBasis: 0,
paddingVertical: 16,
paddingHorizontal: 12,
borderRadius: 14,
minHeight: 56,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}, },
modalButtonGhost: { renameBtnInner: {
backgroundColor: colors.neutral[100], flexDirection: "row",
alignItems: "center",
}, },
modalButtonGhostLabel: { renameBtnGhost: {
fontSize: 15, backgroundColor: colors.neutral[200],
fontWeight: "600", borderWidth: 1.5,
borderColor: colors.neutral[400],
},
renameBtnGhostLabel: {
fontSize: 16,
fontWeight: "700",
color: colors.neutral[800], color: colors.neutral[800],
letterSpacing: 0.2,
marginLeft: 8,
}, },
modalButtonPrimary: { renameBtnPrimary: {
backgroundColor: colors.primary[800], backgroundColor: colors.primary[800],
shadowColor: colors.primary[900],
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 4,
}, },
modalButtonPrimaryLabel: { renameBtnPrimaryLabel: {
fontSize: 15, fontSize: 16,
fontWeight: "600", fontWeight: "700",
color: "#FFFFFF", color: "#FFFFFF",
letterSpacing: 0.2,
marginLeft: 8,
}, },
}); });

View file

@ -8,7 +8,11 @@ import { LinearGradient } from "expo-linear-gradient";
import { toast } from "sonner-native"; import { toast } from "sonner-native";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { VineyardMapView, type VineyardMapHandle, type MapRegion } from "@/components/map/MapView"; import {
VineyardMapView,
type VineyardMapHandle,
type MapRegion,
} from "@/components/map/MapView";
import { FloatingSearch } from "@/components/map/FloatingSearch"; import { FloatingSearch } from "@/components/map/FloatingSearch";
import { FloatingActions } from "@/components/map/FloatingActions"; import { FloatingActions } from "@/components/map/FloatingActions";
import { MapBottomSheet } from "@/components/map/MapBottomSheet"; import { MapBottomSheet } from "@/components/map/MapBottomSheet";
@ -27,8 +31,12 @@ const DEFAULT_REGION: MapRegion = {
longitudeDelta: 0.12, longitudeDelta: 0.12,
}; };
function hasLocation(scan: ScanRecord): scan is ScanRecord & { latitude: number; longitude: number } { function hasLocation(
return typeof scan.latitude === "number" && typeof scan.longitude === "number"; scan: ScanRecord,
): scan is ScanRecord & { latitude: number; longitude: number } {
return (
typeof scan.latitude === "number" && typeof scan.longitude === "number"
);
} }
function computeInitialRegion(scans: ScanRecord[]): MapRegion { function computeInitialRegion(scans: ScanRecord[]): MapRegion {
@ -67,18 +75,27 @@ export default function MapScreen() {
const geojsonCache = useRef<Map<string, object>>(new Map()); const geojsonCache = useRef<Map<string, object>>(new Map());
const activeFilterRef = useRef<string | null>(null); const activeFilterRef = useRef<string | null>(null);
const [activeFilter, setActiveFilter] = useState<string | null>(null); const [activeFilter, setActiveFilter] = useState<string | null>(null);
const [previewScan, setPreviewScan] = useState<ScanRecord | null>(null);
activeFilterRef.current = activeFilter; activeFilterRef.current = activeFilter;
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
reload(); reload();
}, [reload]) }, [reload]),
); );
const locatedScans = useMemo(() => history.filter(hasLocation), [history]); const locatedScans = useMemo(() => history.filter(hasLocation), [history]);
const initialRegion = useMemo(() => computeInitialRegion(history), [history]); const initialRegion = useMemo(() => computeInitialRegion(history), [history]);
function handleScanPress(scan: ScanRecord) { function handleScanPress(scan: ScanRecord) {
// 2nd click on the same scan in preview → open detail
if (previewScan?.id === scan.id) {
setPreviewScan(null);
navigation.navigate("ScanDetail", { scanId: scan.id });
return;
}
// 1st click (or click on a different scan) → preview mode
if (hasLocation(scan)) { if (hasLocation(scan)) {
mapRef.current?.animateToRegion({ mapRef.current?.animateToRegion({
latitude: scan.latitude, latitude: scan.latitude,
@ -89,7 +106,12 @@ export default function MapScreen() {
} }
setActiveFilter(null); setActiveFilter(null);
mapRef.current?.highlightGeoJSON(null); mapRef.current?.highlightGeoJSON(null);
navigation.navigate("ScanDetail", { scanId: scan.id }); setPreviewScan(scan);
sheetRef.current?.snapToIndex(0);
}
function handlePreviewClose() {
setPreviewScan(null);
} }
async function handleLocateUser() { async function handleLocateUser() {
@ -183,18 +205,12 @@ export default function MapScreen() {
pointerEvents="box-none" pointerEvents="box-none"
collapsable={false} collapsable={false}
> >
<FloatingSearch activeFilter={activeFilter} onFilterPress={handleFilterPress} /> <FloatingSearch
activeFilter={activeFilter}
onFilterPress={handleFilterPress}
/>
</View> </View>
<MapBottomSheet
ref={sheetRef}
scans={locatedScans}
onScanPress={handleScanPress}
onRename={handleRename}
onScanCta={() => navigation.navigate("Main", { screen: "Scanner" })}
defaultIndex={isEmpty ? 1 : 0}
/>
<View <View
style={styles.actionsSlot} style={styles.actionsSlot}
pointerEvents="box-none" pointerEvents="box-none"
@ -207,6 +223,17 @@ export default function MapScreen() {
activeAction={activeFilter === "myLocation" ? "locate" : "layers"} activeAction={activeFilter === "myLocation" ? "locate" : "layers"}
/> />
</View> </View>
<MapBottomSheet
ref={sheetRef}
scans={locatedScans}
previewScan={previewScan}
onPreviewClose={handlePreviewClose}
onScanPress={handleScanPress}
onRename={handleRename}
onScanCta={() => navigation.navigate("Main", { screen: "Scanner" })}
defaultIndex={isEmpty ? 1 : 0}
/>
</View> </View>
); );
} }
@ -228,14 +255,12 @@ const styles = StyleSheet.create({
left: 0, left: 0,
right: 0, right: 0,
paddingHorizontal: 16, paddingHorizontal: 16,
zIndex: 20,
elevation: 24,
}, },
actionsSlot: { actionsSlot: {
position: "absolute", position: "absolute",
right: 16, right: 16,
top: "30%", top: "30%",
zIndex: 20, zIndex: 1,
elevation: 24, elevation: 1,
}, },
}); });