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

View file

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

View file

@ -14,6 +14,8 @@ import Animated, {
useAnimatedStyle,
interpolate,
Extrapolate,
useAnimatedReaction,
runOnJS,
} from 'react-native-reanimated';
import { useTheme } from '../../contexts/ThemeContext';
import { logger } from '../../utils/logger';
@ -46,6 +48,7 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
setLogoLoadError,
}) => {
const { currentTheme } = useTheme();
const [isHeaderInteractive, setIsHeaderInteractive] = React.useState(false);
// Animated styles for the header
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
const headerElementsStyle = useAnimatedStyle(() => ({
opacity: headerElementsOpacity.value,
@ -62,7 +74,7 @@ const FloatingHeader: React.FC<FloatingHeaderProps> = ({
}));
return (
<Animated.View style={[styles.floatingHeader, headerAnimatedStyle]}>
<Animated.View style={[styles.floatingHeader, headerAnimatedStyle]} pointerEvents={isHeaderInteractive ? 'auto' : 'none'}>
{Platform.OS === 'ios' ? (
<ExpoBlurView
intensity={50}

View file

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

View file

@ -66,6 +66,7 @@ const UpdateScreen: React.FC = () => {
const insets = useSafeAreaInsets();
const [updateInfo, setUpdateInfo] = useState<any>(null);
const [currentInfo, setCurrentInfo] = useState<any>(null);
const [isChecking, setIsChecking] = useState(false);
const [isInstalling, setIsInstalling] = useState(false);
const [lastChecked, setLastChecked] = useState<Date | null>(null);
@ -154,11 +155,35 @@ const UpdateScreen: React.FC = () => {
const getCurrentUpdateInfo = async () => {
const info = await UpdateService.getCurrentUpdateInfo();
setUpdateInfo(info);
setCurrentInfo(info);
const logs = UpdateService.getLogs();
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 logs = UpdateService.getLogs();
setLogs(logs);
@ -414,6 +439,19 @@ const UpdateScreen: React.FC = () => {
</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 */}
<View style={styles.infoSection}>
<View style={styles.infoItem}>
@ -439,6 +477,33 @@ const UpdateScreen: React.FC = () => {
)}
</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 */}
<TouchableOpacity
style={[styles.modernAdvancedToggle, { backgroundColor: `${currentTheme.colors.primary}08` }]}

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