Skip to content

Commit

Permalink
chore: various fixes & tweaks
Browse files Browse the repository at this point in the history
- fix thumbnails in notification (hf)
- fix initialization for pullToRefreshMixin
- fix tracks search list not refreshing after sorting
- properly show remaining duration in lrc fullscreen (if enabled)
- ui tweaks for channel page & subpage
- properly use PublishTime date as utc
  • Loading branch information
MSOB7YY committed Jul 7, 2024
1 parent c3adcd1 commit 00cae0f
Show file tree
Hide file tree
Showing 17 changed files with 159 additions and 117 deletions.
66 changes: 34 additions & 32 deletions lib/base/audio_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
required YoutubeIDToMediaItemCallback? youtubeIdMediaItem,
}) {
youtubeIdMediaItem ??= (index, ql) {
return item.toMediaItem(_ytNotificationVideoInfo, _ytNotificationVideoThumbnail, index, ql, _ytNotificationDuration);
return item.toMediaItem(_ytNotificationVideoInfo, _ytNotificationVideoThumbnail, index, ql, currentItemDuration.value);
};
final index = currentIndex.value;
final ql = currentQueue.value.length;
Expand Down Expand Up @@ -845,7 +845,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
}
}

Duration? _ytNotificationDuration;
// Duration? _ytNotificationDuration;
VideoStreamInfo? _ytNotificationVideoInfo;
File? _ytNotificationVideoThumbnail;

Expand Down Expand Up @@ -882,21 +882,23 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
final hadCachedVideoPage = YoutubeInfoController.current.updateVideoPageSync(item.id);
final hadCachedComments = YoutubeInfoController.current.updateCurrentCommentsSync(item.id);

Duration? duration;
Duration? duration = streamsResult?.audioStreams.firstOrNull?.duration;
_ytNotificationVideoInfo = streamsResult?.info;
_ytNotificationVideoThumbnail = item.getThumbnailSync();

bool checkInterrupted({bool refreshNoti = true}) {
if (item != currentItem.value) {
return true;
} else {
final curr = currentItem.value;
if (curr is YoutubeID && item.id == curr.id) {
if (duration != null) {
final refresh = _currentItemDuration.value == null && refreshNoti;
_currentItemDuration.value = duration;
final refresh = _ytNotificationDuration == null && refreshNoti;
_ytNotificationDuration = duration;
if (refresh) {
refreshNotification(pi, (index, ql) => item.toMediaItem(_ytNotificationVideoInfo, _ytNotificationVideoThumbnail, index, ql, duration));
}
}
return false;
} else {
return true;
}
}

Expand All @@ -916,11 +918,9 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
refreshNotification(pi, (index, ql) => item.toMediaItem(_ytNotificationVideoInfo, _ytNotificationVideoThumbnail, index, ql, duration));
}

_ytNotificationVideoInfo = streamsResult?.info;
_ytNotificationVideoThumbnail = item.getThumbnailSync();
if (_ytNotificationVideoInfo != null || _ytNotificationVideoThumbnail != null) {
onInfoOrThumbObtained(info: _ytNotificationVideoInfo, thumbnail: _ytNotificationVideoThumbnail);
}
// -- we no longer check if any of these 2 is not null, cuz info like index & queue length needs to be updated asap
onInfoOrThumbObtained(info: _ytNotificationVideoInfo, thumbnail: _ytNotificationVideoThumbnail);

if (_ytNotificationVideoThumbnail == null) {
ThumbnailManager.inst.getYoutubeThumbnailAndCache(id: item.id).then((thumbFile) => onInfoOrThumbObtained(thumbnail: thumbFile));
}
Expand All @@ -940,17 +940,18 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
}
}

final playerStoppingSeikoo = Completer<bool>(); // to prevent accidental stopping if getAvailableStreams was faster than fade effect
Completer<bool>? playerStoppingSeikoo; // to prevent accidental stopping if getAvailableStreams was faster than fade effect
if (enableCrossFade) {
playerStoppingSeikoo.complete(true);
// -- do nothing
} else {
playerStoppingSeikoo = Completer<bool>();
if (isPlaying.value) {
// wait for pausing only if playing.
pauseAndDispose(fadeMS: 100, stillSameItem: () => item == currentItem.value).then((_) {
playerStoppingSeikoo.complete(true);
pauseAndStop(fadeMS: 100, stillSameItem: () => item == currentItem.value).then((_) {
playerStoppingSeikoo?.complete(true);
});
} else {
if (item == currentItem.value) await super.onDispose();
if (item == currentItem.value) await stop();
playerStoppingSeikoo.complete(true);
}
}
Expand Down Expand Up @@ -985,14 +986,13 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
index: index,
canPlayAudioOnly: canPlayAudioOnlyFromCache,
disableVideo: _isAudioOnlyPlayback,
whatToAwait: () async => await playerStoppingSeikoo.future,
whatToAwait: playerStoppingSeikoo?.future,
startPlaying: startPlaying,
possibleAudioFiles: audioCacheMap[item.id] ?? [],
possibleLocalFiles: Indexer.inst.allTracksMappedByYTID[item.id] ?? [],
);

duration ??= playedFromCacheDetails.duration;

if (checkInterrupted()) return; // this also refreshes currentDuration

if (!ConnectivityController.inst.hasConnection && playedFromCacheDetails.audio == null) {
Expand Down Expand Up @@ -1033,8 +1033,9 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
snackyy(message: 'Error getting streams', top: false, isError: true);
return null;
});
duration ??= streamsResult?.audioStreams.firstOrNull?.duration;
onInfoOrThumbObtained(info: streamsResult?.info);
if (checkInterrupted()) return;
if (checkInterrupted(refreshNoti: false)) return; // -- onInfoOrThumbObtained refreshes notification.
YoutubeInfoController.current.currentYTStreams.value = streamsResult;
} else {
YoutubeInfoController.current.currentYTStreams.value = streamsResult;
Expand Down Expand Up @@ -1101,7 +1102,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
maxTotalCacheSize: _defaultMaxCache,
);
}
await playerStoppingSeikoo.future;
await playerStoppingSeikoo?.future;
if (checkInterrupted()) return;

if (shouldResetAudioSource && prefferedAudioStream != null && prefferedAudioStreamUrl != null) {
Expand All @@ -1119,6 +1120,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
videoOptions: videoOptions,
isVideoFile: false,
);
if (checkInterrupted()) return;
} else if (videoOptions != null) {
_latestVideoOptions = videoOptions;
await setVideo(videoOptions);
Expand All @@ -1142,17 +1144,17 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
index: index,
canPlayAudioOnly: canPlayAudioOnlyFromCache,
disableVideo: _isAudioOnlyPlayback,
whatToAwait: () async => await playerStoppingSeikoo.future,
whatToAwait: playerStoppingSeikoo?.future,
startPlaying: startPlaying,
possibleAudioFiles: audioCacheMap[item.id] ?? [],
possibleLocalFiles: Indexer.inst.allTracksMappedByYTID[item.id] ?? [],
);
if (!checkInterrupted()) {
generateWaveform();
if (!okaySetFromCache()) {
showSnackError('skipping');
skipToNext();
}
duration ??= playedFromCacheDetails.duration;
if (checkInterrupted()) return; // this also refreshes currentDuration
generateWaveform();
if (!okaySetFromCache()) {
showSnackError('skipping');
skipToNext();
}
}
}
Expand All @@ -1171,7 +1173,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
required int index,
required bool canPlayAudioOnly,
required bool disableVideo,
required Future<void> Function() whatToAwait,
required Future<void>? whatToAwait,
required bool Function() startPlaying,
required List<AudioCacheDetails> possibleAudioFiles,
required List<Track> possibleLocalFiles,
Expand Down Expand Up @@ -1219,7 +1221,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
// ------ Playing ------
if (cachedVideo != null && cachedAudio != null && !disableVideo) {
// -- play audio & video
await whatToAwait();
await whatToAwait;
try {
if (checkInterrupted()) return nullResult;
final dur = await setSource(
Expand Down Expand Up @@ -1252,7 +1254,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
}
} else if (cachedAudio != null && canPlayAudioOnly) {
// -- play audio only
await whatToAwait();
await whatToAwait;
if (checkInterrupted()) return nullResult;
final dur = await setSource(
AudioSource.file(cachedAudio.file.path, tag: mediaItemFn()),
Expand Down
19 changes: 13 additions & 6 deletions lib/base/pull_to_refresh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,19 @@ mixin PullToRefreshMixin<T extends StatefulWidget> on State<T> implements Ticker
}

_isRefreshing = true;
_animation2.repeat();
await execute();
await _animation2.fling();
_animation2.stop();
_isRefreshing = false;
onVerticalDragFinish();
try {
_animation2.repeat();
await execute();
await _animation2.fling();
_animation2.stop();
_isRefreshing = false;
onVerticalDragFinish();
} catch (_) {
_animation2.stop();
_isRefreshing = false;
onVerticalDragFinish();
rethrow;
}
}

Widget get pullToRefreshWidget {
Expand Down
14 changes: 7 additions & 7 deletions lib/base/youtube_channel_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ abstract class YoutubeChannelController<T extends StatefulWidget> extends State<
}
}

refreshState(() {
this.channelVideoTab = newResult;
isLoadingInitialStreams = false;
if (newResult != null && channelID == channel?.channelID) {
trySortStreams();
}
});
if (channelID == channel?.channelID) {
refreshState(() {
isLoadingInitialStreams = false;
this.channelVideoTab = newResult;
if (newResult != null) trySortStreams();
});
}
}
}
3 changes: 1 addition & 2 deletions lib/controller/file_browser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF

@override
void initState() {
super.initState();
NamidaStorage.inst.getStorageDirectories().then((paths) {
_mainStoragePaths.addAll(paths);
_fetchFiles(Directory(widget.initialDirectory ?? paths.first));
Expand All @@ -678,8 +679,6 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF
}
}
_initIconsLookup();

super.initState();
}

@override
Expand Down
5 changes: 2 additions & 3 deletions lib/controller/search_sort_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -622,9 +622,8 @@ class SearchSortController {
reverse: reverse,
list: trackSearchTemp.value,
onDone: (sortType, isReverse) {
if (!isAuto) {
settings.save(tracksSortSearch: sortType, tracksSortSearchReversed: isReverse);
}
if (!isAuto) settings.save(tracksSortSearch: sortType, tracksSortSearchReversed: isReverse);
trackSearchTemp.refresh();
},
);
}
Expand Down
10 changes: 8 additions & 2 deletions lib/controller/storage_cache_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ class _ImageTrimmer {

final partialFiles = <File>[];
final maxAccessed = DateTime.now();
final zDateTime = DateTime(0);
images.sortBy((e) {
if (e is File) {
if (e.path.endsWith('.temp')) {
Expand All @@ -583,7 +584,7 @@ class _ImageTrimmer {
} catch (_) {}
}
}
return 0;
return zDateTime;
});
for (int i = 0; i < partialFiles.length; i++) {
try {
Expand All @@ -595,16 +596,21 @@ class _ImageTrimmer {
excess -= partialFiles.length;
if (excess <= 0) return;

for (int i = 0; i < excess; i++) {
int imagesLength = images.length;
for (int i = 0; i < excess;) {
final element = images[i];
if (element is File) {
try {
element.deleteSync();
i++;
imagesLength--;
continue;
} catch (_) {}
}
// if not continued safely, i-- indicating that we still need to delete more
i--;
imagesLength--;
if (imagesLength <= 0) break; // just to be safe that i-- doesnt mess things up
}
}
}
Expand Down
15 changes: 6 additions & 9 deletions lib/controller/thumbnail_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ThumbnailManager {
if (imageUrl != null && imageUrl.length > 1) {
finalUrl = imageUrl.last.splitFirst('?').replaceAll('/', '_');
} else {
if (finalUrl != null) finalUrl = '${finalUrl.splitLast('/').splitFirst('=')}.png';
if (finalUrl != null) finalUrl = '${finalUrl.splitLast('/')}.png'; // we need the quality after the =
}

final dirPrefix = isTemp ? 'temp/' : '';
Expand Down Expand Up @@ -137,6 +137,7 @@ class ThumbnailManager {
if (file == null) return null;
final downloaded = await _getYoutubeThumbnail(
itemId: videoId,
urls: null,
isVideo: true,
isImportantInCache: false,
destinationFile: file,
Expand All @@ -156,7 +157,7 @@ class ThumbnailManager {

Future<File?> _getYoutubeThumbnail({
required String itemId,
List<String>? urls,
required List<String>? urls,
required bool isVideo,
required bool lowerResYTID,
required bool isTemp,
Expand All @@ -170,13 +171,9 @@ class ThumbnailManager {
if (activeRequest != null) return activeRequest;

final links = <String>[];
if (isVideo && (urls == null || urls.isEmpty)) {
final yth = YoutiPieVideoThumbnail(itemId);
if (lowerResYTID) {
links.addAll(yth.allQualitiesExceptHighest);
} else {
links.addAll(yth.allQualitiesByHighest);
}
if (isVideo) {
final yth = lowerResYTID ? YoutiPieVideoThumbnail.mixLow(itemId) : YoutiPieVideoThumbnail.mix(itemId);
links.addAll(yth);
}
if (urls != null) links.addAll(urls);
if (links.isEmpty) return null;
Expand Down
Loading

0 comments on commit 00cae0f

Please sign in to comment.