Download lyrics with track support

nightly build links in README
This commit is contained in:
Kingkor Roy Tirtho 2022-04-04 22:54:00 +06:00
parent f7510d7eae
commit d62f3ce6a1
5 changed files with 68 additions and 8 deletions

View File

@ -102,8 +102,8 @@ $ flatpak install flathub com.github.KRTirtho.Spotube
## Mac OS
Download the [Mac OS Disk Image (.dmg) file](https://github.com/KRTirtho/spotube/releases/latest/download/Spotube-macos-x86_64.dmg) from the release & follow along the setup wizard
**I'll/try to upload the package binaries to linux debian/arch/ubuntu/snap/flatpack/redhat/chocolatey/homebrew stores or software centers or repositories**
## Nightly Builds
Get the latest nightly builds of Spotube [here](https://nightly.link/KRTirtho/spotube/workflows/flutter-build/build)
## Optional Configurations
<details>

View File

@ -163,6 +163,19 @@ class Settings extends HookConsumerWidget {
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Download lyrics along with the Track"),
Switch.adaptive(
value: preferences.saveTrackLyrics,
onChanged: (state) {
preferences.setSaveTrackLyrics(state);
},
),
],
),
const SizedBox(height: 10),
if (auth.isAnonymous)
Wrap(
spacing: 20,

View File

@ -2,8 +2,12 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/helpers/artist-to-string.dart';
import 'package:spotube/helpers/getLyrics.dart';
import 'package:spotube/provider/Playback.dart';
import 'package:spotube/provider/UserPreferences.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:path/path.dart' as path;
@ -11,12 +15,14 @@ import 'package:permission_handler/permission_handler.dart';
enum TrackStatus { downloading, idle, done }
class DownloadTrackButton extends HookWidget {
class DownloadTrackButton extends HookConsumerWidget {
final Track? track;
const DownloadTrackButton({Key? key, this.track}) : super(key: key);
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, ref) {
final UserPreferences preferences = ref.watch(userPreferencesProvider);
final Playback playback = ref.watch(playbackProvider);
final status = useState<TrackStatus>(TrackStatus.idle);
YoutubeExplode yt = useMemoized(() => YoutubeExplode());
@ -44,8 +50,10 @@ class DownloadTrackButton extends HookWidget {
: (await path_provider.getDownloadsDirectory())!.path,
"Spotube");
String fileName =
"${track?.name} - ${artistsToString<Artist>(track?.artists ?? [])}.mp3";
File outputFile = File(path.join(downloadFolder, fileName));
"${track?.name} - ${artistsToString<Artist>(track?.artists ?? [])}";
File outputFile = File(path.join(downloadFolder, "$fileName.mp3"));
File outputLyricsFile =
File(path.join(downloadFolder, "$fileName-lyrics.txt"));
if (await outputFile.exists()) {
final shouldReplace = await showDialog<bool>(
@ -102,7 +110,26 @@ class DownloadTrackButton extends HookWidget {
},
);
if (!outputFile.existsSync()) outputFile.createSync(recursive: true);
if (!await outputFile.exists()) await outputFile.create(recursive: true);
if (preferences.saveTrackLyrics && playback.currentTrack != null) {
if (!await outputLyricsFile.exists()) {
await outputLyricsFile.create(recursive: true);
}
final lyrics = await getLyrics(
playback.currentTrack!.name!,
artistsToString<Artist>(playback.currentTrack!.artists ?? []),
apiKey: preferences.geniusAccessToken,
optimizeQuery: true,
);
if (lyrics != null) {
await outputLyricsFile.writeAsString(
"$lyrics\n\nPowered by genius.com",
mode: FileMode.writeOnly,
);
}
}
IOSink outputFileStream = outputFile.openWrite();
await audioStream.pipe(outputFileStream);
await outputFileStream.flush();
@ -120,7 +147,13 @@ class DownloadTrackButton extends HookWidget {
}
return statusCb.cancel();
});
}, [track, status, yt]);
}, [
track,
status,
yt,
preferences.saveTrackLyrics,
playback.currentTrack,
]);
useEffect(() {
return () => yt.close();

View File

@ -1,4 +1,5 @@
abstract class LocalStorageKeys {
static String saveTrackLyrics = 'save_track_lyrics';
static String recommendationMarket = 'recommendation_market';
static String clientId = 'client_id';
static String clientSecret = 'client_secret';

View File

@ -11,6 +11,7 @@ import 'package:spotube/models/generated_secrets.dart';
class UserPreferences extends ChangeNotifier {
String recommendationMarket;
bool saveTrackLyrics;
String geniusAccessToken;
HotKey? nextTrackHotKey;
HotKey? prevTrackHotKey;
@ -18,6 +19,7 @@ class UserPreferences extends ChangeNotifier {
UserPreferences({
required this.geniusAccessToken,
required this.recommendationMarket,
this.saveTrackLyrics = false,
this.nextTrackHotKey,
this.prevTrackHotKey,
this.playPauseHotKey,
@ -46,6 +48,9 @@ class UserPreferences extends ChangeNotifier {
String? accessToken =
localStorage.getString(LocalStorageKeys.geniusAccessToken);
saveTrackLyrics =
localStorage.getBool(LocalStorageKeys.saveTrackLyrics) ?? false;
recommendationMarket =
localStorage.getString(LocalStorageKeys.recommendationMarket) ?? 'US';
geniusAccessToken = accessToken != null && accessToken.isNotEmpty
@ -84,6 +89,14 @@ class UserPreferences extends ChangeNotifier {
}
}
void setSaveTrackLyrics(bool shouldSave) {
saveTrackLyrics = shouldSave;
SharedPreferences.getInstance().then((value) {
value.setBool(LocalStorageKeys.saveTrackLyrics, shouldSave);
notifyListeners();
});
}
void setRecommendationMarket(String country) {
recommendationMarket = country;
SharedPreferences.getInstance().then((value) {