Update default texts, admin UI improvements, Kiosk Mode prep, and fix image gallery saving
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
Modal,
|
||||
BackHandler,
|
||||
PanResponder,
|
||||
Linking,
|
||||
} from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
|
||||
@@ -347,7 +348,7 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
<Text style={styles.label}>Begrüßungstext</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Willkommen zu unserer Feier!"
|
||||
placeholder="Zeit für ein Erinnerungsfoto!"
|
||||
placeholderTextColor={THEME.colors.textMuted}
|
||||
value={welcomeText}
|
||||
onChangeText={setWelcomeText}
|
||||
@@ -357,7 +358,7 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
<Text style={styles.label}>Subtext (Footer)</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="ZUM STARTEN TIPPEN..."
|
||||
placeholder="👆 Display tippen! • 😊 Lächeln! • 📸 Foto schnappen!"
|
||||
placeholderTextColor={THEME.colors.textMuted}
|
||||
value={footerText}
|
||||
onChangeText={setFooterText}
|
||||
@@ -367,7 +368,7 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
<Text style={styles.label}>Event-Name (wird auch im Datum-Sticker & Collage verwendet)</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="z.B. Jannik's Party"
|
||||
placeholder="Schnappix-Party"
|
||||
placeholderTextColor={THEME.colors.textMuted}
|
||||
value={eventText}
|
||||
onChangeText={setEventText}
|
||||
@@ -662,7 +663,10 @@ export default function AdminScreen({ currentSettings, onSave, onClose }: AdminS
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={{ alignItems: 'center', marginTop: 20, marginBottom: 40 }}>
|
||||
<Text style={{ color: '#555', fontSize: 14 }}>App Version {appConfig.expo.version}</Text>
|
||||
<Text style={{ color: '#555', fontSize: 14, marginBottom: 10 }}>App Version {appConfig.expo.version}</Text>
|
||||
<TouchableOpacity onPress={() => Linking.openURL('https://schnappix.orfel.de')}>
|
||||
<Text style={{ color: THEME.colors.accent, fontSize: 16, textDecorationLine: 'underline' }}>schnappix.orfel.de</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ const DEFAULT_SETTINGS: AppSettings = {
|
||||
availableFrameIds: FRAMES.map(f => f.id),
|
||||
dateOverlay: 'off',
|
||||
dateOverlayTransform: { x: 0, y: 0, rotation: 0, scale: 1 },
|
||||
eventText: '',
|
||||
eventText: 'Schnappix-Party',
|
||||
burstCount: 1,
|
||||
burstIntervalSec: 5,
|
||||
welcomeText: 'Willkommen zu unserer Feier!',
|
||||
footerText: 'ZUM STARTEN TIPPEN • Fotos machen • Collage • Drucken',
|
||||
welcomeText: 'Zeit für ein Erinnerungsfoto!',
|
||||
footerText: '👆 Display tippen! • 😊 Lächeln! • 📸 Foto schnappen!',
|
||||
useFrontCamera: false,
|
||||
enableLogs: true,
|
||||
};
|
||||
|
||||
+10
-22
@@ -6,17 +6,18 @@ import * as FileSystem from 'expo-file-system';
|
||||
* @returns Promise<boolean> True if permissions are granted.
|
||||
*/
|
||||
export async function requestStoragePermission(): Promise<boolean> {
|
||||
const { status, canAskAgain } = await getPermissionsAsync();
|
||||
const { status, canAskAgain } = await getPermissionsAsync(true);
|
||||
if (status === 'granted') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (canAskAgain) {
|
||||
const { status: newStatus } = await requestPermissionsAsync();
|
||||
const { status: newStatus } = await requestPermissionsAsync(true);
|
||||
return newStatus === 'granted';
|
||||
}
|
||||
|
||||
return false;
|
||||
// On Android 13+, writeOnly permissions don't block MediaStore inserts
|
||||
return true;
|
||||
}
|
||||
|
||||
function getFormattedDateTime(): string {
|
||||
@@ -58,9 +59,9 @@ export async function saveToGallery(localUri: string, type: 'Raw' | 'Collage', e
|
||||
// 1. Create a media asset from the renamed file
|
||||
const asset = await createAssetAsync(newLocalUri);
|
||||
|
||||
// Define album name (e.g. "Schnappix/EventName/Originale")
|
||||
// Define album name
|
||||
const subFolder = type === 'Raw' ? 'Originale' : 'Collagen';
|
||||
const ALBUM_NAME = `Schnappix/${safeEventName}/${subFolder}`;
|
||||
const ALBUM_NAME = `Schnappix - ${safeEventName} - ${subFolder}`;
|
||||
|
||||
try {
|
||||
// 2. Check if the album already exists
|
||||
@@ -68,31 +69,18 @@ export async function saveToGallery(localUri: string, type: 'Raw' | 'Collage', e
|
||||
|
||||
if (!album) {
|
||||
// 3. If it doesn't exist, create it with our asset
|
||||
await createAlbumAsync(ALBUM_NAME, asset, true);
|
||||
await createAlbumAsync(ALBUM_NAME, asset, false);
|
||||
console.log(`Created new album "${ALBUM_NAME}" and copied photo.`);
|
||||
} else {
|
||||
// 4. If it exists, add our asset to it
|
||||
await addAssetsToAlbumAsync([asset], album, true);
|
||||
await addAssetsToAlbumAsync([asset], album, false);
|
||||
console.log(`Copied photo to existing album "${ALBUM_NAME}".`);
|
||||
}
|
||||
|
||||
return asset.uri;
|
||||
} catch (e: any) {
|
||||
console.error(`Error saving asset to album ${ALBUM_NAME}, trying fallback flat album name:`, e);
|
||||
// Fallback if Android blocks slashes in album names
|
||||
const fallbackAlbumName = `Schnappix - ${safeEventName} - ${subFolder}`;
|
||||
try {
|
||||
const fallbackAlbum = await getAlbumAsync(fallbackAlbumName);
|
||||
if (!fallbackAlbum) {
|
||||
await createAlbumAsync(fallbackAlbumName, asset, true);
|
||||
} else {
|
||||
await addAssetsToAlbumAsync([asset], fallbackAlbum, true);
|
||||
}
|
||||
return asset.uri;
|
||||
} catch (fallbackErr) {
|
||||
console.error('Fallback album also failed, returning asset URI anyway:', fallbackErr);
|
||||
return asset.uri;
|
||||
}
|
||||
console.error(`Error saving asset to album ${ALBUM_NAME}:`, e);
|
||||
return asset.uri;
|
||||
} finally {
|
||||
// Cleanup our temp renamed file
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user