From da4e4031bfc940b99e1c8d19d7feba37be6c4f0f Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 5 Jul 2025 12:34:18 +0530 Subject: [PATCH] remove unecessary blur on adnroid --- src/components/metadata/HeroSection.tsx | 24 +- src/components/player/AndroidVideoPlayer.tsx | 12 +- src/components/player/VideoPlayer.tsx | 13 +- src/screens/AddonsScreen.tsx | 248 +------------------ src/screens/SettingsScreen.tsx | 25 +- 5 files changed, 32 insertions(+), 290 deletions(-) diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx index 0f28967..b64cf98 100644 --- a/src/components/metadata/HeroSection.tsx +++ b/src/components/metadata/HeroSection.tsx @@ -179,17 +179,7 @@ const ActionButtons = React.memo(({ {Platform.OS === 'ios' ? ( ) : ( - Constants.executionEnvironment === ExecutionEnvironment.StoreClient ? ( - - ) : ( - - ) + )} ) : ( - Constants.executionEnvironment === ExecutionEnvironment.StoreClient ? ( - - ) : ( - - ) + )} { const isMounted = useRef(true); const controlsTimeout = useRef(null); const [isSyncingBeforeClose, setIsSyncingBeforeClose] = useState(false); + // Offset in seconds to avoid seeking to the exact end, which fires onEnd and resets. + const END_EPSILON = 0.3; const hideControls = () => { Animated.timing(fadeAnim, { @@ -355,7 +357,9 @@ const AndroidVideoPlayer: React.FC = () => { }; }, [id, type, currentTime, duration]); - const seekToTime = (timeInSeconds: number) => { + const seekToTime = (rawSeconds: number) => { + // Clamp to just before the end of the media. + const timeInSeconds = Math.max(0, Math.min(rawSeconds, duration > 0 ? duration - END_EPSILON : rawSeconds)); if (videoRef.current && duration > 0 && !isSeeking.current) { if (DEBUG_MODE) { logger.log(`[AndroidVideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s out of ${duration.toFixed(2)}s`); @@ -415,8 +419,8 @@ const AndroidVideoPlayer: React.FC = () => { const processProgressTouch = (locationX: number, isDragging = false) => { progressBarRef.current?.measure((x, y, width, height, pageX, pageY) => { - const percentage = Math.max(0, Math.min(locationX / width, 1)); - const seekTime = percentage * duration; + const percentage = Math.max(0, Math.min(locationX / width, 0.999)); + const seekTime = Math.min(percentage * duration, duration - END_EPSILON); progressAnim.setValue(percentage); if (isDragging) { pendingSeekValue.current = seekTime; @@ -519,7 +523,7 @@ const AndroidVideoPlayer: React.FC = () => { const skip = (seconds: number) => { if (videoRef.current) { - const newTime = Math.max(0, Math.min(currentTime + seconds, duration)); + const newTime = Math.max(0, Math.min(currentTime + seconds, duration - END_EPSILON)); seekToTime(newTime); } }; diff --git a/src/components/player/VideoPlayer.tsx b/src/components/player/VideoPlayer.tsx index ec7f654..0674c23 100644 --- a/src/components/player/VideoPlayer.tsx +++ b/src/components/player/VideoPlayer.tsx @@ -152,6 +152,9 @@ const VideoPlayer: React.FC = () => { const isMounted = useRef(true); const controlsTimeout = useRef(null); const [isSyncingBeforeClose, setIsSyncingBeforeClose] = useState(false); + // Small offset (in seconds) used to avoid seeking to the *exact* end of the + // file which triggers the `onEnd` callback and causes playback to restart. + const END_EPSILON = 0.3; const hideControls = () => { Animated.timing(fadeAnim, { @@ -371,7 +374,9 @@ const VideoPlayer: React.FC = () => { } }; - const seekToTime = (timeInSeconds: number) => { + const seekToTime = (rawSeconds: number) => { + // Clamp to just before the end to avoid triggering onEnd. + const timeInSeconds = Math.max(0, Math.min(rawSeconds, duration > 0 ? duration - END_EPSILON : rawSeconds)); if (vlcRef.current && duration > 0 && !isSeeking.current) { if (DEBUG_MODE) { logger.log(`[VideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s out of ${duration.toFixed(2)}s`); @@ -443,8 +448,8 @@ const VideoPlayer: React.FC = () => { const processProgressTouch = (locationX: number, isDragging = false) => { progressBarRef.current?.measure((x, y, width, height, pageX, pageY) => { - const percentage = Math.max(0, Math.min(locationX / width, 1)); - const seekTime = percentage * duration; + const percentage = Math.max(0, Math.min(locationX / width, 0.999)); + const seekTime = Math.min(percentage * duration, duration - END_EPSILON); progressAnim.setValue(percentage); if (isDragging) { pendingSeekValue.current = seekTime; @@ -530,7 +535,7 @@ const VideoPlayer: React.FC = () => { const skip = (seconds: number) => { if (vlcRef.current) { - const newTime = Math.max(0, Math.min(currentTime + seconds, duration)); + const newTime = Math.max(0, Math.min(currentTime + seconds, duration - END_EPSILON)); seekToTime(newTime); } }; diff --git a/src/screens/AddonsScreen.tsx b/src/screens/AddonsScreen.tsx index 39804a0..3d7f725 100644 --- a/src/screens/AddonsScreen.tsx +++ b/src/screens/AddonsScreen.tsx @@ -462,70 +462,6 @@ const createStyles = (colors: any) => StyleSheet.create({ padding: 6, marginRight: 8, }, - communityAddonsList: { - paddingHorizontal: 20, - }, - communityAddonItem: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: colors.card, - borderRadius: 8, - padding: 15, - marginBottom: 10, - }, - communityAddonIcon: { - width: 40, - height: 40, - borderRadius: 6, - marginRight: 15, - }, - communityAddonIconPlaceholder: { - width: 40, - height: 40, - borderRadius: 6, - marginRight: 15, - backgroundColor: colors.darkGray, - justifyContent: 'center', - alignItems: 'center', - }, - communityAddonDetails: { - flex: 1, - marginRight: 10, - }, - communityAddonName: { - fontSize: 16, - fontWeight: '600', - color: colors.white, - marginBottom: 3, - }, - communityAddonDesc: { - fontSize: 13, - color: colors.lightGray, - marginBottom: 5, - opacity: 0.9, - }, - communityAddonMetaContainer: { - flexDirection: 'row', - alignItems: 'center', - opacity: 0.8, - }, - communityAddonVersion: { - fontSize: 12, - color: colors.lightGray, - }, - communityAddonDot: { - fontSize: 12, - color: colors.lightGray, - marginHorizontal: 5, - }, - communityAddonCategory: { - fontSize: 12, - color: colors.lightGray, - flexShrink: 1, - }, - separator: { - height: 10, - }, sectionSeparator: { height: 1, backgroundColor: colors.border, @@ -560,7 +496,7 @@ const createStyles = (colors: any) => StyleSheet.create({ left: 0, right: 0, bottom: 0, - backgroundColor: 'rgba(0,0,0,0.4)', + backgroundColor: 'black', }, androidBlurContainer: { position: 'absolute', @@ -618,14 +554,8 @@ const AddonsScreen = () => { const colors = currentTheme.colors; const styles = createStyles(colors); - // State for community addons - const [communityAddons, setCommunityAddons] = useState([]); - const [communityLoading, setCommunityLoading] = useState(true); - const [communityError, setCommunityError] = useState(null); - useEffect(() => { loadAddons(); - loadCommunityAddons(); }, []); const loadAddons = async () => { @@ -662,34 +592,10 @@ const AddonsScreen = () => { } }; - // Function to load community addons - const loadCommunityAddons = async () => { - setCommunityLoading(true); - setCommunityError(null); - try { - const response = await axios.get('https://stremio-addons.com/catalog.json'); - // Filter out addons without a manifest or transportUrl (basic validation) - let validAddons = response.data.filter(addon => addon.manifest && addon.transportUrl); - - // Filter out Cinemeta if it's already in the community list to avoid duplication - validAddons = validAddons.filter(addon => addon.manifest.id !== 'com.linvo.cinemeta'); - - // Add Cinemeta to the beginning of the list - setCommunityAddons([cinemetaAddon, ...validAddons]); - } catch (error) { - logger.error('Failed to load community addons:', error); - setCommunityError('Failed to load community addons. Please try again later.'); - // Still show Cinemeta if the community list fails to load - setCommunityAddons([cinemetaAddon]); - } finally { - setCommunityLoading(false); - } - }; - const handleAddAddon = async (url?: string) => { const urlToInstall = url || addonUrl; if (!urlToInstall) { - Alert.alert('Error', 'Please enter an addon URL or select a community addon'); + Alert.alert('Error', 'Please enter an addon URL'); return; } @@ -728,7 +634,6 @@ const AddonsScreen = () => { const refreshAddons = async () => { loadAddons(); - loadCommunityAddons(); }; const moveAddonUp = (addon: ExtendedManifest) => { @@ -991,66 +896,6 @@ const AddonsScreen = () => { ); }; - // Function to render community addon items - const renderCommunityAddonItem = ({ item }: { item: CommunityAddon }) => { - const { manifest, transportUrl } = item; - const types = manifest.types || []; - const description = manifest.description || 'No description provided.'; - // @ts-ignore - logo might exist - const logo = manifest.logo || null; - const categoryText = types.length > 0 - ? types.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' • ') - : 'General'; - // Check if addon is configurable - const isConfigurable = manifest.behaviorHints?.configurable === true; - - return ( - - {logo ? ( - - ) : ( - - - - )} - - {manifest.name} - {description} - - v{manifest.version || 'N/A'} - - {categoryText} - - - - {isConfigurable && ( - handleConfigureAddon(manifest, transportUrl)} - > - - - )} - handleAddAddon(transportUrl)} - disabled={installing} - > - {installing ? ( - - ) : ( - - )} - - - - ); - }; - const StatsCard = ({ value, label }: { value: number; label: string }) => ( {value} @@ -1186,95 +1031,6 @@ const AddonsScreen = () => { )} - - {/* Separator */} - - - {/* Community Addons Section */} - - COMMUNITY ADDONS - - {communityLoading ? ( - - - - ) : communityError ? ( - - - {communityError} - - ) : communityAddons.length === 0 ? ( - - - No community addons available - - ) : ( - communityAddons.map((item, index) => ( - - - - {item.manifest.logo ? ( - - ) : ( - - - - )} - - {item.manifest.name} - - v{item.manifest.version || 'N/A'} - - - {item.manifest.types && item.manifest.types.length > 0 - ? item.manifest.types.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' • ') - : 'General'} - - - - - {item.manifest.behaviorHints?.configurable && ( - handleConfigureAddon(item.manifest, item.transportUrl)} - > - - - )} - handleAddAddon(item.transportUrl)} - disabled={installing} - > - {installing ? ( - - ) : ( - - )} - - - - - - {item.manifest.description - ? (item.manifest.description.length > 100 - ? item.manifest.description.substring(0, 100) + '...' - : item.manifest.description) - : 'No description provided.'} - - - - )) - )} - - )} diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 1c2f807..dad0e32 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -29,7 +29,6 @@ import { useTheme } from '../contexts/ThemeContext'; import { catalogService } from '../services/catalogService'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import * as Sentry from '@sentry/react-native'; -import Animated, { FadeInDown } from 'react-native-reanimated'; const { width } = Dimensions.get('window'); @@ -39,15 +38,13 @@ const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0; interface SettingsCardProps { children: React.ReactNode; title?: string; - delay?: number; } -const SettingsCard: React.FC = ({ children, title, delay = 0 }) => { +const SettingsCard: React.FC = ({ children, title }) => { const { currentTheme } = useTheme(); return ( - {title && ( @@ -64,7 +61,7 @@ const SettingsCard: React.FC = ({ children, title, delay = 0 ]}> {children} - + ); }; @@ -297,7 +294,7 @@ const SettingsScreen: React.FC = () => { contentContainerStyle={styles.scrollContent} > {/* Account Section */} - + { {/* Content & Discovery */} - + { {/* Appearance & Interface */} - + { {/* Integrations */} - + { {/* Playback & Experience */} - + { {/* About & Support */} - + { {/* Developer Options - Only show in development */} {__DEV__ && ( - + { {/* Cache Management - Only show if MDBList is connected */} {mdblistKeySet && ( - +