updates UI now support release notes

This commit is contained in:
tapframe 2025-09-07 20:37:47 +05:30
parent 837e3735a2
commit 754dec3946
6 changed files with 133 additions and 15 deletions

View file

@ -1,9 +1,13 @@
#!/bin/bash #!/bin/bash
# Check if the correct number of arguments are provided # Usage: build-and-publish-app-release.sh <xavia-ota-url> [--yes] [--release-notes "text here"]
if [ "$#" -ne 1 ]; then # --yes Skip interactive confirmation
echo "Usage: $0 <xavia-ota-url>" # --release-notes Provide release notes to attach to this upload
echo "Example: $0 https://grim-reyna-tapframe-69970143.koyeb.app"
# Parse arguments
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <xavia-ota-url> [--yes] [--release-notes \"text here\"]"
echo "Example: $0 https://grim-reyna-tapframe-69970143.koyeb.app --yes --release-notes \"Bug fixes and improvements\""
exit 1 exit 1
fi fi
@ -27,6 +31,29 @@ fi
# Assign arguments to variables # Assign arguments to variables
serverHost=$1 serverHost=$1
shift
SKIP_CONFIRM=false
RELEASE_NOTES=""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--yes)
SKIP_CONFIRM=true
shift
;;
--release-notes)
RELEASE_NOTES="$2"
shift
shift
;;
*)
echo "Unknown option: $1"
shift
;;
esac
done
# Validate server URL format # Validate server URL format
if [[ ! "$serverHost" =~ ^https?:// ]]; then if [[ ! "$serverHost" =~ ^https?:// ]]; then
@ -47,13 +74,15 @@ echo "📱 Runtime Version: $runtimeVersion"
echo "🔗 Commit Hash: $commitHash" echo "🔗 Commit Hash: $commitHash"
echo "📝 Commit Message: $commitMessage" echo "📝 Commit Message: $commitMessage"
echo "🌐 Server URL: $serverHost" echo "🌐 Server URL: $serverHost"
echo "📝 Release Notes: ${RELEASE_NOTES:-<none provided>}"
echo "" echo ""
read -p "Do you want to proceed with these values? (y/n): " confirm if [ "$SKIP_CONFIRM" = false ]; then
read -p "Do you want to proceed with these values? (y/n): " confirm
if [ "$confirm" != "y" ]; then if [ "$confirm" != "y" ]; then
echo "❌ Operation cancelled by the user." echo "❌ Operation cancelled by the user."
exit 1 exit 1
fi
fi fi
echo "🔨 Starting build process..." echo "🔨 Starting build process..."
@ -107,6 +136,7 @@ while [ $retry_count -lt $max_retries ]; do
-F "runtimeVersion=$runtimeVersion" \ -F "runtimeVersion=$runtimeVersion" \
-F "commitHash=$commitHash" \ -F "commitHash=$commitHash" \
-F "commitMessage=$commitMessage" \ -F "commitMessage=$commitMessage" \
${RELEASE_NOTES:+-F "releaseNotes=$RELEASE_NOTES"} \
--write-out "HTTP_CODE:%{http_code}" \ --write-out "HTTP_CODE:%{http_code}" \
--silent \ --silent \
--show-error) --show-error)

View file

@ -42,6 +42,17 @@ const UpdatePopup: React.FC<UpdatePopupProps> = ({
const { currentTheme } = useTheme(); const { currentTheme } = useTheme();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const getReleaseNotes = () => {
const manifest: any = updateInfo?.manifest || {};
return (
manifest.description ||
manifest.releaseNotes ||
manifest.extra?.releaseNotes ||
manifest.metadata?.releaseNotes ||
''
);
};
const handleUpdateNow = () => { const handleUpdateNow = () => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
onUpdateNow(); onUpdateNow();
@ -129,13 +140,13 @@ const UpdatePopup: React.FC<UpdatePopupProps> = ({
</Text> </Text>
</View> </View>
{updateInfo.manifest?.description && ( {!!getReleaseNotes() && (
<View style={styles.descriptionContainer}> <View style={styles.descriptionContainer}>
<Text style={[ <Text style={[
styles.description, styles.description,
{ color: currentTheme.colors.mediumEmphasis } { color: currentTheme.colors.mediumEmphasis }
]}> ]}>
{updateInfo.manifest.description} {getReleaseNotes()}
</Text> </Text>
</View> </View>
)} )}

View file

@ -14,6 +14,8 @@ import Animated, {
useAnimatedStyle, useAnimatedStyle,
interpolate, interpolate,
Extrapolate, Extrapolate,
useAnimatedReaction,
runOnJS,
} from 'react-native-reanimated'; } from 'react-native-reanimated';
import { useTheme } from '../../contexts/ThemeContext'; import { useTheme } from '../../contexts/ThemeContext';
import { logger } from '../../utils/logger'; import { logger } from '../../utils/logger';
@ -46,6 +48,7 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
setLogoLoadError, setLogoLoadError,
}) => { }) => {
const { currentTheme } = useTheme(); const { currentTheme } = useTheme();
const [isHeaderInteractive, setIsHeaderInteractive] = React.useState(false);
// Animated styles for the header // Animated styles for the header
const headerAnimatedStyle = useAnimatedStyle(() => ({ const headerAnimatedStyle = useAnimatedStyle(() => ({
@ -55,6 +58,15 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
] ]
})); }));
// Disable touches when header is transparent (Android can still register touches at opacity 0)
useAnimatedReaction(
() => headerOpacity.value,
(opacity) => {
const interactive = opacity > 0.05;
runOnJS(setIsHeaderInteractive)(interactive);
}
);
// Animated style for header elements // Animated style for header elements
const headerElementsStyle = useAnimatedStyle(() => ({ const headerElementsStyle = useAnimatedStyle(() => ({
opacity: headerElementsOpacity.value, opacity: headerElementsOpacity.value,
@ -62,7 +74,7 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
})); }));
return ( return (
<Animated.View style={[styles.floatingHeader, headerAnimatedStyle]}> <Animated.View style={[styles.floatingHeader, headerAnimatedStyle]} pointerEvents={isHeaderInteractive ? 'auto' : 'none'}>
{Platform.OS === 'ios' ? ( {Platform.OS === 'ios' ? (
<ExpoBlurView <ExpoBlurView
intensity={50} intensity={50}

View file

@ -353,7 +353,7 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
onLoad={handleLoad} onLoad={handleLoad}
onError={(error: any) => handleError(error)} onError={(error: any) => handleError(error)}
onProgress={handleProgress} onProgress={handleProgress}
controls={false} controls={Platform.OS === 'android' ? isFullscreen : false}
onEnd={() => { onEnd={() => {
// Only loop if still considered playing and component is mounted // Only loop if still considered playing and component is mounted
if (isPlaying && isComponentMounted) { if (isPlaying && isComponentMounted) {

View file

@ -66,6 +66,7 @@ const UpdateScreen: React.FC = () => {
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const [updateInfo, setUpdateInfo] = useState<any>(null); const [updateInfo, setUpdateInfo] = useState<any>(null);
const [currentInfo, setCurrentInfo] = useState<any>(null);
const [isChecking, setIsChecking] = useState(false); const [isChecking, setIsChecking] = useState(false);
const [isInstalling, setIsInstalling] = useState(false); const [isInstalling, setIsInstalling] = useState(false);
const [lastChecked, setLastChecked] = useState<Date | null>(null); const [lastChecked, setLastChecked] = useState<Date | null>(null);
@ -154,11 +155,35 @@ const UpdateScreen: React.FC = () => {
const getCurrentUpdateInfo = async () => { const getCurrentUpdateInfo = async () => {
const info = await UpdateService.getCurrentUpdateInfo(); const info = await UpdateService.getCurrentUpdateInfo();
setUpdateInfo(info); setCurrentInfo(info);
const logs = UpdateService.getLogs(); const logs = UpdateService.getLogs();
setLogs(logs); setLogs(logs);
}; };
// Extract release notes from various possible manifest fields
const getReleaseNotes = () => {
const manifest: any = updateInfo?.manifest || {};
return (
manifest.description ||
manifest.releaseNotes ||
manifest.extra?.releaseNotes ||
manifest.metadata?.releaseNotes ||
''
);
};
// Extract release notes for the currently running version
const getCurrentReleaseNotes = () => {
const manifest: any = currentInfo?.manifest || {};
return (
manifest.description ||
manifest.releaseNotes ||
manifest.extra?.releaseNotes ||
manifest.metadata?.releaseNotes ||
''
);
};
const refreshLogs = () => { const refreshLogs = () => {
const logs = UpdateService.getLogs(); const logs = UpdateService.getLogs();
setLogs(logs); setLogs(logs);
@ -414,6 +439,19 @@ const UpdateScreen: React.FC = () => {
</View> </View>
</View> </View>
{/* Release Notes */}
{updateInfo?.isAvailable && !!getReleaseNotes() && (
<View style={styles.infoSection}>
<View style={styles.infoItem}>
<View style={[styles.infoIcon, { backgroundColor: `${currentTheme.colors.primary}15` }]}>
<MaterialIcons name="notes" size={14} color={currentTheme.colors.primary} />
</View>
<Text style={[styles.infoLabel, { color: currentTheme.colors.mediumEmphasis }]}>Release notes:</Text>
</View>
<Text style={[styles.infoValue, { color: currentTheme.colors.highEmphasis }]}>{getReleaseNotes()}</Text>
</View>
)}
{/* Info Section */} {/* Info Section */}
<View style={styles.infoSection}> <View style={styles.infoSection}>
<View style={styles.infoItem}> <View style={styles.infoItem}>
@ -439,6 +477,33 @@ const UpdateScreen: React.FC = () => {
)} )}
</View> </View>
{/* Current Version Section */}
<View style={styles.infoSection}>
<View style={styles.infoItem}>
<View style={[styles.infoIcon, { backgroundColor: `${currentTheme.colors.primary}15` }]}>
<MaterialIcons name="verified" size={14} color={currentTheme.colors.primary} />
</View>
<Text style={[styles.infoLabel, { color: currentTheme.colors.mediumEmphasis }]}>Current version:</Text>
<Text style={[styles.infoValue, { color: currentTheme.colors.highEmphasis }]}>
{currentInfo?.manifest?.id ? `${currentInfo.manifest.id.substring(0, 8)}...` : (currentInfo?.isEmbeddedLaunch === false ? 'Unknown' : 'Embedded')}
</Text>
</View>
{!!getCurrentReleaseNotes() && (
<View style={{ marginTop: 8 }}>
<View style={[styles.infoItem, { alignItems: 'flex-start' }]}>
<View style={[styles.infoIcon, { backgroundColor: `${currentTheme.colors.primary}15` }]}>
<MaterialIcons name="notes" size={14} color={currentTheme.colors.primary} />
</View>
<Text style={[styles.infoLabel, { color: currentTheme.colors.mediumEmphasis }]}>Current release notes:</Text>
</View>
<Text style={[styles.infoValue, { color: currentTheme.colors.highEmphasis }]}>
{getCurrentReleaseNotes()}
</Text>
</View>
)}
</View>
{/* Advanced Toggle */} {/* Advanced Toggle */}
<TouchableOpacity <TouchableOpacity
style={[styles.modernAdvancedToggle, { backgroundColor: `${currentTheme.colors.primary}08` }]} style={[styles.modernAdvancedToggle, { backgroundColor: `${currentTheme.colors.primary}08` }]}

@ -1 +1 @@
Subproject commit ef5455acaa04404d816a6bffc25a259e28189918 Subproject commit 90fd3dd10d6ccbef30e9ce68d81c483a5552c378