diff --git a/lib/components/Settings.dart b/lib/components/Settings.dart index d1187a37..5f7609b3 100644 --- a/lib/components/Settings.dart +++ b/lib/components/Settings.dart @@ -20,11 +20,17 @@ class Settings extends HookConsumerWidget { Widget build(BuildContext context, ref) { final UserPreferences preferences = ref.watch(userPreferencesProvider); final Auth auth = ref.watch(authProvider); - var geniusAccessToken = useState(null); - TextEditingController textEditingController = useTextEditingController(); + final geniusAccessToken = useState(null); + TextEditingController geniusTokenController = useTextEditingController(); + final ytSearchFormatController = + useTextEditingController(text: preferences.ytSearchFormat); - textEditingController.addListener(() { - geniusAccessToken.value = textEditingController.value.text; + geniusTokenController.addListener(() { + geniusAccessToken.value = geniusTokenController.value.text; + }); + + ytSearchFormatController.addListener(() { + preferences.setYtSearchFormat(ytSearchFormatController.value.text); }); return SafeArea( @@ -52,7 +58,7 @@ class Settings extends HookConsumerWidget { Expanded( flex: 1, child: TextField( - controller: textEditingController, + controller: geniusTokenController, decoration: InputDecoration( hintText: preferences.geniusAccessToken, ), @@ -76,7 +82,7 @@ class Settings extends HookConsumerWidget { } geniusAccessToken.value = null; - textEditingController.text = ""; + geniusTokenController.text = ""; } : null, child: const Text("Save"), @@ -174,6 +180,23 @@ class Settings extends HookConsumerWidget { ], ), const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Expanded( + flex: 2, + child: Text( + "Format of the YouTube Search term (Case sensitive)"), + ), + Expanded( + flex: 1, + child: TextField( + controller: ytSearchFormatController, + ), + ), + ], + ), + const SizedBox(height: 10), if (auth.isAnonymous) Wrap( spacing: 20, diff --git a/lib/helpers/search-youtube.dart b/lib/helpers/search-youtube.dart index 24fa2e1d..73eea476 100644 --- a/lib/helpers/search-youtube.dart +++ b/lib/helpers/search-youtube.dart @@ -1,11 +1,24 @@ import 'dart:io'; import 'package:spotify/spotify.dart'; +import 'package:spotube/helpers/getLyrics.dart'; +import 'package:spotube/models/Logger.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; -Future toYoutubeTrack(YoutubeExplode youtube, Track track) async { - var artistsName = track.artists?.map((ar) => ar.name).toList() ?? []; - String queryString = - "${artistsName.first} - ${track.name}${artistsName.length > 1 ? " feat. ${artistsName.sublist(1).join(" ")}" : ""}"; +final logger = getLogger("toYoutubeTrack"); +Future toYoutubeTrack( + YoutubeExplode youtube, Track track, String format) async { + final artistsName = track.artists?.map((ar) => ar.name).toList() ?? []; + logger.v("[Track Search Artists] $artistsName"); + final mainArtist = artistsName.first ?? ""; + final featuredArtists = + artistsName.length > 1 ? "feat. " + artistsName.sublist(1).join(" ") : ""; + final title = getTitle(track.name!, "").trim(); + logger.v("[Track Search Title] $title"); + final queryString = format + .replaceAll("\$MAIN_ARTIST", mainArtist) + .replaceAll("\$TITLE", title) + .replaceAll("\$FEATURED_ARTISTS", featuredArtists); + logger.v("[Youtube Search Term] $queryString"); SearchList videos = await youtube.search.getVideos(queryString); @@ -33,5 +46,6 @@ Future toYoutubeTrack(YoutubeExplode youtube, Track track) async { .url .toString(); track.href = ytVideo.url; + logger.v("[YouTube Matched Track] ${ytVideo.title} - ${track.href}"); return track; } diff --git a/lib/models/LocalStorageKeys.dart b/lib/models/LocalStorageKeys.dart index 2de527e6..0fedb95a 100644 --- a/lib/models/LocalStorageKeys.dart +++ b/lib/models/LocalStorageKeys.dart @@ -1,6 +1,8 @@ abstract class LocalStorageKeys { static String saveTrackLyrics = 'save_track_lyrics'; static String recommendationMarket = 'recommendation_market'; + static String ytSearchFormate = 'youtube_search_format'; + static String clientId = 'client_id'; static String clientSecret = 'client_secret'; static String accessToken = 'access_token'; diff --git a/lib/provider/Playback.dart b/lib/provider/Playback.dart index cfcbe0fd..6da9b002 100644 --- a/lib/provider/Playback.dart +++ b/lib/provider/Playback.dart @@ -11,6 +11,7 @@ import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/helpers/search-youtube.dart'; import 'package:spotube/models/Logger.dart'; import 'package:spotube/provider/AudioPlayer.dart'; +import 'package:spotube/provider/UserPreferences.dart'; import 'package:spotube/provider/YouTube.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; @@ -48,6 +49,7 @@ class CurrentPlaylist { } class Playback extends ChangeNotifier { + ChangeNotifierProviderRef ref; AudioSource? _currentAudioSource; final _logger = getLogger(Playback); CurrentPlaylist? _currentPlaylist; @@ -76,6 +78,7 @@ class Playback extends ChangeNotifier { Playback({ required this.player, required this.youtube, + required this.ref, CurrentPlaylist? currentPlaylist, Track? currentTrack, }) : _currentPlaylist = currentPlaylist, @@ -270,7 +273,12 @@ class Playback extends ChangeNotifier { notifyListeners(); }); } - final ytTrack = await toYoutubeTrack(youtube, track); + final preferences = ref.read(userPreferencesProvider); + final ytTrack = await toYoutubeTrack( + youtube, + track, + preferences.ytSearchFormat, + ); if (setTrackUriById(track.id!, ytTrack.uri!)) { _currentAudioSource = AudioSource.uri(Uri.parse(ytTrack.uri!), tag: tag); @@ -294,5 +302,9 @@ class Playback extends ChangeNotifier { final playbackProvider = ChangeNotifierProvider((ref) { final player = ref.watch(audioPlayerProvider); final youtube = ref.watch(youtubeProvider); - return Playback(player: player, youtube: youtube); + return Playback( + player: player, + youtube: youtube, + ref: ref, + ); }); diff --git a/lib/provider/UserPreferences.dart b/lib/provider/UserPreferences.dart index 938446ff..d9e67a17 100644 --- a/lib/provider/UserPreferences.dart +++ b/lib/provider/UserPreferences.dart @@ -11,6 +11,7 @@ import 'package:spotube/models/generated_secrets.dart'; class UserPreferences extends ChangeNotifier { ThemeMode themeMode; + String ytSearchFormat; String recommendationMarket; bool saveTrackLyrics; String geniusAccessToken; @@ -22,6 +23,7 @@ class UserPreferences extends ChangeNotifier { required this.geniusAccessToken, required this.recommendationMarket, required this.themeMode, + required this.ytSearchFormat, this.saveTrackLyrics = false, this.nextTrackHotKey, this.prevTrackHotKey, @@ -149,6 +151,12 @@ class UserPreferences extends ChangeNotifier { ); notifyListeners(); } + + void setYtSearchFormat(String format) { + ytSearchFormat = format; + localStorage?.setString(LocalStorageKeys.ytSearchFormate, format); + notifyListeners(); + } } final userPreferencesProvider = ChangeNotifierProvider( @@ -156,5 +164,6 @@ final userPreferencesProvider = ChangeNotifierProvider( geniusAccessToken: "", recommendationMarket: 'US', themeMode: ThemeMode.system, + ytSearchFormat: "\$MAIN_ARTIST - \$TITLE \$FEATURED_ARTISTS", ), );