Files
etf-oglasi/frontend/components/UpdatePrompt.tsx
T
ksan 14725e180a
CI/CD / Backend Unit Tests (push) Successful in 1m48s
CI/CD / Deploy (push) Successful in 1m38s
push notifications not working for some reason
2026-06-11 01:29:48 +02:00

138 lines
4.2 KiB
TypeScript

// components/UpdatePrompt.tsx
// ─────────────────────────────────────────────────────────────────────────────
// Modal that appears when a newer build is available.
// "Update now" opens the Gitea release page in the browser.
// "Later" dismisses it for the current session (it reappears next launch).
// ─────────────────────────────────────────────────────────────────────────────
import React from 'react';
import {
Linking,
Modal,
Pressable,
StyleSheet,
Text,
View,
} from 'react-native';
import type { UpdateInfo } from '../hooks/useUpdatecheck';
import { version as currentVersion } from '../version.json';
interface Props {
updateInfo: UpdateInfo;
onDismiss: () => void;
}
export function UpdatePrompt({ updateInfo, onDismiss }: Props) {
function openRelease() {
Linking.openURL(updateInfo.releaseUrl).catch(() => {
// If the device can't open the URL, just dismiss so the app isn't stuck.
onDismiss();
});
}
return (
<Modal
visible
transparent
animationType="fade"
onRequestClose={onDismiss}
>
<View style={styles.overlay}>
<View style={styles.card}>
<Text style={styles.title}>Update available</Text>
<Text style={styles.body}>
A new version of the app is available.{'\n'}
You are on build <Text style={styles.bold}>{currentVersion}</Text>,
the latest is build{' '}
<Text style={styles.bold}>{updateInfo.latestVersion}</Text>.
</Text>
<View style={styles.actions}>
<Pressable
style={[styles.btn, styles.btnSecondary]}
onPress={onDismiss}
accessibilityRole="button"
accessibilityLabel="Remind me later"
>
<Text style={styles.btnSecondaryText}>Later</Text>
</Pressable>
<Pressable
style={[styles.btn, styles.btnPrimary]}
onPress={openRelease}
accessibilityRole="button"
accessibilityLabel="Open the release page to update"
>
<Text style={styles.btnPrimaryText}>Update now</Text>
</Pressable>
</View>
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
overlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)',
justifyContent: 'center',
alignItems: 'center',
padding: 24,
},
card: {
width: '100%',
maxWidth: 380,
backgroundColor: '#fff',
borderRadius: 12,
padding: 24,
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.15,
shadowRadius: 12,
elevation: 8,
},
title: {
fontSize: 18,
fontWeight: '700',
color: '#111',
marginBottom: 12,
},
body: {
fontSize: 15,
color: '#444',
lineHeight: 22,
marginBottom: 24,
},
bold: {
fontWeight: '700',
color: '#111',
},
actions: {
flexDirection: 'row',
justifyContent: 'flex-end',
gap: 12,
},
btn: {
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 8,
},
btnPrimary: {
backgroundColor: '#2563EB',
},
btnPrimaryText: {
color: '#fff',
fontWeight: '600',
fontSize: 15,
},
btnSecondary: {
backgroundColor: '#F3F4F6',
},
btnSecondaryText: {
color: '#374151',
fontWeight: '600',
fontSize: 15,
},
});