Sell PRO as an in-app unlock, take shared photos, and let FX run negative

- One free Play app (com.locphamtran.recipescamera) with an expo-iap PRO
  unlock, replacing the paid apk for the store channel
- Android SEND/SEND_MULTIPLE share target feeds photos into the editor,
  on cold start and on resume
- BACK button in the TopBar and press-and-hold PEEK replace the chip row
- NOISE REDUCTION and SHARPENING accept -10: a negative SHARPENING softens
  the frame before the grain pass, a negative NOISE REDUCTION re-grains it,
  in the Skia engine, the live preview and the Kotlin export path alike
This commit is contained in:
2026-09-16 06:48:22 +07:00
parent 27a9dfb65f
commit a85ebf0a81
21 changed files with 860 additions and 183 deletions
+27 -2
View File
@@ -1,7 +1,7 @@
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 } from 'lucide-react-native';
import { Plus, Pencil, Undo2 } from 'lucide-react-native';
import * as Haptics from 'expo-haptics';
interface TopBarProps {
@@ -16,9 +16,23 @@ interface TopBarProps {
// 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;
}
export default function TopBar({ mode, recipeName, onSaveRecipe, onOverwriteRecipe, onEditRecipe, onExportShare }: TopBarProps) {
export default function TopBar({
mode,
recipeName,
onSaveRecipe,
onOverwriteRecipe,
onEditRecipe,
onExportShare,
onUndo,
undoDepth,
}: TopBarProps) {
const insets = useSafeAreaInsets();
const [modalVisible, setModalVisible] = useState(false);
const [newRecipeName, setNewRecipeName] = useState('');
@@ -75,6 +89,17 @@ export default function TopBar({ mode, recipeName, onSaveRecipe, onOverwriteReci
</View>
<View className="flex-row items-center space-x-2">
{/* 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. */}
<TouchableOpacity
onPress={onUndo}
accessibilityLabel="BACK"
className="rounded-full border border-zinc-700/80 bg-black/45 p-2.5"
activeOpacity={0.7}
>
<Undo2 size={13} color={undoDepth > 0 ? '#f59e0b' : '#52525b'} />
</TouchableOpacity>
{onEditRecipe && (
<TouchableOpacity
onPress={onEditRecipe}