alert orientation fix

This commit is contained in:
tapframe 2025-12-19 23:38:33 +05:30
parent 2d5b1263b5
commit 5804959ddf
11 changed files with 242 additions and 214 deletions

View file

@ -101,6 +101,7 @@ const AnnouncementOverlay: React.FC<AnnouncementOverlayProps> = ({
transparent
animationType="none"
statusBarTranslucent
supportedOrientations={['portrait', 'landscape']}
onRequestClose={handleClose}
>
<View style={styles.overlay}>

View file

@ -152,6 +152,7 @@ export const DropUpMenu = ({ visible, onClose, item, onOptionSelect, isSaved: is
visible={visible}
transparent
animationType="none"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={onClose}
>
<GestureHandlerRootView style={{ flex: 1 }}>

View file

@ -1660,6 +1660,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
animationType="fade"
onRequestClose={closeEpisodeActionMenu}
statusBarTranslucent
supportedOrientations={['portrait', 'landscape']}
>
<Pressable
style={{

View file

@ -293,7 +293,7 @@ const TrailersSection: React.FC<TrailersSectionProps> = memo(({
// Auto-select the first available category, preferring "Trailer"
const availableCategories = Object.keys(categorized);
const preferredCategory = availableCategories.includes('Trailer') ? 'Trailer' :
availableCategories.includes('Teaser') ? 'Teaser' : availableCategories[0];
availableCategories.includes('Teaser') ? 'Teaser' : availableCategories[0];
setSelectedCategory(preferredCategory);
}
} catch (err) {
@ -559,6 +559,7 @@ const TrailersSection: React.FC<TrailersSectionProps> = memo(({
visible={dropdownVisible}
transparent={true}
animationType="fade"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => setDropdownVisible(false)}
>
<TouchableOpacity
@ -601,13 +602,13 @@ const TrailersSection: React.FC<TrailersSectionProps> = memo(({
color={currentTheme.colors.primary}
/>
</View>
<Text style={[
styles.dropdownItemText,
{
color: currentTheme.colors.highEmphasis,
fontSize: isTV ? 18 : isLargeTablet ? 17 : isTablet ? 16 : 16
}
]}>
<Text style={[
styles.dropdownItemText,
{
color: currentTheme.colors.highEmphasis,
fontSize: isTV ? 18 : isLargeTablet ? 17 : isTablet ? 16 : 16
}
]}>
{formatTrailerType(category)}
</Text>
<Text style={[

View file

@ -135,10 +135,10 @@ const AndroidVideoPlayer: React.FC = () => {
// Helper to get dynamic volume icon
const getVolumeIcon = (value: number) => {
if (value === 0) return 'volume-off';
if (value < 0.3) return 'volume-mute';
if (value < 0.6) return 'volume-down';
return 'volume-up';
if (value === 0) return 'volume-off';
if (value < 0.3) return 'volume-mute';
if (value < 0.6) return 'volume-down';
return 'volume-up';
};
// Helper to get dynamic brightness icon
@ -3432,8 +3432,6 @@ const AndroidVideoPlayer: React.FC = () => {
buffered={buffered}
formatTime={formatTime}
playerBackend={useVLC ? 'VLC' : 'ExoPlayer'}
nextLoadingTitle={nextLoadingTitle}
controlsFixedOffset={Math.min(Dimensions.get('window').width, Dimensions.get('window').height) >= 768 ? 120 : 100}
/>
{/* Combined Volume & Brightness Gesture Indicator - NEW PILL STYLE (No Bar) */}
@ -3441,45 +3439,45 @@ const AndroidVideoPlayer: React.FC = () => {
<View style={localStyles.gestureIndicatorContainer}>
{/* Dynamic Icon */}
<View
style={[
localStyles.iconWrapper,
{
// Conditional Background Color Logic
backgroundColor: gestureControls.showVolumeOverlay && volume === 0
? 'rgba(242, 184, 181)'
: 'rgba(59, 59, 59)'
}
]}
>
<MaterialIcons
name={
gestureControls.showVolumeOverlay
? getVolumeIcon(volume)
: getBrightnessIcon(brightness)
}
size={24} // Reduced size to fit inside a 32-40px circle better
color={
gestureControls.showVolumeOverlay && volume === 0
? 'rgba(96, 20, 16)' // Bright RED for MUTE icon itself
: 'rgba(255, 255, 255)' // White for all other states
}
/>
style={[
localStyles.iconWrapper,
{
// Conditional Background Color Logic
backgroundColor: gestureControls.showVolumeOverlay && volume === 0
? 'rgba(242, 184, 181)'
: 'rgba(59, 59, 59)'
}
]}
>
<MaterialIcons
name={
gestureControls.showVolumeOverlay
? getVolumeIcon(volume)
: getBrightnessIcon(brightness)
}
size={24} // Reduced size to fit inside a 32-40px circle better
color={
gestureControls.showVolumeOverlay && volume === 0
? 'rgba(96, 20, 16)' // Bright RED for MUTE icon itself
: 'rgba(255, 255, 255)' // White for all other states
}
/>
</View>
{/* Text Label: Shows "Muted" or percentage */}
<Text
style={[
localStyles.gestureText,
// Conditional Text Color Logic
gestureControls.showVolumeOverlay && volume === 0 && { color: 'rgba(242, 184, 181)' } // Light RED for "Muted"
]}
>
{/* Conditional Text Content Logic */}
{gestureControls.showVolumeOverlay && volume === 0
? "Muted" // Display "Muted" when volume is 0
: `${Math.round((gestureControls.showVolumeOverlay ? volume : brightness) * 100)}%` // Display percentage otherwise
}
</Text>
<Text
style={[
localStyles.gestureText,
// Conditional Text Color Logic
gestureControls.showVolumeOverlay && volume === 0 && { color: 'rgba(242, 184, 181)' } // Light RED for "Muted"
]}
>
{/* Conditional Text Content Logic */}
{gestureControls.showVolumeOverlay && volume === 0
? "Muted" // Display "Muted" when volume is 0
: `${Math.round((gestureControls.showVolumeOverlay ? volume : brightness) * 100)}%` // Display percentage otherwise
}
</Text>
</View>
)}
@ -4067,32 +4065,32 @@ const AndroidVideoPlayer: React.FC = () => {
// New styles for the gesture indicator
const localStyles = StyleSheet.create({
gestureIndicatorContainer: {
position: 'absolute',
top: '4%', // Adjust this for vertical position
alignSelf: 'center', // Adjust this for horizontal position
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'rgba(25, 25, 25)', // Dark pill background
borderRadius: 70,
paddingHorizontal: 15,
paddingVertical: 15,
zIndex: 2000, // Very high z-index to ensure visibility
minWidth: 120, // Adjusted min width since bar is removed
position: 'absolute',
top: '4%', // Adjust this for vertical position
alignSelf: 'center', // Adjust this for horizontal position
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'rgba(25, 25, 25)', // Dark pill background
borderRadius: 70,
paddingHorizontal: 15,
paddingVertical: 15,
zIndex: 2000, // Very high z-index to ensure visibility
minWidth: 120, // Adjusted min width since bar is removed
},
iconWrapper: {
borderRadius: 50, // Makes it a perfect circle (set to a high number)
width: 40, // Define the diameter of the circle
height: 40, // Define the diameter of the circle
justifyContent: 'center',
alignItems: 'center',
marginRight: 12, // Margin to separate icon circle from percentage text
borderRadius: 50, // Makes it a perfect circle (set to a high number)
width: 40, // Define the diameter of the circle
height: 40, // Define the diameter of the circle
justifyContent: 'center',
alignItems: 'center',
marginRight: 12, // Margin to separate icon circle from percentage text
},
gestureText: {
color: '#FFFFFF',
fontSize: 18,
fontWeight: 'normal',
minWidth: 35,
textAlign: 'right',
color: '#FFFFFF',
fontSize: 18,
fontWeight: 'normal',
minWidth: 35,
textAlign: 'right',
},
});

View file

@ -1413,6 +1413,7 @@ const AddonsScreen = () => {
visible={showConfirmModal}
transparent
animationType="fade"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => {
setShowConfirmModal(false);
setAddonDetails(null);

View file

@ -685,6 +685,7 @@ const CatalogSettingsScreen = () => {
animationType="fade"
transparent={true}
visible={isRenameModalVisible}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => {
setIsRenameModalVisible(false);
setCatalogToRename(null);

View file

@ -1946,6 +1946,7 @@ const PluginsScreen: React.FC = () => {
visible={showHelpModal}
transparent={true}
animationType="fade"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => setShowHelpModal(false)}
>
<View style={styles.modalOverlay}>
@ -1978,6 +1979,7 @@ const PluginsScreen: React.FC = () => {
visible={showAddRepositoryModal}
transparent={true}
animationType="fade"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => setShowAddRepositoryModal(false)}
>
<View style={styles.modalOverlay}>

View file

@ -52,7 +52,7 @@ const ProfilesScreen: React.FC = () => {
) => {
setAlertTitle(title);
setAlertMessage(message);
setAlertActions(actions && actions.length > 0 ? actions : [{ label: 'OK', onPress: () => {} }]);
setAlertActions(actions && actions.length > 0 ? actions : [{ label: 'OK', onPress: () => { } }]);
setAlertVisible(true);
};
@ -164,7 +164,7 @@ const ProfilesScreen: React.FC = () => {
'Delete Profile',
'Are you sure you want to delete this profile? This action cannot be undone.',
[
{ label: 'Cancel', onPress: () => {} },
{ label: 'Cancel', onPress: () => { } },
{
label: 'Delete',
onPress: () => {
@ -281,6 +281,7 @@ const ProfilesScreen: React.FC = () => {
visible={showAddModal}
transparent
animationType="fade"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => setShowAddModal(false)}
>
<View style={styles.modalOverlay}>

View file

@ -132,17 +132,27 @@ export const StreamsScreen = () => {
const { showSuccess, showInfo } = useToast();
// Add dimension listener and tablet detection
// Use a ref to track previous dimensions to avoid unnecessary re-renders
const [dimensions, setDimensions] = useState(Dimensions.get('window'));
const prevDimensionsRef = useRef({ width: dimensions.width, height: dimensions.height });
useEffect(() => {
const subscription = Dimensions.addEventListener('change', ({ window }) => {
setDimensions(window);
// Only update state if dimensions actually changed (with 1px tolerance)
const widthChanged = Math.abs(window.width - prevDimensionsRef.current.width) > 1;
const heightChanged = Math.abs(window.height - prevDimensionsRef.current.height) > 1;
if (widthChanged || heightChanged) {
prevDimensionsRef.current = { width: window.width, height: window.height };
setDimensions(window);
}
});
return () => subscription?.remove();
}, []);
// Memoize tablet detection to prevent recalculation on every render
const deviceWidth = dimensions.width;
const isTablet = deviceWidth >= 768;
const isTablet = useMemo(() => deviceWidth >= 768, [deviceWidth]);
// Add refs to prevent excessive updates and duplicate loads
const isMounted = useRef(true);
@ -303,6 +313,9 @@ export const StreamsScreen = () => {
}, []);
// Monitor streams loading and update available providers immediately
// Use a ref to track the previous providers to avoid unnecessary state updates
const prevProvidersRef = useRef<Set<string>>(new Set());
useEffect(() => {
// Skip processing if component is unmounting
if (!isMounted.current) return;
@ -317,14 +330,21 @@ export const StreamsScreen = () => {
if (providersWithStreams.length > 0) {
logger.log(`📊 Providers with streams: ${providersWithStreams.join(', ')}`);
const providersWithStreamsSet = new Set(providersWithStreams);
// Only update if we have new providers, don't remove existing ones during loading
setAvailableProviders(prevProviders => {
const newProviders = new Set([...prevProviders, ...providersWithStreamsSet]);
if (__DEV__) console.log('[StreamsScreen] availableProviders ->', Array.from(newProviders));
return newProviders;
});
// Check if we actually have new providers before triggering state update
const hasNewProviders = providersWithStreams.some(
provider => !prevProvidersRef.current.has(provider)
);
if (hasNewProviders) {
setAvailableProviders(prevProviders => {
const newProviders = new Set([...prevProviders, ...providersWithStreams]);
// Update ref to track current providers
prevProvidersRef.current = newProviders;
if (__DEV__) console.log('[StreamsScreen] availableProviders ->', Array.from(newProviders));
return newProviders;
});
}
}
// Update loading states for individual providers

View file

@ -828,6 +828,7 @@ const TMDBSettingsScreen = () => {
visible={languagePickerVisible}
transparent
animationType="slide"
supportedOrientations={['portrait', 'landscape']}
onRequestClose={() => setLanguagePickerVisible(false)}
>
<TouchableWithoutFeedback onPress={() => setLanguagePickerVisible(false)}>
@ -955,42 +956,42 @@ const TMDBSettingsScreen = () => {
return (
<>
{filteredLanguages.map(({ code, label, native }) => (
<TouchableOpacity
key={code}
onPress={() => { updateSetting('tmdbLanguagePreference', code); setLanguagePickerVisible(false); }}
style={[
styles.languageItem,
settings.tmdbLanguagePreference === code && styles.selectedLanguageItem
]}
activeOpacity={0.7}
>
<View style={styles.languageContent}>
<View style={styles.languageInfo}>
<Text style={[
styles.languageName,
settings.tmdbLanguagePreference === code && styles.selectedLanguageName,
{
color: settings.tmdbLanguagePreference === code ? currentTheme.colors.primary : currentTheme.colors.text,
}
]}>
{native}
</Text>
<Text style={[
styles.languageCode,
settings.tmdbLanguagePreference === code && styles.selectedLanguageCode,
{
color: settings.tmdbLanguagePreference === code ? currentTheme.colors.primary : currentTheme.colors.mediumEmphasis,
}
]}>
{label} {code.toUpperCase()}
</Text>
</View>
{settings.tmdbLanguagePreference === code && (
<View style={styles.checkmarkContainer}>
<MaterialIcons name="check-circle" size={24} color={currentTheme.colors.primary} />
</View>
)}
</View>
<TouchableOpacity
key={code}
onPress={() => { updateSetting('tmdbLanguagePreference', code); setLanguagePickerVisible(false); }}
style={[
styles.languageItem,
settings.tmdbLanguagePreference === code && styles.selectedLanguageItem
]}
activeOpacity={0.7}
>
<View style={styles.languageContent}>
<View style={styles.languageInfo}>
<Text style={[
styles.languageName,
settings.tmdbLanguagePreference === code && styles.selectedLanguageName,
{
color: settings.tmdbLanguagePreference === code ? currentTheme.colors.primary : currentTheme.colors.text,
}
]}>
{native}
</Text>
<Text style={[
styles.languageCode,
settings.tmdbLanguagePreference === code && styles.selectedLanguageCode,
{
color: settings.tmdbLanguagePreference === code ? currentTheme.colors.primary : currentTheme.colors.mediumEmphasis,
}
]}>
{label} {code.toUpperCase()}
</Text>
</View>
{settings.tmdbLanguagePreference === code && (
<View style={styles.checkmarkContainer}>
<MaterialIcons name="check-circle" size={24} color={currentTheme.colors.primary} />
</View>
)}
</View>
</TouchableOpacity>
))}
{languageSearch.length > 0 && filteredLanguages.length === 0 && (