feat: implement mobile-specific tabs for series, live tv, and movies functionality

This commit is contained in:
Michael committed 2026-03-29 14:40:21 +02:00
1 parent 6bb0d73f38
commit 6c1e42cd5a
2 files changed
+31 -18

No files matched your search

+10 -1
View File
@@ -42,7 +42,16 @@
"Bash(export PATH=\"$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH\")", "Bash(export PATH=\"$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH\")",
"Bash(__NEW_LINE_fa059bc1c566f6ee__ cd:*)", "Bash(__NEW_LINE_fa059bc1c566f6ee__ cd:*)",
"Bash(__NEW_LINE_70fecd5c4080fe72__ cd:*)", "Bash(__NEW_LINE_70fecd5c4080fe72__ cd:*)",
"Bash(__NEW_LINE_2a0d1cacdabfd662__ cd:*)" "Bash(__NEW_LINE_2a0d1cacdabfd662__ cd:*)",
"Bash(__NEW_LINE_0bb7b05d7f08e67e__ cd:*)",
"Bash(__NEW_LINE_92dba04a4f1169ce__ cd:*)",
"Bash(cmd /c \"cd /d c:\\\\Users\\\\Michael\\\\Git\\\\xtremobile && flutter build apk --release\")",
"Bash(cmd /c \"cd /d c:\\\\Users\\\\Michael\\\\Git\\\\xtremobile && flutter build apk --release 2>&1\")",
"Bash(powershell -Command \"Set-Location ''c:\\\\Users\\\\Michael\\\\Git\\\\xtremobile''; & flutter build apk --release 2>&1\")",
"Bash(powershell -Command \"Get-Command flutter -ErrorAction SilentlyContinue\")",
"Bash(powershell -Command \"Get-ChildItem -Path ''C:\\\\'' -Recurse -Filter ''flutter.bat'' -ErrorAction SilentlyContinue | Select-Object -First 5 -ExpandProperty FullName\")",
"Bash(powershell -Command \"Set-Location ''c:\\\\Users\\\\Michael\\\\Git\\\\xtremobile''; & ''C:\\\\Users\\\\Michael\\\\Git\\\\flutter\\\\bin\\\\flutter.bat'' build apk --release 2>&1\")",
"Bash(powershell -Command \":*)"
] ]
} }
} }
@@ -173,11 +173,11 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
(_player.platform as dynamic)?.setProperty( (_player.platform as dynamic)?.setProperty(
'demuxer-max-bytes', 'demuxer-max-bytes',
'32000000', '32000000',
); // Reduced to 32MB (approx 20-30s @ 10Mbps) for stability ); // 32MB (approx 20-30s @ 10Mbps) for stability
(_player.platform as dynamic) (_player.platform as dynamic)
?.setProperty('demuxer-readahead-secs', '15'); ?.setProperty('demuxer-readahead-secs', '15');
(_player.platform as dynamic) (_player.platform as dynamic)
?.setProperty('demuxer-max-back-bytes', '10000000'); ?.setProperty('demuxer-max-back-bytes', '0');
// Ensure temp files are cleaned up // Ensure temp files are cleaned up
(_player.platform as dynamic)?.setProperty('cache-unlink-files', 'yes'); (_player.platform as dynamic)?.setProperty('cache-unlink-files', 'yes');
@@ -227,12 +227,20 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
(_player.platform as dynamic) (_player.platform as dynamic)
?.setProperty('http-header-fields', 'User-Agent: XtremFlow/1.0'); ?.setProperty('http-header-fields', 'User-Agent: XtremFlow/1.0');
// Live Stream optimizations - reconnection only // Live Stream optimizations
(_player.platform as dynamic)?.setProperty( if (widget.streamType == model.StreamType.live) {
'stream-lavf-o', // For live: reconnect but do NOT use reconnect_streamed (causes rollbacks)
'reconnect=1,reconnect_streamed=1,reconnect_on_network_error=1,reconnect_delay_max=5', (_player.platform as dynamic)?.setProperty(
); 'stream-lavf-o',
// Removed: force-seekable and live_start_index=-1 which caused rollbacks 'reconnect=1,reconnect_on_network_error=1,reconnect_delay_max=3',
);
} else {
// For VOD/series: full reconnect support
(_player.platform as dynamic)?.setProperty(
'stream-lavf-o',
'reconnect=1,reconnect_streamed=1,reconnect_on_network_error=1,reconnect_delay_max=5',
);
}
(_player.platform as dynamic)?.setProperty( (_player.platform as dynamic)?.setProperty(
'demuxer-lavf-o', 'demuxer-lavf-o',
'analyzeduration=2000000,probesize=1000000', 'analyzeduration=2000000,probesize=1000000',
@@ -276,13 +284,11 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
(_player.platform as dynamic)?.setProperty('aid', 'auto'); (_player.platform as dynamic)?.setProperty('aid', 'auto');
(_player.platform as dynamic)?.setProperty('alang', 'fr,fra,fre,en,eng'); (_player.platform as dynamic)?.setProperty('alang', 'fr,fra,fre,en,eng');
// Volume & Sync // Volume
(_player.platform as dynamic)?.setProperty('volume', '100'); (_player.platform as dynamic)?.setProperty('volume', '100');
// Slightly larger buffer for software decoding // NOTE: audio-buffer already set to 1.0s above — do NOT set again here
(_player.platform as dynamic)?.setProperty('audio-buffer', '0.25');
(_player.platform as dynamic)?.setProperty('video-sync', 'audio');
debugPrint('MediaKitPlayer: Audio V3 (Downmix) configuration applied'); debugPrint('MediaKitPlayer: Audio V3 configuration applied');
_controller = VideoController(_player); _controller = VideoController(_player);
@@ -1019,8 +1025,8 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
} }
final current = _player.state.track.audio; final current = _player.state.track.audio;
int currentIndex = tracks.indexOf(current); final currentIndex = tracks.indexOf(current);
int nextIndex = (currentIndex + 1) % tracks.length; final nextIndex = (currentIndex + 1) % tracks.length;
final nextTrack = tracks[nextIndex]; final nextTrack = tracks[nextIndex];
await _player.setAudioTrack(nextTrack); await _player.setAudioTrack(nextTrack);
@@ -1334,8 +1340,6 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
Widget _buildEPGBox(String title) { Widget _buildEPGBox(String title) {
final rawNow = _epg?.nowPlaying ?? ''; final rawNow = _epg?.nowPlaying ?? '';
String nowPlaying = rawNow.isNotEmpty ? rawNow : "Pas d'infos EPG"; String nowPlaying = rawNow.isNotEmpty ? rawNow : "Pas d'infos EPG";
String nextPlaying =
_epg?.nextPlaying != null ? "Suivant: ${_epg!.nextPlaying}" : "";
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,