mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
Download lyrics with track support
nightly build links in README
This commit is contained in:
parent
f7510d7eae
commit
d62f3ce6a1
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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';
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user