Files
sm-emby-share/lib/features/player/player_page_overlays.dart
T
2026-07-14 11:11:36 +08:00

122 lines
4.1 KiB
Dart

part of 'player_page.dart';
extension _PlayerPageOverlays on _PlayerPageState {
List<Widget> _buildVideoOverlays(PlaybackSession session) {
return [
Positioned(
top: 20,
left: 0,
right: 0,
bottom: 0,
child: ValueListenableBuilder<int>(
valueListenable: _danmakuOverlayVersion,
builder: (context, value, child) {
if (!_danmakuLoaded || !_panelSettings.enabled) {
return const SizedBox.shrink();
}
return IgnorePointer(
child: ValueListenableBuilder<bool>(
valueListenable: _bufferingOverlayVisible,
builder: (context, buffering, child) {
return Opacity(opacity: buffering ? 0.0 : 1.0, child: child);
},
child: LayoutBuilder(
builder: (context, constraints) {
final screenHeight = constraints.maxHeight.isFinite
? constraints.maxHeight
: null;
_danmakuOverlayHeight = screenHeight;
final option = _buildDanmakuOption(_panelSettings);
if (screenHeight != null &&
(screenHeight != _danmakuOverlaySyncedHeight ||
!identical(
_panelSettings,
_danmakuOverlaySyncedSettings,
))) {
_danmakuOverlaySyncedHeight = screenHeight;
_danmakuOverlaySyncedSettings = _panelSettings;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
_feeder.setPanelSettings(
_panelSettings,
option: _buildDanmakuOption(_panelSettings),
);
});
}
return DanmakuScreen(
option: option,
createdController: (c) {
_feeder.attach(c);
_feeder.setPanelSettings(
_panelSettings,
option: option,
);
final pos = session.engine.state.position;
_syncDanmakuFeederForSession(
_feeder,
session,
pos.inMilliseconds / 1000.0,
);
},
);
},
),
),
);
},
),
),
Positioned.fill(
child: ValueListenableBuilder<int>(
valueListenable: _subtitleOverlayVersion,
builder: (context, value, child) {
return StyledSubtitleOverlay(
player: session.engine,
settings: _subtitleSettings,
externalLines: session.externalSubtitleLines,
externalActive: session.activeExternalSubtitle,
);
},
),
),
Positioned.fill(
child: BufferingOverlay(
player: session.engine,
speedMonitor: session.speedMonitor,
suppress: _switchInFlight,
onBufferingChanged: (value) {
if (mounted) _bufferingOverlayVisible.value = value;
},
),
),
ValueListenableBuilder<bool>(
valueListenable: _debugHudVisible,
builder: (context, visible, _) {
if (!visible) return const SizedBox.shrink();
return PlayerDebugHud(
engine: session.engine,
frameMonitor: _frameJankMonitor,
);
},
),
];
}
List<Widget> _buildPipOverlays(PlaybackSession session) {
return [
Positioned.fill(
child: BufferingOverlay(
player: session.engine,
speedMonitor: session.speedMonitor,
onBufferingChanged: (value) {
if (mounted) _bufferingOverlayVisible.value = value;
},
),
),
];
}
}