import React, { useState } from 'react';
import { View, Text, TouchableOpacity, TextInput, Modal, KeyboardAvoidingView, Platform, Alert } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Plus, Pencil, Undo2, Zap, ZapOff } from 'lucide-react-native';
import * as Haptics from 'expo-haptics';
import type { FlashMode } from '../types';
// "A" badge tucked into the corner of the flash button's AUTO state.
const FLASH_A_BADGE = {
position: 'absolute' as const,
bottom: 3,
right: 5,
fontSize: 8,
fontWeight: '700' as const,
color: '#f4f4f5',
};
interface TopBarProps {
mode: 'camera' | 'library';
recipeName: string;
onSaveRecipe: (name: string) => void;
// Present only when the active recipe is user-created: enables Save (overwrite).
onOverwriteRecipe?: (name: string) => void;
// Also custom-only: opens the recipe editor — the CREATE form prefilled
// with this recipe's parameters and name.
onEditRecipe?: () => void;
// SAVE & SHARE -> EXPORT: write this look to an encrypted recipe file and
// hand it to the system share sheet so it can reach another phone.
onExportShare: (name: string) => void;
// BACK (undo): one step back through the look's history. PRO only — App
// refuses and offers the paywall when a LITE build taps it. No count is
// drawn: the icon turns amber while there is a step to go back to.
onUndo: () => void;
undoDepth: number;
// LED flash state for the next still, cycled off -> auto -> on. Absent =
// no flash control to show (library mode, or a lens with no flash unit),
// so the front camera shows no dead control.
flashMode?: FlashMode;
onCycleFlash?: () => void;
// Height of the floating top strip (its own onLayout): App keeps the library
// photo — and with it the ratio band — out from under it.
onHeight?: (height: number) => void;
}
export default function TopBar({
mode,
recipeName,
onSaveRecipe,
onOverwriteRecipe,
onEditRecipe,
onExportShare,
onUndo,
undoDepth,
flashMode,
onCycleFlash,
onHeight,
}: TopBarProps) {
const insets = useSafeAreaInsets();
const [modalVisible, setModalVisible] = useState(false);
const [newRecipeName, setNewRecipeName] = useState('');
const openModal = () => {
// Bundled recipes are read-only -> Save As only, blank name. Custom ones
// prefill with the current name so Save (overwrite) is one tap.
setNewRecipeName(onOverwriteRecipe ? recipeName : '');
setModalVisible(true);
};
// SAVE & SHARE: two ways out of the same look — keep it as a recipe on this
// phone, or export it as a file another phone can import.
const openSaveMenu = () => {
Alert.alert(
'SAVE & SHARE',
'Save the look on this screen as a recipe, or export it as a file to share.',
[
{ text: 'CANCEL', style: 'cancel' },
{ text: 'EXPORT & SHARE', onPress: () => onExportShare(recipeName) },
{ text: 'SAVE RECIPE', onPress: openModal },
],
);
};
const run = (fn: (name: string) => void) => {
const name = newRecipeName.trim();
if (!name) return;
fn(name);
setNewRecipeName('');
setModalVisible(false);
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
};
const handleSavePress = () => run(onSaveRecipe);
const handleOverwritePress = () => onOverwriteRecipe && run(onOverwriteRecipe);
return (
<>
onHeight?.(e.nativeEvent.layout.height)}
className="absolute top-0 left-0 right-0 z-20 flex-row items-start justify-between px-4"
>
{mode === 'camera' ? 'LIVE' : 'LIBRARY'}
{recipeName}
{/* Capture-time LED flash, left of BACK: a still taken on the 0.5x
native lens goes through its own Camera2 request, so the state
has to be reachable while the chip row is off screen. */}
{flashMode && onCycleFlash ? (
{flashMode === 'off' ? (
) : (
// AUTO keeps the bolt dim and adds the badge below — a lit
// bolt alone would read as ON.
)}
{flashMode === 'auto' ? A : null}
) : null}
{/* BACK: the history control the chip row used to carry, sitting
between the status block and SAVE & SHARE. Lucide (ISC) vector
— no icon font to ship or license. */}
0 ? '#f59e0b' : '#52525b'} />
{onEditRecipe && (
)}
SAVE & SHARE
setModalVisible(false)}
>
{onOverwriteRecipe ? 'SAVE RECIPE' : 'SAVE CURRENT AS RECIPE'}
setModalVisible(false)}
className="flex-1 bg-zinc-800 py-3 rounded-lg items-center"
>
CANCEL
{onOverwriteRecipe ? (
<>
SAVE AS
SAVE
>
) : (
SAVE RECIPE
)}
>
);
}