Localize app to German, implement auto-save to gallery, always-on camera stream, fix expo-media-library and expo-file-system deprecation/compile errors
This commit is contained in:
@@ -41,36 +41,36 @@ export default function PreviewScreen({
|
||||
// Triggers the view capture and the print job
|
||||
const handlePrint = async () => {
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Preparing your photo...');
|
||||
setStatusMessage('Dein Foto wird vorbereitet...');
|
||||
try {
|
||||
let printUri = currentPhoto;
|
||||
|
||||
// If we are printing a collage layout, capture the ViewShot container
|
||||
if (layout !== 'single') {
|
||||
setStatusMessage('Generating collage...');
|
||||
setStatusMessage('Collage wird generiert...');
|
||||
const capturedUri = await viewShotRef.current.capture();
|
||||
printUri = capturedUri;
|
||||
}
|
||||
|
||||
setStatusMessage('Sending print job to printer...');
|
||||
setStatusMessage('Druckauftrag wird an Drucker gesendet...');
|
||||
// 1. Silent Print via IPP
|
||||
await printImageLocal(printUri, {
|
||||
ipAddress: printerIp,
|
||||
jobName: 'Schnappix Photo Booth',
|
||||
jobName: 'Schnappix Fotobox',
|
||||
});
|
||||
|
||||
setStatusMessage('Saving to tablet library...');
|
||||
setStatusMessage('Wird in Galerie gespeichert...');
|
||||
// 2. Save permanently to DCIM/Schnappix
|
||||
await saveToGallery(printUri);
|
||||
|
||||
setStatusMessage('Print successful! Enjoy!');
|
||||
setStatusMessage('Druck erfolgreich! Viel Spaß! 🎉');
|
||||
setTimeout(() => {
|
||||
setIsProcessing(false);
|
||||
onReset(); // Go back to Home Screen
|
||||
}, 2000);
|
||||
} catch (error: any) {
|
||||
console.error('Printing failed:', error);
|
||||
alert('Error: ' + error.message);
|
||||
alert('Fehler: ' + error.message);
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
@@ -78,7 +78,7 @@ export default function PreviewScreen({
|
||||
// Saves to gallery without printing
|
||||
const handleSaveOnly = async () => {
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Generating image...');
|
||||
setStatusMessage('Bild wird generiert...');
|
||||
try {
|
||||
let saveUri = currentPhoto;
|
||||
|
||||
@@ -87,21 +87,46 @@ export default function PreviewScreen({
|
||||
saveUri = capturedUri;
|
||||
}
|
||||
|
||||
setStatusMessage('Saving to tablet library...');
|
||||
setStatusMessage('Wird in Galerie gespeichert...');
|
||||
await saveToGallery(saveUri);
|
||||
|
||||
setStatusMessage('Saved successfully!');
|
||||
setStatusMessage('Erfolgreich gespeichert!');
|
||||
setTimeout(() => {
|
||||
setIsProcessing(false);
|
||||
onReset();
|
||||
}, 1500);
|
||||
} catch (error: any) {
|
||||
console.error('Saving failed:', error);
|
||||
alert('Error: ' + error.message);
|
||||
alert('Fehler: ' + error.message);
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-save collage and exit
|
||||
const handleExit = async () => {
|
||||
// If layout is single, it has already been auto-saved to gallery right when captured
|
||||
if (layout === 'single') {
|
||||
onReset();
|
||||
return;
|
||||
}
|
||||
|
||||
setIsProcessing(true);
|
||||
setStatusMessage('Collage wird gespeichert...');
|
||||
try {
|
||||
const capturedUri = await viewShotRef.current.capture();
|
||||
await saveToGallery(capturedUri);
|
||||
setStatusMessage('Erfolgreich gespeichert!');
|
||||
setTimeout(() => {
|
||||
setIsProcessing(false);
|
||||
onReset();
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
console.error('Auto-saving collage on exit failed:', error);
|
||||
setIsProcessing(false);
|
||||
onReset();
|
||||
}
|
||||
};
|
||||
|
||||
// Render the selected collage inside the capture container
|
||||
const renderCollageView = () => {
|
||||
switch (layout) {
|
||||
@@ -114,8 +139,8 @@ export default function PreviewScreen({
|
||||
))}
|
||||
</View>
|
||||
<View style={styles.collageFooter}>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX PHOTO BOOTH</Text>
|
||||
<Text style={styles.collageFooterDate}>{new Date().toLocaleDateString()}</Text>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX FOTOBOX</Text>
|
||||
<Text style={styles.collageFooterDate}>{new Date().toLocaleDateString('de-DE')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -128,7 +153,7 @@ export default function PreviewScreen({
|
||||
))}
|
||||
</View>
|
||||
<View style={styles.collageFooter}>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX PHOTO BOOTH</Text>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX FOTOBOX</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -141,7 +166,7 @@ export default function PreviewScreen({
|
||||
))}
|
||||
</View>
|
||||
<View style={styles.collageFooter}>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX PHOTO BOOTH</Text>
|
||||
<Text style={styles.collageFooterText}>SCHNAPPIX FOTOBOX</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -174,7 +199,7 @@ export default function PreviewScreen({
|
||||
|
||||
{/* Right panel: Controls */}
|
||||
<View style={styles.controlPanel}>
|
||||
<Text style={styles.header}>CHOOSE YOUR STYLE</Text>
|
||||
<Text style={styles.header}>WÄHLE DEINEN STIL</Text>
|
||||
|
||||
{/* Layout Selection */}
|
||||
<View style={styles.layoutSelector}>
|
||||
@@ -182,7 +207,7 @@ export default function PreviewScreen({
|
||||
style={[styles.layoutBtn, layout === 'single' && styles.layoutBtnActive]}
|
||||
onPress={() => setLayout('single')}
|
||||
>
|
||||
<Text style={styles.layoutBtnText}>Single</Text>
|
||||
<Text style={styles.layoutBtnText}>Einzelbild</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
@@ -206,7 +231,7 @@ export default function PreviewScreen({
|
||||
disabled={photoUris.length < 3}
|
||||
onPress={() => setLayout('strip')}
|
||||
>
|
||||
<Text style={styles.layoutBtnText}>Strip (3)</Text>
|
||||
<Text style={styles.layoutBtnText}>Streifen (3)</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
@@ -218,37 +243,37 @@ export default function PreviewScreen({
|
||||
disabled={photoUris.length < 4}
|
||||
onPress={() => setLayout('grid')}
|
||||
>
|
||||
<Text style={styles.layoutBtnText}>Grid (4)</Text>
|
||||
<Text style={styles.layoutBtnText}>Raster (4)</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Text style={styles.photosCountText}>
|
||||
Photos Captured: {photoUris.length} / 4
|
||||
Aufgenommene Fotos: {photoUris.length} / 4
|
||||
</Text>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<View style={styles.actions}>
|
||||
<TouchableOpacity style={[styles.actionBtn, styles.printBtn]} onPress={handlePrint}>
|
||||
<Text style={styles.actionBtnText}>PRINT NOW 🖨️</Text>
|
||||
<Text style={styles.actionBtnText}>JETZT DRUCKEN 🖨️</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={[styles.actionBtn, styles.saveBtn]} onPress={handleSaveOnly}>
|
||||
<Text style={styles.actionBtnText}>Save to Tablet Only 💾</Text>
|
||||
<Text style={styles.actionBtnText}>Nur auf Tablet speichern 💾</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{photoUris.length < 4 && (
|
||||
<TouchableOpacity style={[styles.actionBtn, styles.addBtn]} onPress={onAddAnother}>
|
||||
<Text style={styles.actionBtnText}>+ Add Another Photo</Text>
|
||||
<Text style={styles.actionBtnText}>+ Weiteres Foto aufnehmen</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
<View style={styles.rowActions}>
|
||||
<TouchableOpacity style={[styles.smallBtn, styles.retakeBtn]} onPress={onRetakeLast}>
|
||||
<Text style={styles.smallBtnText}>Retake Last</Text>
|
||||
<Text style={styles.smallBtnText}>Letztes wiederholen</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={[styles.smallBtn, styles.resetBtn]} onPress={onReset}>
|
||||
<Text style={styles.smallBtnText}>Exit</Text>
|
||||
<TouchableOpacity style={[styles.smallBtn, styles.resetBtn]} onPress={handleExit}>
|
||||
<Text style={styles.smallBtnText}>Beenden</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
@@ -281,7 +306,6 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: '#050507',
|
||||
},
|
||||
viewShotContainer: {
|
||||
// 3:2 ratio aspect layout matching Canon Selphy postcard paper
|
||||
width: 320,
|
||||
height: 480,
|
||||
justifyContent: 'center',
|
||||
@@ -389,7 +413,6 @@ const styles = StyleSheet.create({
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
// Collage Canvas Layouts (3:2 ratio aspect - width 320, height 480)
|
||||
singleCanvas: {
|
||||
width: 320,
|
||||
height: 480,
|
||||
@@ -433,7 +456,6 @@ const styles = StyleSheet.create({
|
||||
fontSize: 8,
|
||||
color: '#666666',
|
||||
},
|
||||
// Strip (3 images vertical)
|
||||
stripCanvas: {},
|
||||
stripContent: {
|
||||
flex: 1,
|
||||
@@ -446,7 +468,6 @@ const styles = StyleSheet.create({
|
||||
resizeMode: 'cover',
|
||||
borderRadius: 2,
|
||||
},
|
||||
// Grid (4 images 2x2)
|
||||
gridCanvas: {},
|
||||
gridContainer: {
|
||||
flex: 1,
|
||||
@@ -462,7 +483,6 @@ const styles = StyleSheet.create({
|
||||
resizeMode: 'cover',
|
||||
borderRadius: 2,
|
||||
},
|
||||
// Duo (2 images side by side or stacked)
|
||||
duoCanvas: {},
|
||||
duoContainer: {
|
||||
flex: 1,
|
||||
@@ -475,7 +495,6 @@ const styles = StyleSheet.create({
|
||||
resizeMode: 'cover',
|
||||
borderRadius: 2,
|
||||
},
|
||||
// Loading overlay
|
||||
loadingOverlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
|
||||
Reference in New Issue
Block a user