Fix Popup Screen && Major Update Overlay Localization Patch

This commit is contained in:
cyberalby2 2026-03-06 23:32:21 +01:00
parent 70be0cf8f2
commit b69e34f1bb
4 changed files with 241 additions and 80 deletions

View file

@ -1,95 +1,238 @@
import React from 'react';
import { Modal, View, Text, StyleSheet, TouchableOpacity, Linking } from 'react-native';
import {
Modal,
View,
Text,
StyleSheet,
TouchableOpacity,
Linking,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useTheme } from '../contexts/ThemeContext';
import { useTranslation } from 'react-i18next';
interface Props {
visible: boolean;
latestTag?: string;
releaseNotes?: string;
releaseUrl?: string;
onDismiss: () => void;
onLater: () => void;
onUpdateAction?: () => void;
isDownloading?: boolean;
downloadProgress?: number;
visible: boolean;
latestTag?: string;
releaseNotes?: string;
releaseUrl?: string;
onDismiss: () => void;
onLater: () => void;
onUpdateAction?: () => void;
isDownloading?: boolean;
downloadProgress?: number;
}
const MajorUpdateOverlay: React.FC<Props> = ({ visible, latestTag, releaseNotes, releaseUrl, onDismiss, onLater, onUpdateAction, isDownloading, downloadProgress }) => {
const { currentTheme } = useTheme();
const MajorUpdateOverlay: React.FC<Props> = ({
visible,
latestTag,
releaseNotes,
releaseUrl,
onDismiss,
onLater,
onUpdateAction,
isDownloading,
downloadProgress,
}) => {
const { currentTheme } = useTheme();
const { t } = useTranslation();
if (!visible) return null;
if (!visible) return null;
const progressPercent = downloadProgress
? Math.round(downloadProgress * 100)
: 0;
const progressPercent = downloadProgress ? Math.round(downloadProgress * 100) : 0;
return (
<Modal
visible={visible}
transparent
animationType="fade"
statusBarTranslucent
presentationStyle="overFullScreen"
supportedOrientations={[
'portrait',
'landscape',
'landscape-left',
'landscape-right',
]}
>
<View style={styles.backdrop}>
<View
style={[
styles.card,
{
backgroundColor: currentTheme.colors.darkBackground,
borderColor: currentTheme.colors.elevation3,
},
]}
>
<View style={styles.header}>
<View
style={[
styles.iconCircle,
{ backgroundColor: `${currentTheme.colors.primary}22` },
]}
>
<MaterialIcons
name="new-releases"
size={28}
color={currentTheme.colors.primary}
/>
</View>
<Text style={[styles.title, { color: currentTheme.colors.highEmphasis }]}>
{t('major_update_screen.major_update_title')}
</Text>
{!!latestTag && (
<Text
style={[styles.version, { color: currentTheme.colors.mediumEmphasis }]}
>
{t('major_update_screen.latest')} {latestTag}
</Text>
)}
</View>
return (
<Modal visible={visible} transparent animationType="fade" statusBarTranslucent presentationStyle="overFullScreen" supportedOrientations={['portrait', 'landscape', 'landscape-left', 'landscape-right']}>
<View style={styles.backdrop}>
<View style={[styles.card, { backgroundColor: currentTheme.colors.darkBackground, borderColor: currentTheme.colors.elevation3 }]}>
<View style={styles.header}>
<View style={[styles.iconCircle, { backgroundColor: `${currentTheme.colors.primary}22` }]}>
<MaterialIcons name="new-releases" size={28} color={currentTheme.colors.primary} />
</View>
<Text style={[styles.title, { color: currentTheme.colors.highEmphasis }]}>Major update available</Text>
{!!latestTag && (
<Text style={[styles.version, { color: currentTheme.colors.mediumEmphasis }]}>Latest: {latestTag}</Text>
)}
</View>
{!!releaseNotes && (
<View style={styles.notesBox}>
<Text
style={[styles.notes, { color: currentTheme.colors.mediumEmphasis }]}
numberOfLines={10}
>
{releaseNotes}
</Text>
</View>
)}
{!!releaseNotes && (
<View style={styles.notesBox}>
<Text style={[styles.notes, { color: currentTheme.colors.mediumEmphasis }]} numberOfLines={10}>
{releaseNotes}
</Text>
</View>
)}
<View style={styles.actions}>
{releaseUrl || onUpdateAction ? (
<TouchableOpacity
style={[
styles.primaryBtn,
{
backgroundColor: currentTheme.colors.primary,
opacity: isDownloading ? 0.7 : 1,
},
]}
onPress={
onUpdateAction || (() => releaseUrl && Linking.openURL(releaseUrl))
}
disabled={isDownloading}
>
<MaterialIcons
name={isDownloading ? 'downloading' : 'system-update'}
size={18}
color="#fff"
/>
<Text style={styles.primaryText}>
{isDownloading
? `${t('major_update_screen.downloading')}... ${progressPercent}%`
: onUpdateAction
? t('major_update_screen.update_now')
: t('major_update_screen.view_release')}
</Text>
</TouchableOpacity>
) : null}
<View style={styles.actions}>
{releaseUrl || onUpdateAction ? (
<TouchableOpacity
style={[styles.primaryBtn, { backgroundColor: currentTheme.colors.primary, opacity: isDownloading ? 0.7 : 1 }]}
onPress={onUpdateAction || (() => releaseUrl && Linking.openURL(releaseUrl))}
disabled={isDownloading}
>
<MaterialIcons name={isDownloading ? "downloading" : "system-update"} size={18} color="#fff" />
<Text style={styles.primaryText}>
{isDownloading ? `Downloading... ${progressPercent}%` : (onUpdateAction ? 'Update Now' : 'View release')}
</Text>
</TouchableOpacity>
) : null}
<View style={styles.secondaryRow}>
<TouchableOpacity style={[styles.secondaryBtn, { borderColor: currentTheme.colors.elevation3 }]} onPress={onLater}>
<Text style={[styles.secondaryText, { color: currentTheme.colors.mediumEmphasis }]}>Later</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.secondaryBtn, { borderColor: currentTheme.colors.elevation3 }]} onPress={onDismiss}>
<Text style={[styles.secondaryText, { color: currentTheme.colors.mediumEmphasis }]}>Dismiss</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</Modal>
);
<View style={styles.secondaryRow}>
<TouchableOpacity
style={[
styles.secondaryBtn,
{ borderColor: currentTheme.colors.elevation3 },
]}
onPress={onLater}
>
<Text
style={[
styles.secondaryText,
{ color: currentTheme.colors.mediumEmphasis },
]}
>
{t('major_update_screen.later')}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.secondaryBtn,
{ borderColor: currentTheme.colors.elevation3 },
]}
onPress={onDismiss}
>
<Text
style={[
styles.secondaryText,
{ color: currentTheme.colors.mediumEmphasis },
]}
>
{t('major_update_screen.dismiss')}
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</Modal>
);
};
const styles = StyleSheet.create({
backdrop: { flex: 1, backgroundColor: 'rgba(0,0,0,0.8)', alignItems: 'center', justifyContent: 'center', padding: 20 },
card: { width: 380, maxWidth: '100%', borderRadius: 20, borderWidth: 1, overflow: 'hidden' },
header: { alignItems: 'center', paddingTop: 28, paddingBottom: 16, paddingHorizontal: 20 },
iconCircle: { width: 56, height: 56, borderRadius: 28, alignItems: 'center', justifyContent: 'center', marginBottom: 12 },
title: { fontSize: 20, fontWeight: '700', marginBottom: 6 },
version: { fontSize: 14 },
notesBox: { marginHorizontal: 20, marginBottom: 16, padding: 12, borderRadius: 12, backgroundColor: 'rgba(255,255,255,0.08)' },
notes: { fontSize: 14, lineHeight: 20 },
actions: { paddingHorizontal: 20, paddingBottom: 20 },
primaryBtn: { flexDirection: 'row', alignItems: 'center', gap: 8, justifyContent: 'center', paddingVertical: 12, borderRadius: 12, marginBottom: 12 },
primaryText: { color: '#fff', fontSize: 16, fontWeight: '600' },
secondaryRow: { flexDirection: 'row', gap: 10 },
secondaryBtn: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: 12, borderRadius: 12, borderWidth: 1 },
secondaryText: { fontSize: 15, fontWeight: '500' },
backdrop: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.8)',
alignItems: 'center',
justifyContent: 'center',
padding: 20,
},
card: {
width: 380,
maxWidth: '100%',
borderRadius: 20,
borderWidth: 1,
overflow: 'hidden',
},
header: {
alignItems: 'center',
paddingTop: 28,
paddingBottom: 16,
paddingHorizontal: 20,
},
iconCircle: {
width: 56,
height: 56,
borderRadius: 28,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 12,
},
title: { fontSize: 20, fontWeight: '700', marginBottom: 6 },
version: { fontSize: 14 },
notesBox: {
marginHorizontal: 20,
marginBottom: 16,
padding: 12,
borderRadius: 12,
backgroundColor: 'rgba(255,255,255,0.08)',
},
notes: { fontSize: 14, lineHeight: 20 },
actions: { paddingHorizontal: 20, paddingBottom: 20 },
primaryBtn: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
justifyContent: 'center',
paddingVertical: 12,
borderRadius: 12,
marginBottom: 12,
},
primaryText: { color: '#fff', fontSize: 16, fontWeight: '600' },
secondaryRow: { flexDirection: 'row', gap: 10 },
secondaryBtn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 12,
borderRadius: 12,
borderWidth: 1,
},
secondaryText: { fontSize: 15, fontWeight: '500' },
});
export default MajorUpdateOverlay;

View file

@ -13,7 +13,7 @@ import { useTheme } from '../contexts/ThemeContext';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import * as Haptics from 'expo-haptics';
import AndroidUpdatePopup from './AndroidUpdatePopup';
import { t } from 'i18next';
import { useTranslation } from 'react-i18next';
const { width, height } = Dimensions.get('window');
@ -43,7 +43,7 @@ const UpdatePopup: React.FC<UpdatePopupProps> = ({
}) => {
const { currentTheme } = useTheme();
const insets = useSafeAreaInsets();
const { t } = useTranslation();
const getReleaseNotes = () => {
const manifest: any = updateInfo?.manifest || {};
return (

View file

@ -1564,5 +1564,14 @@
"installing": "Installing...",
"later": "Later",
"dismiss": "Dismiss"
}
},
"major_update_screen":{
"major_update_title":"Major update available",
"latest":"Latest:",
"downloading":"Downloading...",
"update_now":"Update Now",
"later":"Later",
"dismiss":"Dismiss",
"view_release":"View Release"
}
}

View file

@ -1564,5 +1564,14 @@
"installing": "Installazione...",
"later": "Dopo",
"dismiss": "Ignora"
},
"major_update_screen": {
"major_update_title": "Aggiornamento Importante Disponibile",
"latest": "Ultima:",
"downloading": "Download in corso...",
"update_now": "Aggiorna Ora",
"later": "Dopo",
"dismiss": "Ignora",
"view_release": "Vedi Release"
}
}