feat: failsafe pocketbase requests, removal of unneeded preferences options & vertical playbutton actions

This commit is contained in:
Kingkor Roy Tirtho 2023-02-06 09:45:20 +06:00
parent ee46d0970b
commit d68d150d3f
6 changed files with 58 additions and 152 deletions

View File

@ -142,13 +142,13 @@ class PlaybuttonCard extends HookWidget {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
bottom: 10, bottom: 10,
end: 5, end: 5,
child: Row( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
if (!isPlaying) addToQueueButton, if (!isPlaying) addToQueueButton,
if (platform != TargetPlatform.linux) if (platform != TargetPlatform.linux)
const SizedBox(width: 5), const SizedBox(height: 5),
playButton, playButton,
], ],
), ),

View File

@ -1,7 +1,9 @@
import 'dart:async'; import 'dart:async';
import 'package:catcher/catcher.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/video.dart'; import 'package:spotube/extensions/video.dart';
import 'package:spotube/extensions/album_simple.dart'; import 'package:spotube/extensions/album_simple.dart';
@ -65,7 +67,7 @@ class SpotubeTrack extends Track {
uri = track.uri; uri = track.uri;
} }
static Future<SpotubeTrack> fromFetchTrack( static Future<SpotubeTrack> fetchFromTrack(
Track track, UserPreferences preferences) async { Track track, UserPreferences preferences) async {
final artists = (track.artists ?? []) final artists = (track.artists ?? [])
.map((ar) => ar.name) .map((ar) => ar.name)
@ -79,16 +81,17 @@ class SpotubeTrack extends Track {
onlyCleanArtist: true, onlyCleanArtist: true,
).trim(); ).trim();
final cachedTracks = await pb.collection(BackendTrack.collection).getList( final cachedTracks = await Future<RecordModel?>.value(
filter: "spotify_id = '${track.id}'", pb
sort: "-votes", .collection(BackendTrack.collection)
page: 0, .getFirstListItem("spotify_id = '${track.id}'"),
perPage: 1, ).catchError((e, stack) {
); Catcher.reportCheckedError(e, stack);
return null;
});
final cachedTrack = cachedTracks.items.isNotEmpty final cachedTrack =
? BackendTrack.fromRecord(cachedTracks.items.first) cachedTracks != null ? BackendTrack.fromRecord(cachedTracks) : null;
: null;
Video ytVideo; Video ytVideo;
List<Video> siblings = []; List<Video> siblings = [];
@ -127,13 +130,17 @@ class SpotubeTrack extends Track {
final ytUri = chosenStreamInfo.url.toString(); final ytUri = chosenStreamInfo.url.toString();
if (cachedTrack == null) { if (cachedTrack == null) {
await pb.collection(BackendTrack.collection).create( await Future<RecordModel?>.value(
body: BackendTrack( pb.collection(BackendTrack.collection).create(
spotifyId: track.id!, body: BackendTrack(
youtubeId: ytVideo.id.value, spotifyId: track.id!,
votes: 0, youtubeId: ytVideo.id.value,
).toJson(), votes: 0,
); ).toJson(),
)).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
} }
if (preferences.predownload && if (preferences.predownload &&
@ -205,32 +212,38 @@ class SpotubeTrack extends Track {
final ytUri = chosenStreamInfo.url.toString(); final ytUri = chosenStreamInfo.url.toString();
final cachedTracks = await pb.collection(BackendTrack.collection).getList( final cachedTracks = await Future<RecordModel?>.value(
filter: "spotify_id = '$id' && youtube_id = '${video.id.value}'", pb.collection(BackendTrack.collection).getFirstListItem(
sort: "-votes", "spotify_id = '$id' && youtube_id = '${video.id.value}'"),
page: 0, ).catchError((e, stack) {
perPage: 1, Catcher.reportCheckedError(e, stack);
); return null;
});
final cachedTrack = cachedTracks.items.isNotEmpty final cachedTrack =
? BackendTrack.fromRecord(cachedTracks.items.first) cachedTracks != null ? BackendTrack.fromRecord(cachedTracks) : null;
: null;
if (cachedTrack == null) { if (cachedTrack == null) {
await pb.collection(BackendTrack.collection).create( await Future<RecordModel?>.value(
body: BackendTrack( pb.collection(BackendTrack.collection).create(
spotifyId: id!, body: BackendTrack(
youtubeId: video.id.value, spotifyId: id!,
votes: 1, youtubeId: video.id.value,
).toJson(), votes: 1,
); ).toJson(),
)).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
} else { } else {
await pb.collection(BackendTrack.collection).update( await Future<RecordModel?>.value(
pb.collection(BackendTrack.collection).update(
cachedTrack.id, cachedTrack.id,
body: { body: {"votes": cachedTrack.votes + 1},
"votes": cachedTrack.votes + 1, )).catchError((e, stack) {
}, Catcher.reportCheckedError(e, stack);
); return null;
});
} }
if (preferences.predownload && if (preferences.predownload &&

View File

@ -9,10 +9,8 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart'; import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
import 'package:spotube/components/shared/adaptive/adaptive_list_tile.dart'; import 'package:spotube/components/shared/adaptive/adaptive_list_tile.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/main.dart'; import 'package:spotube/main.dart';
import 'package:spotube/collections/spotify_markets.dart'; import 'package:spotube/collections/spotify_markets.dart';
import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/provider/auth_provider.dart'; import 'package:spotube/provider/auth_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@ -41,10 +39,6 @@ class SettingsPage extends HookConsumerWidget {
preferences.setDownloadLocation(dirStr); preferences.setDownloadLocation(dirStr);
}, [preferences.downloadLocation]); }, [preferences.downloadLocation]);
var ytSearchFormatController = useTextEditingController(
text: preferences.ytSearchFormat,
);
return SafeArea( return SafeArea(
child: PlatformScaffold( child: PlatformScaffold(
appBar: PageWindowTitleBar( appBar: PageWindowTitleBar(
@ -379,83 +373,6 @@ class SettingsPage extends HookConsumerWidget {
), ),
), ),
), ),
AdaptiveListTile(
leading: const Icon(SpotubeIcons.screenSearch),
title: const SizedBox(
height: 50,
width: 200,
child: Align(
alignment: Alignment.centerLeft,
child: AutoSizeText(
"Format of the YouTube Search term",
maxLines: 2,
),
),
),
subtitle: const PlatformText("(Case sensitive)"),
breakOn: Breakpoints.lg,
trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 450),
child: PlatformTextField(
controller: ytSearchFormatController,
suffix: PlatformFilledButton(
child: const Icon(SpotubeIcons.save),
onPressed: () {
preferences.setYtSearchFormat(
ytSearchFormatController.value.text,
);
},
),
onSubmitted: (value) {
preferences.setYtSearchFormat(value);
update?.call(() {});
},
),
),
),
AdaptiveListTile(
leading: const Icon(SpotubeIcons.barChart),
title: SizedBox(
height: 50,
width: 180,
child: Align(
alignment: Alignment.centerLeft,
child: AutoSizeText(
"Track Match Algorithm",
maxLines: 1,
style: PlatformTextTheme.of(context).body,
),
),
),
trailing: (context, update) =>
PlatformDropDownMenu<SpotubeTrackMatchAlgorithm>(
value: preferences.trackMatchAlgorithm,
items: [
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.authenticPopular,
child: const PlatformText(
"Popular from Author",
),
),
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.popular,
child: const PlatformText(
"Accurately Popular",
),
),
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.youtube,
child: const PlatformText("YouTube's Top choice"),
),
],
onChanged: (value) {
if (value != null) {
preferences.setTrackMatchAlgorithm(value);
update?.call(() {});
}
},
),
),
PlatformText( PlatformText(
" Downloads", " Downloads",
style: PlatformTextTheme.of(context) style: PlatformTextTheme.of(context)

View File

@ -52,7 +52,7 @@ class Downloader with ChangeNotifier {
// Using android Audio Focus to keep the app run in background // Using android Audio Focus to keep the app run in background
// _playback.mobileAudioService?.session?.setActive(true); // _playback.mobileAudioService?.session?.setActive(true);
grabberQueue.add(() async { grabberQueue.add(() async {
final track = await SpotubeTrack.fromFetchTrack( final track = await SpotubeTrack.fetchFromTrack(
baseTrack, baseTrack,
ref.read(userPreferencesProvider), ref.read(userPreferencesProvider),
); );

View File

@ -40,7 +40,7 @@ class PlaylistQueue {
if (e["path"] != null) { if (e["path"] != null) {
return LocalTrack.fromJson(jsonTrack); return LocalTrack.fromJson(jsonTrack);
} else if (i == json["active"] && !json.containsKey("path")) { } else if (i == json["active"] && !json.containsKey("path")) {
return await SpotubeTrack.fromFetchTrack( return await SpotubeTrack.fetchFromTrack(
Track.fromJson(jsonTrack), Track.fromJson(jsonTrack),
preferences, preferences,
); );
@ -63,7 +63,7 @@ class PlaylistQueue {
if (e["path"] != null) { if (e["path"] != null) {
return LocalTrack.fromJson(jsonTrack); return LocalTrack.fromJson(jsonTrack);
} else if (i == json["active"] && !json.containsKey("path")) { } else if (i == json["active"] && !json.containsKey("path")) {
return await SpotubeTrack.fromFetchTrack( return await SpotubeTrack.fetchFromTrack(
Track.fromJson(jsonTrack), Track.fromJson(jsonTrack),
preferences, preferences,
); );
@ -196,7 +196,7 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
!isPreSearching) { !isPreSearching) {
isPreSearching = true; isPreSearching = true;
final tracks = state!.tracks.toList(); final tracks = state!.tracks.toList();
tracks[state!.active + 1] = await SpotubeTrack.fromFetchTrack( tracks[state!.active + 1] = await SpotubeTrack.fetchFromTrack(
state!.tracks.elementAt(state!.active + 1), state!.tracks.elementAt(state!.active + 1),
preferences, preferences,
); );
@ -355,7 +355,7 @@ class PlaylistQueueNotifier extends PersistedStateNotifier<PlaylistQueue?> {
} }
if (state!.activeTrack is! SpotubeTrack) { if (state!.activeTrack is! SpotubeTrack) {
final tracks = state!.tracks.toList(); final tracks = state!.tracks.toList();
tracks[state!.active] = await SpotubeTrack.fromFetchTrack( tracks[state!.active] = await SpotubeTrack.fetchFromTrack(
state!.activeTrack, state!.activeTrack,
preferences, preferences,
); );

View File

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart'; import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/models/generated_secrets.dart'; import 'package:spotube/models/generated_secrets.dart';
import 'package:spotube/utils/persisted_change_notifier.dart'; import 'package:spotube/utils/persisted_change_notifier.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
@ -25,12 +24,10 @@ enum AudioQuality {
class UserPreferences extends PersistedChangeNotifier { class UserPreferences extends PersistedChangeNotifier {
ThemeMode themeMode; ThemeMode themeMode;
String ytSearchFormat;
String recommendationMarket; String recommendationMarket;
bool saveTrackLyrics; bool saveTrackLyrics;
String geniusAccessToken; String geniusAccessToken;
bool checkUpdate; bool checkUpdate;
SpotubeTrackMatchAlgorithm trackMatchAlgorithm;
AudioQuality audioQuality; AudioQuality audioQuality;
MaterialColor accentColorScheme; MaterialColor accentColorScheme;
@ -48,14 +45,12 @@ class UserPreferences extends PersistedChangeNotifier {
required this.geniusAccessToken, required this.geniusAccessToken,
required this.recommendationMarket, required this.recommendationMarket,
required this.themeMode, required this.themeMode,
required this.ytSearchFormat,
required this.layoutMode, required this.layoutMode,
required this.predownload, required this.predownload,
this.saveTrackLyrics = false, this.saveTrackLyrics = false,
this.accentColorScheme = Colors.green, this.accentColorScheme = Colors.green,
this.backgroundColorScheme = Colors.grey, this.backgroundColorScheme = Colors.grey,
this.checkUpdate = true, this.checkUpdate = true,
this.trackMatchAlgorithm = SpotubeTrackMatchAlgorithm.youtube,
this.audioQuality = AudioQuality.high, this.audioQuality = AudioQuality.high,
this.skipSponsorSegments = true, this.skipSponsorSegments = true,
this.downloadLocation = "", this.downloadLocation = "",
@ -100,12 +95,6 @@ class UserPreferences extends PersistedChangeNotifier {
updatePersistence(); updatePersistence();
} }
void setYtSearchFormat(String format) {
ytSearchFormat = format;
notifyListeners();
updatePersistence();
}
void setAccentColorScheme(MaterialColor color) { void setAccentColorScheme(MaterialColor color) {
accentColorScheme = color; accentColorScheme = color;
notifyListeners(); notifyListeners();
@ -124,12 +113,6 @@ class UserPreferences extends PersistedChangeNotifier {
updatePersistence(); updatePersistence();
} }
void setTrackMatchAlgorithm(SpotubeTrackMatchAlgorithm algorithm) {
trackMatchAlgorithm = algorithm;
notifyListeners();
updatePersistence();
}
void setAudioQuality(AudioQuality quality) { void setAudioQuality(AudioQuality quality) {
audioQuality = quality; audioQuality = quality;
notifyListeners(); notifyListeners();
@ -181,7 +164,6 @@ class UserPreferences extends PersistedChangeNotifier {
geniusAccessToken = map["geniusAccessToken"] ?? geniusAccessToken = map["geniusAccessToken"] ??
PrimitiveUtils.getRandomElement(lyricsSecrets); PrimitiveUtils.getRandomElement(lyricsSecrets);
ytSearchFormat = map["ytSearchFormat"] ?? ytSearchFormat;
themeMode = ThemeMode.values[map["themeMode"] ?? 0]; themeMode = ThemeMode.values[map["themeMode"] ?? 0];
backgroundColorScheme = colorsMap.values backgroundColorScheme = colorsMap.values
.firstWhereOrNull((e) => e.value == map["backgroundColorScheme"]) ?? .firstWhereOrNull((e) => e.value == map["backgroundColorScheme"]) ??
@ -189,9 +171,6 @@ class UserPreferences extends PersistedChangeNotifier {
accentColorScheme = colorsMap.values accentColorScheme = colorsMap.values
.firstWhereOrNull((e) => e.value == map["accentColorScheme"]) ?? .firstWhereOrNull((e) => e.value == map["accentColorScheme"]) ??
accentColorScheme; accentColorScheme;
trackMatchAlgorithm = map["trackMatchAlgorithm"] != null
? SpotubeTrackMatchAlgorithm.values[map["trackMatchAlgorithm"]]
: trackMatchAlgorithm;
audioQuality = map["audioQuality"] != null audioQuality = map["audioQuality"] != null
? AudioQuality.values[map["audioQuality"]] ? AudioQuality.values[map["audioQuality"]]
: audioQuality; : audioQuality;
@ -213,12 +192,10 @@ class UserPreferences extends PersistedChangeNotifier {
"saveTrackLyrics": saveTrackLyrics, "saveTrackLyrics": saveTrackLyrics,
"recommendationMarket": recommendationMarket, "recommendationMarket": recommendationMarket,
"geniusAccessToken": geniusAccessToken, "geniusAccessToken": geniusAccessToken,
"ytSearchFormat": ytSearchFormat,
"themeMode": themeMode.index, "themeMode": themeMode.index,
"backgroundColorScheme": backgroundColorScheme.value, "backgroundColorScheme": backgroundColorScheme.value,
"accentColorScheme": accentColorScheme.value, "accentColorScheme": accentColorScheme.value,
"checkUpdate": checkUpdate, "checkUpdate": checkUpdate,
"trackMatchAlgorithm": trackMatchAlgorithm.index,
"audioQuality": audioQuality.index, "audioQuality": audioQuality.index,
"skipSponsorSegments": skipSponsorSegments, "skipSponsorSegments": skipSponsorSegments,
"downloadLocation": downloadLocation, "downloadLocation": downloadLocation,
@ -234,7 +211,6 @@ final userPreferencesProvider = ChangeNotifierProvider(
geniusAccessToken: "", geniusAccessToken: "",
recommendationMarket: 'US', recommendationMarket: 'US',
themeMode: ThemeMode.system, themeMode: ThemeMode.system,
ytSearchFormat: "\$MAIN_ARTIST - \$TITLE \$FEATURED_ARTISTS",
layoutMode: kIsMobile ? LayoutMode.compact : LayoutMode.adaptive, layoutMode: kIsMobile ? LayoutMode.compact : LayoutMode.adaptive,
predownload: kIsMobile, predownload: kIsMobile,
), ),