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,
bottom: 10,
end: 5,
child: Row(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (!isPlaying) addToQueueButton,
if (platform != TargetPlatform.linux)
const SizedBox(width: 5),
const SizedBox(height: 5),
playButton,
],
),

View File

@ -1,7 +1,9 @@
import 'dart:async';
import 'package:catcher/catcher.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/video.dart';
import 'package:spotube/extensions/album_simple.dart';
@ -65,7 +67,7 @@ class SpotubeTrack extends Track {
uri = track.uri;
}
static Future<SpotubeTrack> fromFetchTrack(
static Future<SpotubeTrack> fetchFromTrack(
Track track, UserPreferences preferences) async {
final artists = (track.artists ?? [])
.map((ar) => ar.name)
@ -79,16 +81,17 @@ class SpotubeTrack extends Track {
onlyCleanArtist: true,
).trim();
final cachedTracks = await pb.collection(BackendTrack.collection).getList(
filter: "spotify_id = '${track.id}'",
sort: "-votes",
page: 0,
perPage: 1,
);
final cachedTracks = await Future<RecordModel?>.value(
pb
.collection(BackendTrack.collection)
.getFirstListItem("spotify_id = '${track.id}'"),
).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
final cachedTrack = cachedTracks.items.isNotEmpty
? BackendTrack.fromRecord(cachedTracks.items.first)
: null;
final cachedTrack =
cachedTracks != null ? BackendTrack.fromRecord(cachedTracks) : null;
Video ytVideo;
List<Video> siblings = [];
@ -127,13 +130,17 @@ class SpotubeTrack extends Track {
final ytUri = chosenStreamInfo.url.toString();
if (cachedTrack == null) {
await pb.collection(BackendTrack.collection).create(
body: BackendTrack(
spotifyId: track.id!,
youtubeId: ytVideo.id.value,
votes: 0,
).toJson(),
);
await Future<RecordModel?>.value(
pb.collection(BackendTrack.collection).create(
body: BackendTrack(
spotifyId: track.id!,
youtubeId: ytVideo.id.value,
votes: 0,
).toJson(),
)).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
}
if (preferences.predownload &&
@ -205,32 +212,38 @@ class SpotubeTrack extends Track {
final ytUri = chosenStreamInfo.url.toString();
final cachedTracks = await pb.collection(BackendTrack.collection).getList(
filter: "spotify_id = '$id' && youtube_id = '${video.id.value}'",
sort: "-votes",
page: 0,
perPage: 1,
);
final cachedTracks = await Future<RecordModel?>.value(
pb.collection(BackendTrack.collection).getFirstListItem(
"spotify_id = '$id' && youtube_id = '${video.id.value}'"),
).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
final cachedTrack = cachedTracks.items.isNotEmpty
? BackendTrack.fromRecord(cachedTracks.items.first)
: null;
final cachedTrack =
cachedTracks != null ? BackendTrack.fromRecord(cachedTracks) : null;
if (cachedTrack == null) {
await pb.collection(BackendTrack.collection).create(
body: BackendTrack(
spotifyId: id!,
youtubeId: video.id.value,
votes: 1,
).toJson(),
);
await Future<RecordModel?>.value(
pb.collection(BackendTrack.collection).create(
body: BackendTrack(
spotifyId: id!,
youtubeId: video.id.value,
votes: 1,
).toJson(),
)).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
} else {
await pb.collection(BackendTrack.collection).update(
await Future<RecordModel?>.value(
pb.collection(BackendTrack.collection).update(
cachedTrack.id,
body: {
"votes": cachedTrack.votes + 1,
},
);
body: {"votes": cachedTrack.votes + 1},
)).catchError((e, stack) {
Catcher.reportCheckedError(e, stack);
return null;
});
}
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/shared/adaptive/adaptive_list_tile.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/collections/spotify_markets.dart';
import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/provider/auth_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
@ -41,10 +39,6 @@ class SettingsPage extends HookConsumerWidget {
preferences.setDownloadLocation(dirStr);
}, [preferences.downloadLocation]);
var ytSearchFormatController = useTextEditingController(
text: preferences.ytSearchFormat,
);
return SafeArea(
child: PlatformScaffold(
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(
" Downloads",
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
// _playback.mobileAudioService?.session?.setActive(true);
grabberQueue.add(() async {
final track = await SpotubeTrack.fromFetchTrack(
final track = await SpotubeTrack.fetchFromTrack(
baseTrack,
ref.read(userPreferencesProvider),
);

View File

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

View File

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