fix(mobile): optimize player UI for mobile portrait and tune HLS buffering

This commit is contained in:
Michael committed 2026-03-09 21:56:56 +01:00
1 parent 441597354e
commit b69e9d1812
2 files changed
+79 -6

No files matched your search

@@ -811,6 +811,64 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
);
}
List<Widget> _buildControlButtons(bool isSmallScreen) {
final buttonSize = isSmallScreen ? 40.0 : 44.0;
final playButtonSize = isSmallScreen ? 48.0 : 52.0;
final spacing = isSmallScreen ? 8.0 : 16.0;
return [
// Previous Channel
if (widget.channels != null && widget.channels!.length > 1)
_buildSimpleIconButton(
icon: Icons.skip_previous_rounded,
onTap: _previousChannel,
size: buttonSize,
),
if (widget.channels != null && widget.channels!.length > 1)
SizedBox(width: spacing),
// Play/Pause (Large)
_buildSimpleIconButton(
icon: _isPlaying ? Icons.pause_rounded : Icons.play_arrow_rounded,
onTap: _togglePlayPause,
size: playButtonSize,
iconSize: isSmallScreen ? 24 : 28,
highlighted: true,
),
if (widget.channels != null && widget.channels!.length > 1)
SizedBox(width: spacing),
// Next Channel
if (widget.channels != null && widget.channels!.length > 1)
_buildSimpleIconButton(
icon: Icons.skip_next_rounded,
onTap: _nextChannel,
size: buttonSize,
),
SizedBox(width: spacing),
// Mute button
_buildSimpleIconButton(
icon: _isMuted ? Icons.volume_off_rounded : Icons.volume_up_rounded,
onTap: _toggleMute,
size: buttonSize,
),
if (isSmallScreen) ...[
SizedBox(width: spacing),
// Fullscreen button inside the bar for mobile
_buildSimpleIconButton(
icon: Icons.fullscreen_rounded,
onTap: _toggleFullscreen,
size: buttonSize,
),
],
];
}
// Simple Icon Button for Live TV player (no BackdropFilter issues)
Widget _buildSimpleIconButton({
required IconData icon,
+21 -6
View File
@@ -214,12 +214,15 @@
}
const hls = new Hls({
maxBufferLength: 30,
maxMaxBufferLength: 60,
liveSyncDurationCount: 3,
liveMaxLatencyDurationCount: 6,
maxBufferLength: 60, // doubled for stability on mobile
maxMaxBufferLength: 120,
liveSyncDurationCount: 5, // more segments for safety
liveMaxLatencyDurationCount: 10,
liveDurationInfinity: true,
enableWorker: true
enableWorker: true,
backStep: 0.2, // step back slightly on stall
nudgeOffset: 0.1,
nudgeMaxRetry: 5
});
window.hlsInstance = hls;
@@ -505,10 +508,22 @@
video.currentTime = parseFloat(data.value);
}
} else if (data.type === 'request_fullscreen') {
log('Fullscreen requested from parent');
const el = document.documentElement;
const requestMethod = el.requestFullscreen || el.webkitRequestFullscreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullscreen;
if (requestMethod) {
requestMethod.call(el).catch(e => log('Fullscreen error: ' + e));
// Browsers require a user gesture for fullscreen.
// This message usually comes from a Flutter button tap, so it should count as a gesture.
requestMethod.call(el).catch(e => {
log('Fullscreen API error: ' + e);
// Fallback: try element-specific request for iOS
if (video.webkitEnterFullscreen) {
video.webkitEnterFullscreen();
}
});
} else if (video.webkitEnterFullscreen) {
video.webkitEnterFullscreen();
}
}
});