fix [Windows] Player Stuttering #33 , fix autoUpdate extension setting

This commit is contained in:
kodjomoustapha 2023-10-09 14:14:01 +01:00
parent 83b287b69e
commit 9d0a2c83ff
4 changed files with 141 additions and 138 deletions

View file

@ -166,9 +166,18 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
late final VideoController _controller = VideoController(_player);
late final _streamController = AnimeStreamController(episode: widget.episode);
late final _firstVid = widget.videos.first;
late final ValueNotifier<VideoPrefs?> _video = ValueNotifier(VideoPrefs(
videoTrack: VideoTrack(
_firstVid.originalUrl, _firstVid.quality, _firstVid.quality),
headers: _firstVid.headers));
late final ValueNotifier<SubtitleTrack?> _subtitle = ValueNotifier(
SubtitleTrack.uri(_firstVid.subtitles!.first.file!,
title: _firstVid.subtitles!.first.label,
language: _firstVid.subtitles!.first.label));
final ValueNotifier<VideoPrefs?> _video = ValueNotifier(null);
final ValueNotifier<VideoPrefs?> _subtitle = ValueNotifier(null);
final ValueNotifier<double> _playbackSpeed = ValueNotifier(1.0);
bool _seekToCurrentPosition = true;
bool _initSubtitle = true;
@ -176,62 +185,60 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
final _showFitLabel = StateProvider((ref) => false);
final ValueNotifier<bool> _isCompleted = ValueNotifier(false);
final _fit = StateProvider((ref) => BoxFit.contain);
final bool _isDesktop =
Platform.isWindows || Platform.isMacOS || Platform.isLinux;
late StreamSubscription<Duration> _currentPositionSub =
_player.stream.position.listen(
(position) {
if (_initSubtitle) {
if (_firstVid.subtitles!.isNotEmpty) {
_player.setSubtitleTrack(SubtitleTrack.uri(
_firstVid.subtitles!.first.file!,
title: _firstVid.subtitles!.first.label,
language: _firstVid.subtitles!.first.label));
(position) async {
if (_seekToCurrentPosition && _currentPosition != Duration.zero) {
await _player.stream.buffer.first;
_player.seek(_currentPosition);
_isCompleted.value =
_player.state.duration.inSeconds - _currentPosition.inSeconds <= 10;
_seekToCurrentPosition = false;
} else {
_currentPosition = position;
}
if (_firstVid.subtitles!.isNotEmpty) {
if (_initSubtitle) {
_player.setSubtitleTrack(_subtitle.value!);
_initSubtitle = false;
}
}
if (_seekToCurrentPosition && _currentPosition != Duration.zero) {
_player.seek(_currentPosition);
_seekToCurrentPosition = false;
_isCompleted.value =
_player.state.duration.inSeconds - _currentPosition.inSeconds <= 10;
} else {
_currentPosition = position;
_streamController.setCurrentPosition(position.inMilliseconds);
_streamController.setAnimeHistoryUpdate();
}
},
);
late final _firstVid = widget.videos.first;
@override
void initState() {
super.initState();
_setCurrentPosition();
_currentPositionSub;
_video.value = VideoPrefs(
videoTrack: VideoTrack(
_firstVid.originalUrl, _firstVid.quality, _firstVid.quality),
headers: _firstVid.headers);
_player.open(Media(_video.value!.videoTrack!.id,
httpHeaders: _video.value!.headers));
super.initState();
}
@override
void dispose() {
_setCurrentPosition();
_player.dispose();
_currentPositionSub.cancel();
super.dispose();
}
void _onChangeVideoQuality() {
List<VideoPrefs> videoQuality = [];
List<VideoTrack> videoTracks = _player.state.tracks.video
.where((element) => element.w != null && element.h != null)
.toList();
void _setCurrentPosition() {
_streamController.setCurrentPosition(_currentPosition.inMilliseconds);
_streamController.setAnimeHistoryUpdate();
}
for (var track in videoTracks) {
videoQuality.add(VideoPrefs(videoTrack: track, isLocal: true));
}
void _onChangeVideoQuality() {
List<VideoPrefs> videoQuality = _player.state.tracks.video
.where((element) =>
element.w != null && element.h != null && widget.isLocal)
.toList()
.map((e) => VideoPrefs(videoTrack: e, isLocal: true))
.toList();
if (widget.videos.isNotEmpty && !widget.isLocal) {
for (var video in widget.videos) {
@ -252,7 +259,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
builder: (_) => CupertinoActionSheet(
title: Text(l10n.change_video_quality,
style: TextStyle(
fontSize: 20,
fontSize: 24,
color: Theme.of(context)
.textTheme
.bodyLarge!
@ -266,11 +273,9 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
children: [
Expanded(
child: Text(
quality.isLocal && !widget.isLocal
? "${_firstVid.quality} ${quality.videoTrack!.h}p"
: widget.isLocal
? _firstVid.quality
: quality.videoTrack!.title!,
widget.isLocal
? _firstVid.quality
: quality.videoTrack!.title!,
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
@ -286,12 +291,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
),
Icon(
Icons.check,
color: quality.isLocal &&
!widget.isLocal &&
"${quality.videoTrack!.title}${quality.videoTrack!.h}p" ==
"${_video.value!.videoTrack!.title}${_video.value!.videoTrack!.h}p" ||
"${_video.value!.videoTrack!.id}${_video.value!.videoTrack!.title}" ==
"${quality.videoTrack!.id}${quality.videoTrack!.title}"
color: "${_video.value!.videoTrack!.id}${_video.value!.videoTrack!.title}" ==
"${quality.videoTrack!.id}${quality.videoTrack!.title}"
? Theme.of(context).iconTheme.color
: Colors.transparent,
),
@ -311,23 +312,16 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
httpHeaders: quality.headers));
}
_seekToCurrentPosition = true;
_initSubtitle = true;
_currentPositionSub = _player.stream.position.listen(
(position) {
if (_initSubtitle && _subtitle.value != null) {
_player.setSubtitleTrack(
_subtitle.value!.subtitle!);
_initSubtitle = false;
}
(position) async {
if (_seekToCurrentPosition &&
_currentPosition != Duration.zero) {
await _player.stream.buffer.first;
_player.seek(_currentPosition);
_player.setSubtitleTrack(_subtitle.value!);
_seekToCurrentPosition = false;
} else {
_currentPosition = position;
_streamController.setCurrentPosition(
position.inMilliseconds);
_streamController.setAnimeHistoryUpdate();
}
},
);
@ -344,13 +338,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
}
void _onChangeVideoSubtitle() {
List<VideoPrefs> videoSubtitle = [];
List<SubtitleTrack> videoSubs = _player.state.tracks.subtitle
.where((element) => element.title != null && element.language != null)
List<VideoPrefs> videoSubtitle = _player.state.tracks.subtitle
.where((element) =>
element.title != null && element.language != null && widget.isLocal)
.toList()
.map((e) => VideoPrefs(isLocal: true, subtitle: e))
.toList();
for (var sub in videoSubs) {
videoSubtitle.add(VideoPrefs(isLocal: true, subtitle: sub));
}
SubtitleTrack? subtitle;
List<String> subs = [];
if (widget.videos.isNotEmpty && !widget.isLocal) {
for (var video in widget.videos) {
@ -365,15 +360,19 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
}
}
}
if (widget.isLocal) {
subtitle = _player.state.track.subtitle;
} else {
subtitle = _subtitle.value;
}
_subtitle.value ??= videoSubtitle.first;
final l10n = l10nLocalizations(context)!;
showCupertinoModalPopup(
context: context,
builder: (_) => CupertinoActionSheet(
title: Text(l10n.change_video_subtitle,
style: TextStyle(
fontSize: 20,
fontSize: 24,
color: Theme.of(context)
.textTheme
.bodyLarge!
@ -383,19 +382,19 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
actions: videoSubtitle
.toSet()
.toList()
.map((subtitle) => CupertinoActionSheetAction(
.map((sub) => CupertinoActionSheetAction(
onPressed: () {
Navigator.maybePop(_);
_subtitle.value = subtitle;
_player.setSubtitleTrack(subtitle.subtitle!);
_player.setSubtitleTrack(sub.subtitle!);
if (!widget.isLocal) _subtitle.value = sub.subtitle;
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
subtitle.subtitle!.title ??
subtitle.subtitle!.language ??
subtitle.subtitle!.channels ??
sub.subtitle!.title ??
sub.subtitle!.language ??
sub.subtitle!.channels ??
"N/A",
style: TextStyle(
fontSize: 16,
@ -409,9 +408,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
),
Icon(
Icons.check,
color: _subtitle.value != null &&
"${_subtitle.value!.subtitle!.id}${_subtitle.value!.subtitle!.title}${_subtitle.value!.subtitle!.language}" ==
"${subtitle.subtitle!.id}${subtitle.subtitle!.title}${subtitle.subtitle!.language}"
color: subtitle != null && sub.subtitle == subtitle
? Theme.of(context).iconTheme.color
: Colors.transparent,
),

View file

@ -57,38 +57,41 @@ Future fetchAnimeSourcesList(FetchAnimeSourcesListRef ref,
} else if (isar.sources.getSync(source.id!) != null) {
// log("exist");
final sourc = isar.sources.getSync(source.id!)!;
if (compareVersions(sourc.version!, source.version!) < 0) {
// log("update aivalable auto update");
if (ref.watch(autoUpdateExtensionsStateProvider)) {
final req =
await http.get(Uri.parse(source.sourceCodeUrl!));
final headers = await getHeaders(req.body, source.baseUrl!);
isar.writeTxnSync(() {
isar.sources.putSync(sourc
..headers = headers ?? ""
..isAdded = true
..sourceCode = req.body
..sourceCodeUrl = source.sourceCodeUrl
..id = source.id
..apiUrl = source.apiUrl
..baseUrl = source.baseUrl
..dateFormat = source.dateFormat
..dateFormatLocale = source.dateFormatLocale
..hasCloudflare = source.hasCloudflare
..iconUrl = source.iconUrl
..typeSource = source.typeSource
..lang = source.lang
..isNsfw = source.isNsfw
..name = source.name
..version = source.version
..versionLast = source.version
..isManga = source.isManga
..isFullData = source.isFullData ?? false
..appMinVerReq = source.appMinVerReq);
});
} else {
// log("update aivalable");
isar.sources.putSync(sourc..versionLast = source.version);
if (sourc.isAdded!) {
if (compareVersions(sourc.version!, source.version!) < 0) {
// log("update aivalable auto update");
if (ref.watch(autoUpdateExtensionsStateProvider)) {
final req =
await http.get(Uri.parse(source.sourceCodeUrl!));
final headers =
await getHeaders(req.body, source.baseUrl!);
isar.writeTxnSync(() {
isar.sources.putSync(sourc
..headers = headers ?? ""
..isAdded = true
..sourceCode = req.body
..sourceCodeUrl = source.sourceCodeUrl
..id = source.id
..apiUrl = source.apiUrl
..baseUrl = source.baseUrl
..dateFormat = source.dateFormat
..dateFormatLocale = source.dateFormatLocale
..hasCloudflare = source.hasCloudflare
..iconUrl = source.iconUrl
..typeSource = source.typeSource
..lang = source.lang
..isNsfw = source.isNsfw
..name = source.name
..version = source.version
..versionLast = source.version
..isManga = source.isManga
..isFullData = source.isFullData ?? false
..appMinVerReq = source.appMinVerReq);
});
} else {
// log("update aivalable");
isar.sources.putSync(sourc..versionLast = source.version);
}
}
}
} else {

View file

@ -59,38 +59,41 @@ Future fetchMangaSourcesList(FetchMangaSourcesListRef ref,
} else if (isar.sources.getSync(source.id!) != null) {
// log("exist");
final sourc = isar.sources.getSync(source.id!)!;
if (compareVersions(sourc.version!, source.version!) < 0) {
// log("update aivalable auto update");
if (ref.watch(autoUpdateExtensionsStateProvider)) {
final req =
await http.get(Uri.parse(source.sourceCodeUrl!));
final headers = await getHeaders(req.body, source.baseUrl!);
isar.writeTxnSync(() {
isar.sources.putSync(sourc
..headers = headers ?? ""
..isAdded = true
..sourceCode = req.body
..sourceCodeUrl = source.sourceCodeUrl
..id = source.id
..apiUrl = source.apiUrl
..baseUrl = source.baseUrl
..dateFormat = source.dateFormat
..dateFormatLocale = source.dateFormatLocale
..hasCloudflare = source.hasCloudflare
..iconUrl = source.iconUrl
..typeSource = source.typeSource
..lang = source.lang
..isNsfw = source.isNsfw
..name = source.name
..version = source.version
..versionLast = source.version
..isManga = source.isManga
..isFullData = source.isFullData ?? false
..appMinVerReq = source.appMinVerReq);
});
} else {
// log("update aivalable");
isar.sources.putSync(sourc..versionLast = source.version);
if (sourc.isAdded!) {
if (compareVersions(sourc.version!, source.version!) < 0) {
// log("update aivalable auto update");
if (ref.watch(autoUpdateExtensionsStateProvider)) {
final req =
await http.get(Uri.parse(source.sourceCodeUrl!));
final headers =
await getHeaders(req.body, source.baseUrl!);
isar.writeTxnSync(() {
isar.sources.putSync(sourc
..headers = headers ?? ""
..isAdded = true
..sourceCode = req.body
..sourceCodeUrl = source.sourceCodeUrl
..id = source.id
..apiUrl = source.apiUrl
..baseUrl = source.baseUrl
..dateFormat = source.dateFormat
..dateFormatLocale = source.dateFormatLocale
..hasCloudflare = source.hasCloudflare
..iconUrl = source.iconUrl
..typeSource = source.typeSource
..lang = source.lang
..isNsfw = source.isNsfw
..name = source.name
..version = source.version
..versionLast = source.version
..isManga = source.isManga
..isFullData = source.isFullData ?? false
..appMinVerReq = source.appMinVerReq);
});
} else {
// log("update aivalable");
isar.sources.putSync(sourc..versionLast = source.version);
}
}
}
} else {

View file

@ -1,2 +1,2 @@
const useTestSourceCode = false;
const testSourceCode = '''''';
const testSourceCode = r'''''';