Startup mode default/last-session; GPS watermark default OFF; shutter OFF truly silent
- Settings STARTUP MODE chips (AsyncStorage startup_mode): default = clean camera + PROVIA neutral 4:3, last = restore full session look. - initSession: resolve sim-* recipe ids via FILM_SIMS (fix clobber of session ratio/adjustments to 4:3 canonical); restore via setSelectedRecipe not applyRecipe so user tweaks (frame/geotag/ratio) survive restore. - applyDefaultStartup turns GPS watermark OFF (user-requested default). - Shutter: OFF must not play click on must-play-policy devices. VisionCamera v5.2.3 HybridPhotoOutput.kt plays MediaActionSound itself gated by (enableShutterSound ?: true) || mustPlayShutterSound — on Xiaomi mustPlay=true so OFF still clicked. Both capture paths now gate on enableShutterSound != false. node_modules patch not trackable -> artifacts/patches/vision-camera-shutter-silent.patch. Verified on Xiaomi 12S Ultra: log SND user=false -> play=false; cold-start DEFAULT shows GPS WATERMARK OFF.
This commit is contained in:
@@ -16,9 +16,9 @@ import ToolRail, { TabId } from './src/components/ToolRail';
|
||||
import SettingsModal from './src/components/SettingsModal';
|
||||
import PhotoViewerModal from './src/components/PhotoViewerModal';
|
||||
|
||||
import { Recipe, ColorAdjustments, FrameId, GPSInfo, AspectRatio, MeterMode, PhotoEntry, ShutterSound } from './src/types';
|
||||
import { Recipe, ColorAdjustments, FrameId, GPSInfo, AspectRatio, MeterMode, PhotoEntry, ShutterSound, StartupMode } from './src/types';
|
||||
import { getAllRecipes, saveCustomRecipe, deleteCustomRecipe } from './src/utils/storageUtils';
|
||||
import { DEFAULT_ADJUSTMENTS } from './src/utils/defaultRecipes';
|
||||
import { DEFAULT_ADJUSTMENTS, FILM_SIMS, filmSimToRecipe } from './src/utils/defaultRecipes';
|
||||
import { getCurrentGPS, requestLocationPermissions } from './src/utils/locationUtils';
|
||||
import { resolvePhotoGPS } from './src/utils/photoGps';
|
||||
import { processAndExportPhoto } from './src/utils/exportEngine';
|
||||
@@ -29,6 +29,7 @@ import { PARAM_DEFS } from './src/utils/paramDefs';
|
||||
import './global.css';
|
||||
|
||||
const SESSION_KEY = 'saved_session';
|
||||
const STARTUP_MODE_KEY = 'startup_mode';
|
||||
|
||||
// P5: native Kotlin export path. EXPO_PUBLIC_NATIVE_EXPORT=1 swaps the Skia
|
||||
// render engine for the RecipesCamExport native pipeline (same look contract,
|
||||
@@ -100,6 +101,9 @@ export default function App() {
|
||||
const [settingsVisible, setSettingsVisible] = useState(false);
|
||||
// Shutter click: only OFF/ON (no volume API on Android). Applied at capture.
|
||||
const [shutterSound, setShutterSound] = useState<ShutterSound>('on');
|
||||
// Startup behavior: 'default' = PROVIA neutral at 4:3 camera; 'last' = restore
|
||||
// previous session from AsyncStorage. Default is 'default'.
|
||||
const [startupMode, setStartupMode] = useState<StartupMode>('default');
|
||||
const photoSeq = useRef(0);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
// Short shutter-burst lock: guards the capturePhotoToFile calls from
|
||||
@@ -195,6 +199,34 @@ export default function App() {
|
||||
const list = await getAllRecipes();
|
||||
setRecipes(list);
|
||||
|
||||
// Startup mode: 'default' opens camera + PROVIA film sim (neutral
|
||||
// adjustments, DEFAULT_ADJUSTMENTS) at 4:3. 'last' restores the previous
|
||||
// session from AsyncStorage; with no saved session it falls back to the
|
||||
// same clean default state.
|
||||
let startup: StartupMode = 'default';
|
||||
try {
|
||||
const raw = await AsyncStorage.getItem(STARTUP_MODE_KEY);
|
||||
if (raw === 'last') startup = 'last';
|
||||
} catch (e) {
|
||||
console.warn('Failed to read startup mode:', e);
|
||||
}
|
||||
setStartupMode(startup);
|
||||
|
||||
const applyDefaultStartup = () => {
|
||||
setMode('camera');
|
||||
setLibraryImageUri(null);
|
||||
setAspectRatio('4:3');
|
||||
const provia = FILM_SIMS.find((f) => f.id === 'sim-provia');
|
||||
if (provia) applyRecipe(filmSimToRecipe(provia));
|
||||
// Clean camera start: GPS watermark stays OFF until the user opts in.
|
||||
setUseGeotag(false);
|
||||
};
|
||||
|
||||
if (startup === 'default') {
|
||||
applyDefaultStartup();
|
||||
return;
|
||||
}
|
||||
|
||||
let session: any = null;
|
||||
try {
|
||||
const raw = await AsyncStorage.getItem(SESSION_KEY);
|
||||
@@ -230,14 +262,22 @@ export default function App() {
|
||||
if (session.shutterSound === 'on' || session.shutterSound === 'off') setShutterSound(session.shutterSound);
|
||||
if (session.gpsInfo) setGpsInfo(session.gpsInfo);
|
||||
if (session.selectedRecipeId) {
|
||||
restoredRecipe = list.find((r: Recipe) => r.id === session.selectedRecipeId) || null;
|
||||
// Film sims are never persisted in the recipe list (sims applied on the
|
||||
// fly) — resolve sim ids via FILM_SIMS, real recipes via the list.
|
||||
const sim = FILM_SIMS.find((f) => f.id === session.selectedRecipeId);
|
||||
restoredRecipe = sim
|
||||
? filmSimToRecipe(sim)
|
||||
: list.find((r: Recipe) => r.id === session.selectedRecipeId) || null;
|
||||
}
|
||||
}
|
||||
|
||||
if (restoredRecipe) {
|
||||
applyRecipe(restoredRecipe);
|
||||
} else if (list.length > 0) {
|
||||
applyRecipe(list[0]);
|
||||
// Recipe identity restored; the look (adjustments/frame/geotag/ratio)
|
||||
// stays exactly as saved in the session above — applyRecipe would reset
|
||||
// them to the recipe's canonical values and drop the user's tweaks.
|
||||
setSelectedRecipe(restoredRecipe);
|
||||
} else {
|
||||
applyDefaultStartup();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -315,6 +355,11 @@ export default function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleStartupMode = (mode: StartupMode) => {
|
||||
setStartupMode(mode);
|
||||
AsyncStorage.setItem(STARTUP_MODE_KEY, mode).catch(() => {});
|
||||
};
|
||||
|
||||
// Latest-rawEnabled ref so the stable session-error callback below can read
|
||||
// the live toggle without re-subscribing the Camera session on every render.
|
||||
const rawEnabledRef = useRef(rawEnabled);
|
||||
@@ -851,6 +896,8 @@ export default function App() {
|
||||
onMeterModeChange={setMeterMode}
|
||||
shutterSound={shutterSound}
|
||||
onShutterSound={setShutterSound}
|
||||
startupMode={startupMode}
|
||||
onStartupMode={handleStartupMode}
|
||||
/>
|
||||
|
||||
{/* Session photo viewer (swipe across captured/exported photos) */}
|
||||
|
||||
Reference in New Issue
Block a user