165 lines
4.9 KiB
Dart
165 lines
4.9 KiB
Dart
|
|
|
|
part of 'player_page.dart';
|
|
|
|
|
|
bool _isDanmakuLayoutChange(DanmakuPanelSettings a, DanmakuPanelSettings b) {
|
|
return a.maxRows != b.maxRows ||
|
|
a.fontSize != b.fontSize ||
|
|
a.lineHeight != b.lineHeight ||
|
|
a.fontFamily != b.fontFamily ||
|
|
a.area != b.area;
|
|
}
|
|
|
|
void _syncDanmakuFeederForSession(
|
|
DanmakuFeeder feeder,
|
|
PlaybackSession session,
|
|
double posSec, {
|
|
bool clear = false,
|
|
}) {
|
|
feeder.seekTo(posSec, clear: clear);
|
|
if (session.isDanmakuActive) {
|
|
feeder.playFrom(posSec);
|
|
} else {
|
|
feeder.freezeAt(posSec);
|
|
}
|
|
}
|
|
|
|
extension _PlayerPageDanmaku on _PlayerPageState {
|
|
DanmakuOption _buildDanmakuOption(DanmakuPanelSettings settings) {
|
|
final base = settings.toDanmakuOption(screenHeight: _danmakuOverlayHeight);
|
|
if (_playbackRate == 1.0 || _playbackRate <= 0) return base;
|
|
return base.copyWith(duration: base.duration / _playbackRate);
|
|
}
|
|
|
|
void _applyDanmakuPanelSettings(DanmakuPanelSettings settings) {
|
|
_panelSettings = settings;
|
|
_feeder.setPanelSettings(settings, option: _buildDanmakuOption(settings));
|
|
}
|
|
|
|
|
|
void _wireDanmakuListeners() {
|
|
final session = ref.read(danmakuSessionProvider).value;
|
|
if (session != null) {
|
|
_sessionState = session;
|
|
if (session is DanmakuSessionMatched &&
|
|
session.commentStatus == DanmakuCommentStatus.ready &&
|
|
!identical(session, _lastSyncedDanmakuSession)) {
|
|
_lastSyncedDanmakuSession = session;
|
|
_feeder.setComments(session.comments);
|
|
final s = _session;
|
|
if (s != null) {
|
|
_syncDanmakuFeederForSession(
|
|
_feeder,
|
|
s,
|
|
s.engine.state.position.inMilliseconds / 1000.0,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
final settingsPanel = ref
|
|
.read(danmakuSettingsProvider)
|
|
.value
|
|
?.panelSettings;
|
|
if (settingsPanel != null && settingsPanel != _panelSettings) {
|
|
_applyDanmakuPanelSettings(settingsPanel);
|
|
}
|
|
|
|
ref.listen<AsyncValue<DanmakuSessionState>>(danmakuSessionProvider, (
|
|
prev,
|
|
next,
|
|
) {
|
|
final state = next.value;
|
|
if (state == null) return;
|
|
_sessionState = state;
|
|
|
|
if (state is DanmakuSessionMatched &&
|
|
state.commentStatus == DanmakuCommentStatus.ready) {
|
|
_lastSyncedDanmakuSession = state;
|
|
_feeder.setComments(state.comments);
|
|
final s = _session;
|
|
if (s != null) {
|
|
final posSec = s.engine.state.position.inMilliseconds / 1000.0;
|
|
_syncDanmakuFeederForSession(_feeder, s, posSec);
|
|
}
|
|
} else {
|
|
_lastSyncedDanmakuSession = null;
|
|
_feeder.setComments(const []);
|
|
}
|
|
|
|
_invalidateBottomBar();
|
|
_refreshPanel();
|
|
_invalidateDanmakuOverlay();
|
|
});
|
|
|
|
ref.listen<AsyncValue<DanmakuSettingsState>>(danmakuSettingsProvider, (
|
|
prev,
|
|
next,
|
|
) {
|
|
final settings = next.value;
|
|
if (settings == null) return;
|
|
final newPanel = settings.panelSettings;
|
|
final oldPanel = _panelSettings;
|
|
final panelChanged = oldPanel != newPanel;
|
|
final previousSettings = prev?.value;
|
|
final keywordsChanged =
|
|
previousSettings != null &&
|
|
!listEquals(
|
|
previousSettings.blockedKeywords,
|
|
settings.blockedKeywords,
|
|
);
|
|
|
|
final enabledChanged = oldPanel.enabled != newPanel.enabled;
|
|
final offsetChanged = oldPanel.offset != newPanel.offset;
|
|
final layoutChanged = _isDanmakuLayoutChange(oldPanel, newPanel);
|
|
|
|
|
|
final opacityChanged = oldPanel.opacity != newPanel.opacity;
|
|
if (panelChanged) {
|
|
_applyDanmakuPanelSettings(newPanel);
|
|
if (enabledChanged) {
|
|
_invalidateBottomBar();
|
|
}
|
|
_invalidateDanmakuOverlay();
|
|
final s = _session;
|
|
if ((enabledChanged ||
|
|
offsetChanged ||
|
|
layoutChanged ||
|
|
opacityChanged) &&
|
|
s != null) {
|
|
final posSec = s.engine.state.position.inMilliseconds / 1000.0;
|
|
_syncDanmakuFeederForSession(_feeder, s, posSec, clear: true);
|
|
}
|
|
}
|
|
if (panelChanged || keywordsChanged) {
|
|
_refreshPanel();
|
|
}
|
|
});
|
|
}
|
|
|
|
bool get _danmakuLoaded =>
|
|
_sessionState is DanmakuSessionMatched ||
|
|
_sessionState is DanmakuSessionEmpty;
|
|
|
|
bool get _danmakuSearching =>
|
|
_sessionState is DanmakuSessionMatching ||
|
|
(_sessionState is DanmakuSessionMatched &&
|
|
(_sessionState as DanmakuSessionMatched).commentStatus ==
|
|
DanmakuCommentStatus.loading);
|
|
|
|
List<DanmakuMatchCandidate> get _danmakuMatches {
|
|
final s = _sessionState;
|
|
return s is DanmakuSessionMatched ? s.matches : const [];
|
|
}
|
|
|
|
int get _danmakuSelectedMatchIndex {
|
|
final s = _sessionState;
|
|
return s is DanmakuSessionMatched ? s.selectedIndex : -1;
|
|
}
|
|
|
|
int get _danmakuCommentCount {
|
|
final s = _sessionState;
|
|
return s is DanmakuSessionMatched ? s.comments.length : 0;
|
|
}
|
|
}
|