android Trailer Fix

This commit is contained in:
tapframe 2025-09-02 20:28:40 +05:30
parent de5dc55ce0
commit 76fde372ff
4 changed files with 162 additions and 11 deletions

1
.gitignore vendored
View file

@ -48,3 +48,4 @@ sliderreadme.md
local-scrapers-repo
worki.json
VERSION_UPDATE_README.md
hackintosh-emulator-fix.sh

View file

@ -911,6 +911,132 @@
opacity: 1;
}
/* Mobile Responsive Styles for iOS Modal */
@media (max-width: 768px) {
.ios-modal-content {
padding: 1.5rem;
margin: 1rem;
max-width: calc(100% - 2rem);
width: calc(100% - 2rem);
border-radius: 20px;
}
.ios-modal-title {
font-size: 1.5rem;
margin-bottom: 0.25rem;
}
.ios-modal-subtitle {
font-size: 0.9rem;
}
.ios-modal-header {
margin-bottom: 1.5rem;
}
.ios-install-option {
padding: 1rem;
gap: 0.75rem;
border-radius: 12px;
}
.ios-option-icon {
width: 40px;
height: 40px;
border-radius: 10px;
}
.ios-option-icon img {
width: 28px;
height: 28px;
border-radius: 6px;
}
.ios-option-title {
font-size: 1rem;
margin-bottom: 0.2rem;
}
.ios-option-description {
font-size: 0.85rem;
line-height: 1.3;
}
.ios-modal-close {
top: 0.75rem;
right: 0.75rem;
width: 32px;
height: 32px;
font-size: 1.1rem;
}
.copy-feedback {
padding: 0.75rem 1.5rem;
font-size: 0.85rem;
border-radius: 10px;
margin: 0 1rem;
max-width: calc(100% - 2rem);
}
}
@media (max-width: 480px) {
.ios-modal-content {
padding: 1.25rem;
margin: 0.75rem;
max-width: calc(100% - 1.5rem);
width: calc(100% - 1.5rem);
border-radius: 16px;
}
.ios-modal-title {
font-size: 1.3rem;
}
.ios-modal-subtitle {
font-size: 0.85rem;
}
.ios-install-option {
padding: 0.875rem;
gap: 0.625rem;
border-radius: 10px;
}
.ios-option-icon {
width: 36px;
height: 36px;
border-radius: 8px;
}
.ios-option-icon img {
width: 24px;
height: 24px;
border-radius: 5px;
}
.ios-option-title {
font-size: 0.95rem;
}
.ios-option-description {
font-size: 0.8rem;
}
.ios-modal-close {
top: 0.5rem;
right: 0.5rem;
width: 30px;
height: 30px;
font-size: 1rem;
}
.copy-feedback {
padding: 0.625rem 1.25rem;
font-size: 0.8rem;
border-radius: 8px;
}
}
.screenshot h4 {
font-size: 1rem;
font-weight: 500;

View file

@ -746,7 +746,6 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
setTrailerPreloaded(true);
}
setTrailerReady(true);
setTrailerPlaying(true);
// Smooth transition: fade out thumbnail, fade in trailer
thumbnailOpacity.value = withTiming(0, { duration: 500 });

View file

@ -60,6 +60,7 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
const [showControls, setShowControls] = useState(false);
const [duration, setDuration] = useState(0);
const [position, setPosition] = useState(0);
const [isFullscreen, setIsFullscreen] = useState(false);
// Animated values
const controlsOpacity = useSharedValue(0);
@ -139,12 +140,13 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
logger.info('TrailerPlayer', 'Video loaded successfully');
}, [loadingOpacity, onLoad]);
const handleError = useCallback((error: string) => {
const handleError = useCallback((error: any) => {
setIsLoading(false);
setHasError(true);
loadingOpacity.value = withTiming(0, { duration: 300 });
onError?.(error);
logger.error('TrailerPlayer', 'Video error:', error);
const message = typeof error === 'string' ? error : (error?.errorString || error?.error?.string || error?.error?.message || JSON.stringify(error));
onError?.(message);
logger.error('TrailerPlayer', 'Video error details:', error);
}, [loadingOpacity, onError]);
const handleProgress = useCallback((data: OnProgressData) => {
@ -216,24 +218,47 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
<View style={[styles.container, style]}>
<Video
ref={videoRef}
source={{ uri: trailerUrl }}
source={(() => {
const androidHeaders = Platform.OS === 'android' ? { 'User-Agent': 'Nuvio/1.0 (Android)' } : {} as any;
// Help ExoPlayer select proper MediaSource
const lower = (trailerUrl || '').toLowerCase();
const looksLikeHls = /\.m3u8(\b|$)/.test(lower) || /hls|applehlsencryption|playlist|m3u/.test(lower);
const looksLikeDash = /\.mpd(\b|$)/.test(lower) || /dash|manifest/.test(lower);
if (Platform.OS === 'android') {
if (looksLikeHls) {
return { uri: trailerUrl, type: 'm3u8', headers: androidHeaders } as any;
}
if (looksLikeDash) {
return { uri: trailerUrl, type: 'mpd', headers: androidHeaders } as any;
}
return { uri: trailerUrl, headers: androidHeaders } as any;
}
return { uri: trailerUrl } as any;
})()}
style={styles.video}
resizeMode="cover"
resizeMode={isFullscreen ? 'contain' : 'cover'}
paused={!isPlaying}
repeat={true}
repeat={isPlaying}
muted={isMuted}
volume={isMuted ? 0 : 1}
mixWithOthers="duck"
ignoreSilentSwitch="ignore"
/* TextureView can cause rendering issues with complex overlays on Android */
useTextureView={Platform.OS === 'android' ? false : undefined}
playInBackground={false}
playWhenInactive={false}
onFullscreenPlayerWillPresent={() => setIsFullscreen(true)}
onFullscreenPlayerDidDismiss={() => setIsFullscreen(false)}
onLoadStart={handleLoadStart}
onLoad={handleLoad}
onError={(error: any) => handleError(error?.error?.message || 'Unknown error')}
onError={(error: any) => handleError(error)}
onProgress={handleProgress}
controls={false}
onEnd={() => {
// Auto-restart when video ends
videoRef.current?.seek(0);
setIsPlaying(true);
// Only loop if still considered playing
if (isPlaying) {
videoRef.current?.seek(0);
}
}}
/>