From 7ae46313a5201fe1d0797ddc7c9cd8fdd7adbdb4 Mon Sep 17 00:00:00 2001 From: tapframe Date: Wed, 18 Jun 2025 18:21:04 +0530 Subject: [PATCH] Refactor useMetadataAnimations for Android compatibility and optimize animation values This update modifies the entrance animations in the useMetadataAnimations hook to start with visible values for better compatibility on Android devices. The opacity and scale values for various animations have been adjusted to enhance performance and visual consistency. Additionally, the progress animation logic has been simplified for improved efficiency. --- src/hooks/useMetadataAnimations.ts | 34 ++++++++++++---------- src/screens/MDBListSettingsScreen.tsx | 2 +- src/screens/SettingsScreen.tsx | 7 +++-- src/screens/StreamsScreen.tsx | 41 +++++++-------------------- 4 files changed, 34 insertions(+), 50 deletions(-) diff --git a/src/hooks/useMetadataAnimations.ts b/src/hooks/useMetadataAnimations.ts index e6698a95..eef76726 100644 --- a/src/hooks/useMetadataAnimations.ts +++ b/src/hooks/useMetadataAnimations.ts @@ -32,18 +32,18 @@ const easings = { }; export const useMetadataAnimations = (safeAreaTop: number, watchProgress: any) => { - // Consolidated entrance animations - fewer shared values - const screenOpacity = useSharedValue(0); - const contentOpacity = useSharedValue(0); + // Consolidated entrance animations - start with visible values for Android compatibility + const screenOpacity = useSharedValue(1); + const contentOpacity = useSharedValue(1); // Combined hero animations - const heroOpacity = useSharedValue(0); - const heroScale = useSharedValue(0.95); // Combined scale for micro-animation + const heroOpacity = useSharedValue(1); + const heroScale = useSharedValue(1); // Start at 1 for Android compatibility const heroHeightValue = useSharedValue(height * 0.5); // Combined UI element animations - const uiElementsOpacity = useSharedValue(0); - const uiElementsTranslateY = useSharedValue(10); + const uiElementsOpacity = useSharedValue(1); + const uiElementsTranslateY = useSharedValue(0); // Progress animation - simplified to single value const progressOpacity = useSharedValue(0); @@ -57,10 +57,11 @@ export const useMetadataAnimations = (safeAreaTop: number, watchProgress: any) = // Ultra-fast entrance sequence - batch animations for better performance useEffect(() => { - 'worklet'; - // Batch all entrance animations to run simultaneously const enterAnimations = () => { + 'worklet'; + + // Start with slightly reduced values and animate to full visibility screenOpacity.value = withTiming(1, { duration: 250, easing: easings.fast @@ -92,14 +93,17 @@ export const useMetadataAnimations = (safeAreaTop: number, watchProgress: any) = // Optimized watch progress animation useEffect(() => { - 'worklet'; - const hasProgress = watchProgress && watchProgress.duration > 0; - progressOpacity.value = withTiming(hasProgress ? 1 : 0, { - duration: hasProgress ? 200 : 150, - easing: easings.fast - }); + const updateProgress = () => { + 'worklet'; + progressOpacity.value = withTiming(hasProgress ? 1 : 0, { + duration: hasProgress ? 200 : 150, + easing: easings.fast + }); + }; + + runOnUI(updateProgress)(); }, [watchProgress]); // Ultra-optimized scroll handler with minimal calculations diff --git a/src/screens/MDBListSettingsScreen.tsx b/src/screens/MDBListSettingsScreen.tsx index 7dd3ddab..93126f5d 100644 --- a/src/screens/MDBListSettingsScreen.tsx +++ b/src/screens/MDBListSettingsScreen.tsx @@ -540,7 +540,7 @@ const MDBListSettingsScreen = () => { const openMDBListWebsite = () => { logger.log('[MDBListSettingsScreen] Opening MDBList website'); - Linking.openURL('https://mdblist.com/settings').catch(error => { + Linking.openURL('https://mdblist.com/preferences').catch(error => { logger.error('[MDBListSettingsScreen] Error opening website:', error); }); }; diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 9b1dcf16..7f442260 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -697,19 +697,20 @@ const styles = StyleSheet.create({ borderRadius: 8, overflow: 'hidden', height: 36, - width: 160, + width: 180, marginRight: 8, }, selectorButton: { flex: 1, justifyContent: 'center', alignItems: 'center', - paddingHorizontal: 12, + paddingHorizontal: 8, backgroundColor: 'rgba(255,255,255,0.08)', }, selectorText: { - fontSize: 14, + fontSize: 13, fontWeight: '500', + textAlign: 'center', }, profileLockContainer: { padding: 16, diff --git a/src/screens/StreamsScreen.tsx b/src/screens/StreamsScreen.tsx index e1b14e37..941500d2 100644 --- a/src/screens/StreamsScreen.tsx +++ b/src/screens/StreamsScreen.tsx @@ -679,39 +679,18 @@ export const StreamsScreen = () => { navigateToPlayer(stream); }); } else { - // For direct video URLs, use the S.Browser.ACTION_VIEW approach - // This is a more reliable way to force Android to show all video apps + // For direct video URLs, use the VideoPlayerService to show the Android app chooser + const success = await VideoPlayerService.playVideo(stream.url, { + useExternalPlayer: true, + title: metadata?.name || 'Video', + episodeTitle: type === 'series' ? currentEpisode?.name : undefined, + episodeNumber: type === 'series' && currentEpisode ? `S${currentEpisode.season_number}E${currentEpisode.episode_number}` : undefined, + }); - // Strip query parameters if they exist as they can cause issues with some apps - let cleanUrl = stream.url; - if (cleanUrl.includes('?')) { - cleanUrl = cleanUrl.split('?')[0]; + if (!success) { + console.log('VideoPlayerService failed, falling back to built-in player'); + navigateToPlayer(stream); } - - // Create an Android intent URL that forces the chooser - // Set component=null to ensure chooser is shown - // Set action=android.intent.action.VIEW to open the content - const intentUrl = `intent:${cleanUrl}#Intent;action=android.intent.action.VIEW;category=android.intent.category.DEFAULT;component=;type=video/*;launchFlags=0x10000000;end`; - - console.log(`Using intent URL: ${intentUrl}`); - - Linking.openURL(intentUrl) - .then(() => console.log('Successfully opened with intent URL')) - .catch(err => { - console.error('Failed to open with intent URL:', err); - - // First fallback: Try direct URL with regular Linking API - console.log('Trying plain URL as fallback'); - Linking.openURL(stream.url) - .then(() => console.log('Opened with direct URL')) - .catch(directErr => { - console.error('Failed to open direct URL:', directErr); - - // Final fallback: Use built-in player - console.log('All external player attempts failed, using built-in player'); - navigateToPlayer(stream); - }); - }); } } catch (error) { console.error('Error with external player:', error);