mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
Fix Popup Screen && Major Update Overlay Localization Patch
This commit is contained in:
parent
70be0cf8f2
commit
b69e34f1bb
4 changed files with 241 additions and 80 deletions
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue