mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 00:32:04 +00:00
tablet padding changes
This commit is contained in:
parent
230afd7414
commit
704c642a8f
4 changed files with 38 additions and 19 deletions
|
|
@ -248,7 +248,7 @@ PODS:
|
||||||
- SDWebImageSVGCoder (~> 1.7.0)
|
- SDWebImageSVGCoder (~> 1.7.0)
|
||||||
- ExpoKeepAwake (14.0.3):
|
- ExpoKeepAwake (14.0.3):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoLibVlcPlayer (2.2.1):
|
- ExpoLibVlcPlayer (2.1.7):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- MobileVLCKit (= 3.6.1b1)
|
- MobileVLCKit (= 3.6.1b1)
|
||||||
- ExpoLinearGradient (14.0.2):
|
- ExpoLinearGradient (14.0.2):
|
||||||
|
|
@ -2914,7 +2914,7 @@ SPEC CHECKSUMS:
|
||||||
ExpoHaptics: 8d199b2f33245ea85289ff6c954c7ee7c00a5b5d
|
ExpoHaptics: 8d199b2f33245ea85289ff6c954c7ee7c00a5b5d
|
||||||
ExpoImage: d840b256050f4428d2942bc2b6e9251f9e0d7021
|
ExpoImage: d840b256050f4428d2942bc2b6e9251f9e0d7021
|
||||||
ExpoKeepAwake: b0171a73665bfcefcfcc311742a72a956e6aa680
|
ExpoKeepAwake: b0171a73665bfcefcfcc311742a72a956e6aa680
|
||||||
ExpoLibVlcPlayer: dce3d0b5847838cd5f8c5f3c3aa1bc55c92e911d
|
ExpoLibVlcPlayer: 027c16c178364a133f6ee10fc7a7d8636f92dbe8
|
||||||
ExpoLinearGradient: 35ebd83b16f80b3add053a2fd68cc328ed927f60
|
ExpoLinearGradient: 35ebd83b16f80b3add053a2fd68cc328ed927f60
|
||||||
ExpoLinking: 8d12bee174ba0cdf31239706578e29e74a417402
|
ExpoLinking: 8d12bee174ba0cdf31239706578e29e74a417402
|
||||||
ExpoLocalization: 7776ea3bdb112125390745bbaf919b734b2ad1c7
|
ExpoLocalization: 7776ea3bdb112125390745bbaf919b734b2ad1c7
|
||||||
|
|
|
||||||
|
|
@ -192,10 +192,14 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
|
||||||
return 'https://via.placeholder.com/154x231/333/666?text=No+Image';
|
return 'https://via.placeholder.com/154x231/333/666?text=No+Image';
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've had an error, try metahub fallback
|
// Retry 1: cache-busting query to avoid stale memory artifacts
|
||||||
// Use addon poster if available, otherwise use placeholder
|
if (retryCount === 1) {
|
||||||
if (retryCount > 0 && !item.poster) {
|
const bust = item.poster.includes('?') ? `&r=${Date.now()}` : `?r=${Date.now()}`;
|
||||||
return 'https://via.placeholder.com/300x450/cccccc/666666?text=No+Image';
|
return item.poster + bust;
|
||||||
|
}
|
||||||
|
// Retry 2+: hard fallback placeholder
|
||||||
|
if (retryCount >= 2) {
|
||||||
|
return 'https://via.placeholder.com/154x231/333/666?text=No+Image';
|
||||||
}
|
}
|
||||||
|
|
||||||
// For TMDB images, use smaller sizes
|
// For TMDB images, use smaller sizes
|
||||||
|
|
@ -268,16 +272,15 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
|
||||||
}}
|
}}
|
||||||
onError={(error) => {
|
onError={(error) => {
|
||||||
if (__DEV__) console.warn('Image load error for:', item.poster, error);
|
if (__DEV__) console.warn('Image load error for:', item.poster, error);
|
||||||
// Try fallback URL on first error
|
// Increment retry; 0 -> 1 (cache-bust), 1 -> 2 (placeholder)
|
||||||
if (retryCount === 0 && item.poster && !item.poster.includes('placeholder')) {
|
setRetryCount((prev) => prev + 1);
|
||||||
setRetryCount(1);
|
// Only show broken state after final retry
|
||||||
// Don't set error state yet, let it try the fallback
|
if (retryCount >= 1) {
|
||||||
return;
|
setImageError(true);
|
||||||
|
setImageLoaded(false);
|
||||||
}
|
}
|
||||||
setImageError(true);
|
|
||||||
setImageLoaded(false);
|
|
||||||
}}
|
}}
|
||||||
recyclingKey={item.id} // Add recycling key for better performance
|
recyclingKey={`${item.id}-${optimizedPosterUrl}`} // Tie texture reuse to URL to avoid stale reuse
|
||||||
placeholder={PLACEHOLDER_BLURHASH}
|
placeholder={PLACEHOLDER_BLURHASH}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -736,7 +736,9 @@ const SearchScreen = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const headerBaseHeight = Platform.OS === 'android' ? 80 : 60;
|
const headerBaseHeight = Platform.OS === 'android' ? 80 : 60;
|
||||||
const topSpacing = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top;
|
// Keep header below floating top navigator on tablets by adding extra offset
|
||||||
|
const tabletNavOffset = isTablet ? 64 : 0;
|
||||||
|
const topSpacing = (Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top) + tabletNavOffset;
|
||||||
const headerHeight = headerBaseHeight + topSpacing + 60;
|
const headerHeight = headerBaseHeight + topSpacing + 60;
|
||||||
|
|
||||||
// Set up listeners for watched status and library updates
|
// Set up listeners for watched status and library updates
|
||||||
|
|
|
||||||
|
|
@ -186,12 +186,18 @@ interface SidebarProps {
|
||||||
onCategorySelect: (category: string) => void;
|
onCategorySelect: (category: string) => void;
|
||||||
currentTheme: any;
|
currentTheme: any;
|
||||||
categories: typeof SETTINGS_CATEGORIES;
|
categories: typeof SETTINGS_CATEGORIES;
|
||||||
|
extraTopPadding?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sidebar: React.FC<SidebarProps> = ({ selectedCategory, onCategorySelect, currentTheme, categories }) => {
|
const Sidebar: React.FC<SidebarProps> = ({ selectedCategory, onCategorySelect, currentTheme, categories, extraTopPadding = 0 }) => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.sidebar, { backgroundColor: currentTheme.colors.elevation1 }]}>
|
<View style={[styles.sidebar, { backgroundColor: currentTheme.colors.elevation1 }]}>
|
||||||
<View style={styles.sidebarHeader}>
|
<View style={[
|
||||||
|
styles.sidebarHeader,
|
||||||
|
{
|
||||||
|
paddingTop: (Platform.OS === 'android' ? (StatusBar.currentHeight || 0) + 24 : 48) + extraTopPadding,
|
||||||
|
}
|
||||||
|
]}>
|
||||||
<Text style={[styles.sidebarTitle, { color: currentTheme.colors.highEmphasis }]}>
|
<Text style={[styles.sidebarTitle, { color: currentTheme.colors.highEmphasis }]}>
|
||||||
Settings
|
Settings
|
||||||
</Text>
|
</Text>
|
||||||
|
|
@ -750,7 +756,9 @@ const SettingsScreen: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const headerBaseHeight = Platform.OS === 'android' ? 80 : 60;
|
const headerBaseHeight = Platform.OS === 'android' ? 80 : 60;
|
||||||
const topSpacing = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top;
|
// Keep headers below floating top navigator on tablets by adding extra offset
|
||||||
|
const tabletNavOffset = isTablet ? 64 : 0;
|
||||||
|
const topSpacing = (Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top) + tabletNavOffset;
|
||||||
const headerHeight = headerBaseHeight + topSpacing;
|
const headerHeight = headerBaseHeight + topSpacing;
|
||||||
|
|
||||||
if (isTablet) {
|
if (isTablet) {
|
||||||
|
|
@ -766,9 +774,15 @@ const SettingsScreen: React.FC = () => {
|
||||||
onCategorySelect={setSelectedCategory}
|
onCategorySelect={setSelectedCategory}
|
||||||
currentTheme={currentTheme}
|
currentTheme={currentTheme}
|
||||||
categories={visibleCategories}
|
categories={visibleCategories}
|
||||||
|
extraTopPadding={tabletNavOffset}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<View style={styles.tabletContent}>
|
<View style={[
|
||||||
|
styles.tabletContent,
|
||||||
|
{
|
||||||
|
paddingTop: (Platform.OS === 'android' ? (StatusBar.currentHeight || 0) + 24 : 48) + tabletNavOffset,
|
||||||
|
}
|
||||||
|
]}>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={styles.tabletScrollView}
|
style={styles.tabletScrollView}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue