Ios #14
4 changed files with 34 additions and 50 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue