fix: Move calculation logic to lib_mpv subtitles

This commit is contained in:
PartyDonut 2025-07-28 21:32:37 +02:00
parent c446210e6a
commit 5fac088e2d
8 changed files with 42 additions and 63 deletions

View file

@ -39,8 +39,8 @@ class MediaControlsWrapper extends BaseAudioHandler {
Stream<PlayerState>? get stateStream => _player?.stateStream;
PlayerState? get lastState => _player?.lastState;
Widget? subtitleWidget(bool showOverlay, {double? menuHeight}) =>
_player?.subtitles(showOverlay, menuHeight: menuHeight);
Widget? subtitleWidget(bool showOverlay, {GlobalKey? controlsKey}) =>
_player?.subtitles(showOverlay, menuKey: controlsKey);
Widget? videoWidget(Key key, BoxFit fit) => _player?.videoWidget(key, fit);
final Ref ref;

View file

@ -20,7 +20,7 @@ abstract class BasePlayer {
);
Widget? subtitles(
bool showOverlay, {
double? menuHeight,
GlobalKey? menuKey,
});
Future<void> dispose();
Future<void> open(String url, bool play);

View file

@ -191,7 +191,7 @@ class LibMDK extends BasePlayer {
);
@override
Widget? subtitles(bool showOverlay, {double? menuHeight}) => null;
Widget? subtitles(bool showOverlay, {GlobalKey? menuKey}) => null;
@override
Future<void> setVolume(double volume) async => _controller?.setVolume(volume / 100);

View file

@ -168,13 +168,13 @@ class LibMPV extends BasePlayer {
@override
Widget? subtitles(
bool showOverlay, {
double? menuHeight, // Passed from video_player_controls.dart which owns the menu UI
GlobalKey? menuKey,
}) =>
_controller != null
? _VideoSubtitles(
controller: _controller!,
showOverlay: showOverlay,
menuHeight: menuHeight, // Forward the measured height for accurate positioning
menuKey: menuKey,
)
: null;
@ -198,12 +198,12 @@ class LibMPV extends BasePlayer {
class _VideoSubtitles extends ConsumerStatefulWidget {
final VideoController controller;
final bool showOverlay;
final double? menuHeight; // Accurate measurement from controls, null triggers fallback positioning
final GlobalKey? menuKey;
const _VideoSubtitles({
required this.controller,
this.showOverlay = false,
this.menuHeight, // Receives pre-measured height rather than measuring internally
this.menuKey,
});
@override
@ -216,15 +216,16 @@ class _VideoSubtitlesState extends ConsumerState<_VideoSubtitles> {
List<String>? _lastSubtitleList;
StreamSubscription<List<String>>? subscription;
double? _cachedMenuHeight;
@override
void initState() {
super.initState(); // Move to very start as per best practices
super.initState();
subtitle = widget.controller.player.state.subtitle;
subscription = widget.controller.player.stream.subtitle.listen((value) {
if (mounted) {
setState(() {
subtitle = value;
// Invalidate cache when subtitle changes
_lastSubtitleList = null;
});
}
@ -239,30 +240,29 @@ class _VideoSubtitlesState extends ConsumerState<_VideoSubtitles> {
@override
Widget build(BuildContext context) {
final settings = ref.watch(subtitleSettingsProvider);
final padding = MediaQuery.of(context).padding;
_measureMenuHeight();
final settings = ref.watch(subtitleSettingsProvider);
final padding = MediaQuery.paddingOf(context);
// Cache processed subtitle text to avoid unnecessary computation
if (!const ListEquality().equals(subtitle, _lastSubtitleList)) {
_cachedSubtitleText = subtitle.where((line) => line.trim().isNotEmpty).map((line) => line.trim()).join('\n');
_lastSubtitleList = List<String>.from(subtitle);
_cachedSubtitleText = subtitle.where((line) => line.trim().isNotEmpty).map((line) => line.trim()).join('\n');
}
final text = _cachedSubtitleText;
// Extract libass enabled check for clarity
final bool isLibassEnabled = widget.controller.player.platform?.configuration.libass ?? false;
// Early return for cases where subtitles shouldn't be rendered
if (isLibassEnabled || text.isEmpty) {
return const SizedBox.shrink();
}
// Use the utility for offset calculation with passed menuHeight
final offset = SubtitlePositionCalculator.calculateOffset(
settings: settings,
showOverlay: widget.showOverlay,
screenHeight: MediaQuery.of(context).size.height,
menuHeight: widget.menuHeight,
screenHeight: MediaQuery.sizeOf(context).height,
menuHeight: _cachedMenuHeight,
);
return SubtitleText(
@ -272,4 +272,19 @@ class _VideoSubtitlesState extends ConsumerState<_VideoSubtitles> {
text: text,
);
}
void _measureMenuHeight() {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || widget.menuKey == null) return;
final RenderBox? renderBox = widget.menuKey?.currentContext?.findRenderObject() as RenderBox?;
final newHeight = renderBox?.size.height;
if (newHeight != _cachedMenuHeight && newHeight != null) {
setState(() {
_cachedMenuHeight = newHeight;
});
}
});
}
}