Skip to content

Commit

Permalink
chore: various fixes & tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
MSOB7YY committed Jul 2, 2024
1 parent 9cf37ca commit 5e4c3e3
Show file tree
Hide file tree
Showing 38 changed files with 1,425 additions and 1,311 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/dart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ on:
jobs:
build_android:
runs-on: ubuntu-latest
env:
ACCESS_TOKEN: ${{ secrets.PAT }}

steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -90,11 +88,11 @@ jobs:
repository: namidaco/namida-snapshots
tag_name: ${{ steps.extract_version.outputs.version}}
files: |
build_final_signed/*
build_final/*
token: ${{ secrets.SNAPSHOTS_REPO_SECRET }}

- name: Upload all APKs
uses: actions/upload-artifact@v3
with:
name: all-apks
path: build_final_signed/**
path: build_final/**
96 changes: 56 additions & 40 deletions lib/base/audio_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'dart:io';

import 'package:audio_service/audio_service.dart';
import 'package:basic_audio_handler/basic_audio_handler.dart';
import 'package:flutter/scheduler.dart';
import 'package:just_audio/just_audio.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:playlist_manager/module/playlist_id.dart';
Expand Down Expand Up @@ -153,13 +152,21 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
// =================================================================================

void refreshNotification([Q? item, YoutubeIDToMediaItemCallback? youtubeIdMediaItem]) {
final exectuteOn = item ?? currentItem.value;
Q? exectuteOn = item ?? currentItem.value;
Duration? knownDur;
if (item != null) {
exectuteOn = item;
} else {
exectuteOn = currentItem.value;
knownDur = currentItemDuration.value;
}
exectuteOn?._execute(
selectable: (finalItem) {
_notificationUpdateItemSelectable(
item: finalItem,
isItemFavourite: finalItem.track.isFavourite,
itemIndex: currentIndex.value,
duration: knownDur,
);
},
youtubeID: (finalItem) {
Expand All @@ -171,7 +178,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
(int index, int queueLength) {
final streamInfo = YoutubeInfoController.current.currentYTStreams.value?.info;
final thumbnail = finalItem.getThumbnailSync();
return finalItem.toMediaItem(streamInfo, thumbnail, index, queueLength);
return finalItem.toMediaItem(streamInfo, thumbnail, index, queueLength, knownDur);
},
);
},
Expand All @@ -182,8 +189,9 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
required Selectable item,
required bool isItemFavourite,
required int itemIndex,
required Duration? duration,
}) {
mediaItem.add(item.toMediaItem(currentIndex.value, currentQueue.value.length));
mediaItem.add(item.toMediaItem(currentIndex.value, currentQueue.value.length, duration));
playbackState.add(transformEvent(PlaybackEvent(currentIndex: currentIndex.value), isItemFavourite, itemIndex));
}

Expand Down Expand Up @@ -523,10 +531,12 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
}
});

Duration? duration;

Future<Duration?> setPls() async {
if (!File(tr.path).existsSync()) throw PathNotFoundException(tr.path, const OSError(), 'Track file not found or couldn\'t be accessed.');
final dur = await setSource(
tr.toAudioSource(currentIndex.value, currentQueue.value.length),
tr.toAudioSource(currentIndex.value, currentQueue.value.length, duration),
item: pi,
startPlaying: startPlaying,
videoOptions: initialVideo == null
Expand All @@ -546,8 +556,6 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
return dur;
}

Duration? duration;

bool checkInterrupted() {
if (item.track != currentItem.value) {
return true;
Expand Down Expand Up @@ -870,42 +878,46 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
final hadCachedComments = YoutubeInfoController.current.updateCurrentCommentsSync(item.id);

Duration? duration;
Duration? notificationDuration;
VideoStreamInfo? notificationVideoInfo;
File? notificationVideoThumbnail;

bool checkInterrupted() {
if (item != currentItem.value) {
return true;
} else {
if (duration != null) _currentItemDuration.value = duration;
if (duration != null) {
_currentItemDuration.value = duration;
if (notificationDuration == null) {
notificationDuration = duration;
refreshNotification(pi, (index, ql) => item.toMediaItem(notificationVideoInfo, notificationVideoThumbnail, index, ql, duration));
}
}
return false;
}
}

Future<void> fetchFullVideoPage() async {
await YoutubeInfoController.current.updateVideoPage(
item.id,
forceRequestPage: !hadCachedVideoPage,
forceRequestComments: !hadCachedComments,
requestPage: !hadCachedVideoPage,
requestComments: !hadCachedComments,
);
}

VideoStreamInfo? info;
File? videoThumbnail;
bool notificationDidRefreshInfo = false;
bool notificationDidRefreshThumbnail = false;
void onInfoOrThumbObtained({VideoStreamInfo? info, File? thumbnail, bool forceRefreshNoti = false}) {
if (forceRefreshNoti == false && notificationDidRefreshInfo && notificationDidRefreshThumbnail) return;
void onInfoOrThumbObtained({VideoStreamInfo? info, File? thumbnail}) {
if (checkInterrupted()) return;
if (info != null) notificationDidRefreshInfo = true;
if (thumbnail != null) notificationDidRefreshThumbnail = true;
refreshNotification(pi, (index, ql) => item.toMediaItem(info, thumbnail, index, ql));
notificationVideoInfo ??= info; // we assign cuz later some functions can depend on this
notificationVideoThumbnail ??= thumbnail;
refreshNotification(pi, (index, ql) => item.toMediaItem(notificationVideoInfo, notificationVideoThumbnail, index, ql, duration));
}

info = streamsResult?.info;
videoThumbnail = item.getThumbnailSync();
if (info != null || videoThumbnail != null) {
onInfoOrThumbObtained(info: info, thumbnail: videoThumbnail);
notificationVideoInfo = streamsResult?.info;
notificationVideoThumbnail = item.getThumbnailSync();
if (notificationVideoInfo != null || notificationVideoThumbnail != null) {
onInfoOrThumbObtained(info: notificationVideoInfo, thumbnail: notificationVideoThumbnail);
}
if (videoThumbnail == null) {
if (notificationVideoThumbnail == null) {
ThumbnailManager.inst.getYoutubeThumbnailAndCache(id: item.id).then((thumbFile) => onInfoOrThumbObtained(thumbnail: thumbFile));
}

Expand Down Expand Up @@ -964,7 +976,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
/// different then it will be set later after fetching.
playedFromCacheDetails = await _trySetYTVideoWithoutConnection(
item: item,
mediaItemFn: () => item.toMediaItem(info, videoThumbnail, index, currentQueue.value.length),
mediaItemFn: () => item.toMediaItem(notificationVideoInfo, notificationVideoThumbnail, index, currentQueue.value.length, duration),
checkInterrupted: () => item != currentItem.value,
index: index,
canPlayAudioOnly: canPlayAudioOnlyFromCache,
Expand Down Expand Up @@ -1017,7 +1029,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
snackyy(message: 'Error getting streams', top: false, isError: true);
return null;
});
onInfoOrThumbObtained(info: streamsResult?.info, forceRefreshNoti: false /* we may need to force refresh if info could have changed */);
onInfoOrThumbObtained(info: streamsResult?.info);
if (checkInterrupted()) return;
YoutubeInfoController.current.currentYTStreams.value = streamsResult;
} else {
Expand All @@ -1029,11 +1041,16 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {

fetchFullVideoPage();

notificationVideoInfo = streamsResult?.info;

final audiostreams = streamsResult?.audioStreams ?? [];
final videoStreams = streamsResult?.videoStreams ?? [];
info = streamsResult?.info;

if (info == null && audiostreams.isEmpty && videoStreams.isEmpty) return;
if (audiostreams.isEmpty) {
snackyy(message: 'Error playing video, empty audio streams', top: false, isError: true);
return;
}

if (checkInterrupted()) return;
final prefferedVideoStream = _isAudioOnlyPlayback || videoStreams.isEmpty ? null : YoutubeController.inst.getPreferredStreamQuality(videoStreams, preferIncludeWebm: false);
final prefferedAudioStream =
Expand Down Expand Up @@ -1108,19 +1125,17 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
} catch (e) {
if (checkInterrupted()) return;
void showSnackError(String nextAction) {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
if (item == currentItem.value) {
snackyy(message: 'Error playing video, $nextAction: $e', top: false, isError: true);
}
});
if (item == currentItem.value) {
snackyy(message: 'Error playing video, $nextAction: $e', top: false, isError: true);
}
}

showSnackError('trying again');

printy(e, isError: true);
playedFromCacheDetails = await _trySetYTVideoWithoutConnection(
item: item,
mediaItemFn: () => item.toMediaItem(info, videoThumbnail, index, currentQueue.value.length),
mediaItemFn: () => item.toMediaItem(notificationVideoInfo, notificationVideoThumbnail, index, currentQueue.value.length, duration),
checkInterrupted: checkInterrupted,
index: index,
canPlayAudioOnly: canPlayAudioOnlyFromCache,
Expand Down Expand Up @@ -1315,6 +1330,7 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {
item: finalItem,
itemIndex: currentIndex.value,
isItemFavourite: newStat,
duration: currentItemDuration.value,
);
},
youtubeID: (finalItem) {},
Expand Down Expand Up @@ -1605,14 +1621,14 @@ class NamidaAudioVideoHandler<Q extends Playable> extends BasicAudioHandler<Q> {

// ----------------------- Extensions --------------------------
extension TrackToAudioSourceMediaItem on Selectable {
UriAudioSource toAudioSource(int currentIndex, int queueLength) {
UriAudioSource toAudioSource(int currentIndex, int queueLength, Duration? duration) {
return AudioSource.uri(
Uri.file(track.path),
tag: toMediaItem(currentIndex, queueLength),
tag: toMediaItem(currentIndex, queueLength, duration),
);
}

MediaItem toMediaItem(int currentIndex, int queueLength) {
MediaItem toMediaItem(int currentIndex, int queueLength, Duration? duration) {
final tr = track.toTrackExt();
final artist = tr.originalArtist == '' ? UnknownTags.ARTIST : tr.originalArtist;
final imagePage = tr.pathToImage;
Expand All @@ -1625,14 +1641,14 @@ extension TrackToAudioSourceMediaItem on Selectable {
artist: artist,
album: tr.hasUnknownAlbum ? '' : tr.album,
genre: tr.originalGenre,
duration: Duration(seconds: tr.duration),
duration: duration ?? Duration(seconds: tr.duration),
artUri: Uri.file(File(imagePage).existsSync() ? imagePage : AppPaths.NAMIDA_LOGO),
);
}
}

extension YoutubeIDToMediaItem on YoutubeID {
MediaItem toMediaItem(VideoStreamInfo? videoInfo, File? thumbnail, int currentIndex, int queueLength) {
MediaItem toMediaItem(VideoStreamInfo? videoInfo, File? thumbnail, int currentIndex, int queueLength, Duration? duration) {
final vi = videoInfo;
final artistAndTitle = vi?.title.splitArtistAndTitle();
final videoName = vi?.title;
Expand All @@ -1654,7 +1670,7 @@ extension YoutubeIDToMediaItem on YoutubeID {
displayTitle: videoName,
displaySubtitle: channelName,
displayDescription: "${currentIndex + 1}/$queueLength",
duration: vi?.durSeconds?.seconds ?? Duration.zero,
duration: duration ?? vi?.durSeconds?.seconds ?? Duration.zero,
artUri: Uri.file((thumbnail != null && thumbnail.existsSync()) ? thumbnail.path : AppPaths.NAMIDA_LOGO),
);
}
Expand Down
9 changes: 7 additions & 2 deletions lib/base/pull_to_refresh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,15 @@ mixin PullToRefreshMixin<T extends StatefulWidget> on State<T> implements Ticker
}

bool _isRefreshing = false;
Future<void> onRefresh(PullToRefreshCallback execute) async {
Future<void> onRefresh(PullToRefreshCallback execute, {bool forceShow = false}) async {
if (!enablePullToRefresh) return;
onVerticalDragFinish();
if (animation.value != 1 || _isRefreshing) return;
if (_isRefreshing) return;
if (animation.value != 1) {
if (!forceShow) return;
animation.animateTo(1, duration: const Duration(milliseconds: 100));
}

_isRefreshing = true;
_animation2.repeat();
await execute();
Expand Down
17 changes: 10 additions & 7 deletions lib/base/youtube_channel_controller.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import 'package:flutter/material.dart';
import 'package:youtipie/class/channels/channel_page_result.dart';
import 'package:youtipie/class/channels/tabs/channel_tab_videos_result.dart';
import 'package:youtipie/class/execute_details.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item.dart';
import 'package:youtipie/youtipie.dart';

import 'package:namida/base/youtube_streams_manager.dart';
import 'package:namida/controller/connectivity.dart';
import 'package:namida/controller/current_color.dart';
import 'package:namida/core/extensions.dart';
import 'package:namida/core/utils.dart';
import 'package:namida/youtube/class/youtube_subscription.dart';
import 'package:namida/youtube/controller/youtube_info_controller.dart';
import 'package:namida/youtube/controller/youtube_subscriptions_controller.dart';
import 'package:youtipie/youtipie.dart';

abstract class YoutubeChannelController<T extends StatefulWidget> extends State<T> with YoutubeStreamsManager {
@override
Expand All @@ -23,7 +25,7 @@ abstract class YoutubeChannelController<T extends StatefulWidget> extends State<
Color? get sortChipBGColor => CurrentColor.inst.color;

@override
void onSortChanged(void Function() fn) => setState(fn);
void onSortChanged(void Function() fn) => refreshState(fn);

late final ScrollController uploadsScrollController = ScrollController();
YoutubeSubscription? channel;
Expand Down Expand Up @@ -61,18 +63,19 @@ abstract class YoutubeChannelController<T extends StatefulWidget> extends State<
streamsPeakDates = (oldest: DateTime.fromMillisecondsSinceEpoch(oldest), newest: DateTime.fromMillisecondsSinceEpoch(newest));
}

Future<void> fetchChannelStreams(YoutiPieChannelPageResult channelPage) async {
Future<void> fetchChannelStreams(YoutiPieChannelPageResult channelPage, {bool forceRequest = false}) async {
final tab = channelPage.tabs.getVideosTab();
if (tab == null) return;
final channelID = channelPage.id;
final result = await YoutubeInfoController.channel.fetchChannelTab(channelId: channelID, tab: tab);
final details = forceRequest ? ExecuteDetails.forceRequest() : null;
final result = await YoutubeInfoController.channel.fetchChannelTab(channelId: channelID, tab: tab, details: details);
if (result == null) return;
this.channelVideoTab = result;

final st = result.items;
updatePeakDates(st);
YoutubeSubscriptionsController.inst.refreshLastFetchedTime(channelID);
setState(() {
refreshState(() {
this.channelVideoTab = result;
isLoadingInitialStreams = false;
if (channelID == channel?.channelID) {
trySortStreams();
Expand All @@ -93,7 +96,7 @@ abstract class YoutubeChannelController<T extends StatefulWidget> extends State<

if (didFetch) {
if (result.channelId == channel?.channelID) {
setState(trySortStreams);
refreshState(trySortStreams);
}
} else {
if (ConnectivityController.inst.hasConnection) lastLoadingMoreWasEmpty.value = true;
Expand Down
1 change: 1 addition & 0 deletions lib/controller/backup_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class BackupController {
AppPaths.SETTINGS_PLAYER,
AppPaths.LATEST_QUEUE,
AppPaths.YT_LIKES_PLAYLIST,
AppPaths.YT_SUBSCRIPTIONS,
AppDirs.PLAYLISTS,
AppDirs.HISTORY_PLAYLIST,
AppDirs.QUEUES,
Expand Down
7 changes: 4 additions & 3 deletions lib/controller/file_browser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF
_SortType.size: lang.SIZE,
};

void _sortItems(_SortType? type, bool? reversed, {bool refresh = true}) {
void _sortItems(_SortType? type, bool? reversed, {bool refreshState = true}) {
type ??= _sortType.value;
reversed ??= _sortReversed.value;

Expand Down Expand Up @@ -272,7 +272,7 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF
_sortType.value = type;
_sortReversed.value = reversed;

if (refresh) setState(() {});
if (refreshState) setState(() {});
}

final _showHiddenFiles = false.obs;
Expand Down Expand Up @@ -344,7 +344,7 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF
_isFetching = false;
if (isolateRes.$1.isNotEmpty) _currentFiles = isolateRes.$1;
if (isolateRes.$2.isNotEmpty) _currentFolders = isolateRes.$2;
_sortItems(null, null, refresh: false);
_sortItems(null, null, refreshState: false);
});
if (isolateRes.$3 != null) {
snackyy(title: lang.ERROR, message: isolateRes.$3!.toString(), isError: true);
Expand All @@ -367,6 +367,7 @@ class _NamidaFileBrowserState<T extends FileSystemEntity> extends State<_NamidaF
setState(() {
_currentInfoFiles = res.$1;
_currentInfoDirs = res.$2;
if (_sortType.value != _SortType.name) _sortItems(null, null, refreshState: false);
});
}
_stopInfoIsolates();
Expand Down
Loading

0 comments on commit 5e4c3e3

Please sign in to comment.