Fix bugs from code review (state flow, idle timer, logger, kiosk, temp files)
This commit is contained in:
@@ -217,6 +217,22 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
</View>
|
||||
);
|
||||
|
||||
const handleClose = () => {
|
||||
// If user exits without saving, revert Kiosk Mode to match saved settings
|
||||
if (kioskActive !== currentSettings.kioskModeEnabled) {
|
||||
try {
|
||||
if (currentSettings.kioskModeEnabled) {
|
||||
KioskMode.startKiosk();
|
||||
} else {
|
||||
KioskMode.stopKiosk();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to revert Kiosk mode:', e);
|
||||
}
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View entering={FadeIn.duration(400)} exiting={FadeOut.duration(300)} style={styles.container}>
|
||||
<View style={styles.headerRow}>
|
||||
@@ -224,7 +240,7 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
<FontAwesomeIcon icon={faUserGear} size={22} color={THEME.colors.accent} />
|
||||
<Text style={styles.title}>EINSTELLUNGEN</Text>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.closeBtn} onPress={onClose}>
|
||||
<TouchableOpacity style={styles.closeBtn} onPress={handleClose}>
|
||||
<FontAwesomeIcon icon={faArrowLeft} size={14} color={THEME.colors.text} />
|
||||
<Text style={styles.closeBtnText}>Zurück zur Fotobox</Text>
|
||||
</TouchableOpacity>
|
||||
@@ -523,7 +539,7 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
<Text style={{ color: '#fff', fontWeight: 'bold' }}>Schließen</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={{ backgroundColor: THEME.colors.danger, padding: 15, borderRadius: 8, flex: 0.48, alignItems: 'center' }}
|
||||
style={{ backgroundColor: THEME.colors.error, padding: 15, borderRadius: 8, flex: 0.48, alignItems: 'center' }}
|
||||
onPress={async () => { await logger.clearLogs(); setLogs(await logger.readLogs()); }}
|
||||
>
|
||||
<Text style={{ color: '#fff', fontWeight: 'bold' }}>Leeren</Text>
|
||||
|
||||
@@ -159,8 +159,18 @@ export default function CameraScreen({
|
||||
}, []);
|
||||
|
||||
// Cancel capture process
|
||||
const handleLocalCancel = () => {
|
||||
const handleLocalCancel = async () => {
|
||||
if (burstTimerRef.current) clearTimeout(burstTimerRef.current);
|
||||
|
||||
// Clean up any temp files from a partially completed burst
|
||||
for (const uri of burstUris) {
|
||||
try {
|
||||
await FileSystem.deleteAsync(uri, { idempotent: true });
|
||||
} catch (e) {
|
||||
console.warn('Failed to delete temp file on cancel:', e);
|
||||
}
|
||||
}
|
||||
|
||||
setCountdown(countdownDuration);
|
||||
setIsCapturing(false);
|
||||
setBurstIndex(0);
|
||||
|
||||
@@ -183,16 +183,22 @@ export default function PreviewScreen({
|
||||
setSelectedStickerId(null);
|
||||
}, []);
|
||||
|
||||
// Keep latest state in a ref to avoid stale closures and rapid re-renders
|
||||
const stateRef = useRef({ stickers, layout, activeFrame, dateOverlay, onReset, currentPhoto });
|
||||
React.useEffect(() => {
|
||||
stateRef.current = { stickers, layout, activeFrame, dateOverlay, onReset, currentPhoto };
|
||||
}, [stickers, layout, activeFrame, dateOverlay, onReset, currentPhoto]);
|
||||
|
||||
// ── Capture the final image ──
|
||||
const captureComposite = async () => {
|
||||
const captureComposite = async (fallbackPhoto: string = currentPhoto) => {
|
||||
try {
|
||||
if (viewShotRef.current) {
|
||||
return await viewShotRef.current.capture();
|
||||
}
|
||||
return currentPhoto;
|
||||
return fallbackPhoto;
|
||||
} catch (e) {
|
||||
console.error('Failed to capture composite:', e);
|
||||
return currentPhoto;
|
||||
return fallbackPhoto;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -202,7 +208,7 @@ export default function PreviewScreen({
|
||||
setStatusMessage('Dein Foto wird vorbereitet...');
|
||||
try {
|
||||
setStatusMessage('Bild wird generiert...');
|
||||
const printUri = await captureComposite();
|
||||
const printUri = await captureComposite(currentPhoto);
|
||||
|
||||
setStatusMessage('Druckauftrag wird an Drucker gesendet...');
|
||||
await printImageLocal(printUri, {
|
||||
@@ -230,7 +236,7 @@ export default function PreviewScreen({
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Bild wird generiert...');
|
||||
try {
|
||||
const saveUri = await captureComposite();
|
||||
const saveUri = await captureComposite(currentPhoto);
|
||||
|
||||
setStatusMessage('Wird in Galerie gespeichert...');
|
||||
await saveToGallery(saveUri);
|
||||
@@ -249,27 +255,28 @@ export default function PreviewScreen({
|
||||
|
||||
// Auto-save and exit
|
||||
const handleExit = useCallback(async () => {
|
||||
if (stickers.length === 0 && layout === 'single' && !activeFrame && dateOverlay === 'off') {
|
||||
onReset();
|
||||
const state = stateRef.current;
|
||||
if (state.stickers.length === 0 && state.layout === 'single' && !state.activeFrame && state.dateOverlay === 'off') {
|
||||
state.onReset();
|
||||
return;
|
||||
}
|
||||
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Wird gespeichert...');
|
||||
try {
|
||||
const capturedUri = await captureComposite();
|
||||
const capturedUri = await captureComposite(state.currentPhoto);
|
||||
await saveToGallery(capturedUri);
|
||||
setStatusMessage('Erfolgreich gespeichert!');
|
||||
setTimeout(() => {
|
||||
setIsProcessing(false);
|
||||
onReset();
|
||||
state.onReset();
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
console.error('Auto-saving on exit failed:', error);
|
||||
setIsProcessing(false);
|
||||
onReset();
|
||||
state.onReset();
|
||||
}
|
||||
}, [stickers, layout, activeFrame, dateOverlay, onReset]);
|
||||
}, []); // Stable reference
|
||||
|
||||
// Idle timer logic
|
||||
const resetIdleTimer = useCallback(() => {
|
||||
@@ -291,7 +298,7 @@ export default function PreviewScreen({
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Wird vor dem Wiederholen gespeichert...');
|
||||
try {
|
||||
const capturedUri = await captureComposite();
|
||||
const capturedUri = await captureComposite(currentPhoto);
|
||||
await saveToGallery(capturedUri);
|
||||
} catch (error) {
|
||||
console.error('Auto-saving before retake failed:', error);
|
||||
|
||||
Reference in New Issue
Block a user