activate log level in release with env var

Check if the track already exists in the disk while download button is pressed
This commit is contained in:
Kingkor Roy Tirtho 2022-04-04 19:55:17 +06:00
parent 6111e8c291
commit 0036df6e12
22 changed files with 121 additions and 57 deletions

View File

@ -24,7 +24,7 @@ class _ArtistAlbumViewState extends ConsumerState<ArtistAlbumView> {
final PagingController<int, Album> _pagingController =
PagingController<int, Album>(firstPageKey: 0);
final logger = createLogger(ArtistAlbumView);
final logger = getLogger(ArtistAlbumView);
@override
void initState() {

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:marquee/marquee.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Shared/SpotubeWidgets.dart';
import 'package:spotube/components/Shared/SpotubeMarqueeText.dart';
class ArtistCard extends StatelessWidget {
final Artist artist;

View File

@ -21,7 +21,7 @@ import 'package:spotube/provider/SpotifyDI.dart';
class ArtistProfile extends HookConsumerWidget {
final String artistId;
final logger = createLogger(ArtistProfile);
final logger = getLogger(ArtistProfile);
ArtistProfile(this.artistId, {Key? key}) : super(key: key);
@override

View File

@ -17,7 +17,7 @@ class CategoryCard extends HookWidget {
this.playlists,
}) : super(key: key);
final logger = createLogger(CategoryCard);
final logger = getLogger(CategoryCard);
@override
Widget build(BuildContext context) {

View File

@ -42,7 +42,7 @@ List<String> spotifyScopes = [
class Home extends HookConsumerWidget {
Home({Key? key}) : super(key: key);
final logger = createLogger(Home);
final logger = getLogger(Home);
@override
Widget build(BuildContext context, ref) {

View File

@ -16,7 +16,7 @@ class UserArtists extends ConsumerStatefulWidget {
class _UserArtistsState extends ConsumerState<UserArtists> {
final PagingController<String, Artist> _pagingController =
PagingController(firstPageKey: "");
final logger = createLogger(UserArtists);
final logger = getLogger(UserArtists);
@override
void initState() {

View File

@ -14,7 +14,7 @@ import 'package:spotube/provider/UserPreferences.dart';
class Login extends HookConsumerWidget {
Login({Key? key}) : super(key: key);
final log = createLogger(Login);
final log = getLogger(Login);
@override
Widget build(BuildContext context, ref) {

View File

@ -19,7 +19,7 @@ import 'package:flutter/material.dart';
class Player extends HookConsumerWidget {
Player({Key? key}) : super(key: key);
final logger = createLogger(Player);
final logger = getLogger(Player);
@override
Widget build(BuildContext context, ref) {
Playback playback = ref.watch(playbackProvider);

View File

@ -15,7 +15,7 @@ class PlayerActions extends HookConsumerWidget {
this.mainAxisAlignment = MainAxisAlignment.center,
Key? key,
}) : super(key: key);
final logger = createLogger(PlayerActions);
final logger = getLogger(PlayerActions);
@override
Widget build(BuildContext context, ref) {

View File

@ -14,7 +14,7 @@ class PlayerControls extends HookConsumerWidget {
Key? key,
}) : super(key: key);
final logger = createLogger(PlayerControls);
final logger = getLogger(PlayerControls);
@override
Widget build(BuildContext context, ref) {
@ -47,7 +47,9 @@ class PlayerControls extends HookConsumerWidget {
child: Column(
children: [
StreamBuilder<Duration>(
stream: player.positionStream,
stream: player.positionStream.isBroadcast
? player.positionStream
: player.positionStream.asBroadcastStream(),
builder: (context, snapshot) {
final totalMinutes =
zeroPadNumStr(duration.inMinutes.remainder(60));

View File

@ -12,7 +12,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/provider/SpotifyDI.dart';
class PlaylistView extends HookConsumerWidget {
final logger = createLogger(PlaylistView);
final logger = getLogger(PlaylistView);
final PlaylistSimple playlist;
PlaylistView(this.playlist, {Key? key}) : super(key: key);

View File

@ -17,10 +17,10 @@ class DownloadTrackButton extends HookWidget {
@override
Widget build(BuildContext context) {
var status = useState<TrackStatus>(TrackStatus.idle);
final status = useState<TrackStatus>(TrackStatus.idle);
YoutubeExplode yt = useMemoized(() => YoutubeExplode());
var _downloadTrack = useCallback(() async {
final _downloadTrack = useCallback(() async {
if (track == null) return;
if ((Platform.isAndroid || Platform.isIOS) &&
!await Permission.storage.isGranted &&
@ -38,6 +38,43 @@ class DownloadTrackButton extends HookWidget {
StreamManifest manifest =
await yt.videos.streamsClient.getManifest(track?.href);
String downloadFolder = path.join(
Platform.isAndroid
? "/storage/emulated/0/Download"
: (await path_provider.getDownloadsDirectory())!.path,
"Spotube");
String fileName =
"${track?.name} - ${artistsToString<Artist>(track?.artists ?? [])}.mp3";
File outputFile = File(path.join(downloadFolder, fileName));
if (await outputFile.exists()) {
final shouldReplace = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Track Already Exists"),
content: const Text(
"Do you want to replace the already downloaded track?"),
actions: [
TextButton(
child: const Text("No"),
onPressed: () {
Navigator.pop(context, false);
},
),
TextButton(
child: const Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
)
],
);
},
);
if (shouldReplace != true) return;
}
final audioStream = yt.videos.streamsClient
.get(
manifest.audioOnly
@ -65,16 +102,7 @@ class DownloadTrackButton extends HookWidget {
},
);
String downloadFolder = path.join(
Platform.isAndroid
? "/storage/emulated/0/Download"
: (await path_provider.getDownloadsDirectory())!.path,
"Spotube");
String fileName =
"${track?.name} - ${artistsToString<Artist>(track?.artists ?? [])}.mp3";
File outputFile = File(path.join(downloadFolder, fileName));
if (!outputFile.existsSync()) {
outputFile.createSync(recursive: true);
if (!outputFile.existsSync()) outputFile.createSync(recursive: true);
IOSink outputFileStream = outputFile.openWrite();
await audioStream.pipe(outputFileStream);
await outputFileStream.flush();
@ -92,7 +120,6 @@ class DownloadTrackButton extends HookWidget {
}
return statusCb.cancel();
});
}
}, [track, status, yt]);
useEffect(() {

View File

@ -1,6 +1,6 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:spotube/components/Shared/SpotubeWidgets.dart';
import 'package:spotube/components/Shared/SpotubeMarqueeText.dart';
class PlaybuttonCard extends StatelessWidget {
final void Function()? onTap;

View File

@ -6,7 +6,7 @@ import 'package:spotube/helpers/get-random-element.dart';
import 'package:spotube/models/Logger.dart';
import 'package:spotube/models/generated_secrets.dart';
final logger = createLogger("GetLyrics");
final logger = getLogger("GetLyrics");
String getTitle(String title, String artist) {
return "$title $artist"

View File

@ -7,7 +7,7 @@ import 'package:spotube/models/Logger.dart';
import 'package:spotube/provider/Auth.dart';
const redirectUri = "http://localhost:4304/auth/spotify/callback";
final logger = createLogger("OAuthLogin");
final logger = getLogger("OAuthLogin");
Future<void> oauthLogin(Auth auth,
{required String clientId, required String clientSecret}) async {

View File

@ -3,7 +3,7 @@ import 'dart:io';
import 'package:spotube/models/Logger.dart';
import 'package:url_launcher/url_launcher.dart';
final logger = createLogger("ServerIPC");
final logger = getLogger("ServerIPC");
Future<String?> connectIpc(String authUri, String redirectUri) async {
try {

View File

@ -1,7 +1,7 @@
import 'package:spotube/models/Logger.dart';
import 'package:spotube/provider/Playback.dart';
final logger = createLogger("PlaybackHook");
final logger = getLogger("PlaybackHook");
Future<void> Function() useNextTrack(Playback playback) {
return () async {

View File

@ -39,7 +39,7 @@ void main() async {
class MyApp extends HookConsumerWidget {
final GoRouter _router = createGoRouter();
final logger = createLogger(MyApp);
final logger = getLogger(MyApp);
MyApp({Key? key}) : super(key: key);
@override

View File

@ -4,12 +4,16 @@ import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
_SpotubeLogger createLogger<T>(T owner) =>
_SpotubeLogger(owner is String ? owner : owner.toString());
final _loggerFactory = _SpotubeLogger();
_SpotubeLogger getLogger<T>(T owner) {
_loggerFactory.owner = owner is String ? owner : owner.toString();
return _loggerFactory;
}
class _SpotubeLogger extends Logger {
String owner;
_SpotubeLogger(this.owner);
String? owner;
_SpotubeLogger([this.owner]) : super(filter: _SpotubeLogFilter());
@override
void log(Level level, message, [error, StackTrace? stackTrace]) {
@ -23,3 +27,16 @@ class _SpotubeLogger extends Logger {
super.log(level, "[$owner] $message", error, stackTrace);
}
}
class _SpotubeLogFilter extends DevelopmentFilter {
@override
bool shouldLog(LogEvent event) {
final env = Platform.environment;
if ((env["DEBUG"] == "true" && event.level == Level.debug) ||
(env["VERBOSE"] == "true" && event.level == Level.verbose) ||
(env["ERROR"] == "true" && event.level == Level.error)) {
return true;
}
return super.shouldLog(event);
}
}

View File

@ -48,7 +48,8 @@ class CurrentPlaylist {
}
class Playback extends ChangeNotifier {
final _logger = createLogger(Playback);
AudioSource? _currentAudioSource;
final _logger = getLogger(Playback);
CurrentPlaylist? _currentPlaylist;
Track? _currentTrack;
@ -67,6 +68,7 @@ class Playback extends ChangeNotifier {
StreamSubscription<Duration?>? _durationStreamListener;
StreamSubscription<ProcessingState>? _processingStateStreamListener;
StreamSubscription<AudioInterruptionEvent>? _audioInterruptionEventListener;
StreamSubscription<Duration>? _positionStreamListener;
AudioPlayer player;
YoutubeExplode youtube;
@ -97,15 +99,17 @@ class Playback extends ChangeNotifier {
if (player.playing) await player.pause();
await player.play();
}
_duration = duration;
_callAllDurationListeners(duration);
// for avoiding unnecessary re-renders in other components that
// doesn't need duration
_callAllDurationListeners(duration);
}
});
_processingStateStreamListener =
player.processingStateStream.listen((event) async {
_logger.v("[Processing State Change] $event");
try {
if (event != ProcessingState.completed) return;
if (_currentTrack?.id != null) {
@ -122,6 +126,11 @@ class Playback extends ChangeNotifier {
}
});
_positionStreamListener = (player.positionStream.isBroadcast
? player.positionStream
: player.positionStream.asBroadcastStream())
.listen((position) async {});
AudioSession.instance.then((session) async {
_audioSession = session;
await session.configure(const AudioSessionConfiguration.music());
@ -159,16 +168,19 @@ class Playback extends ChangeNotifier {
}
set setCurrentTrack(Track track) {
_logger.v("[Setting Current Track] ${track.name} - ${track.id}");
_currentTrack = track;
notifyListeners();
}
set setCurrentPlaylist(CurrentPlaylist playlist) {
_logger.v("[Current Playlist Changed] ${playlist.name} - ${playlist.id}");
_currentPlaylist = playlist;
notifyListeners();
}
void reset() {
_logger.v("Playback Reset");
_isPlaying = false;
_duration = null;
_callAllDurationListeners(null);
@ -200,11 +212,13 @@ class Playback extends ChangeNotifier {
_durationStreamListener?.cancel();
_playingStreamListener?.cancel();
_audioInterruptionEventListener?.cancel();
_positionStreamListener?.cancel();
_audioSession?.setActive(false);
super.dispose();
}
void movePlaylistPositionBy(int pos) {
_logger.v("[Playlist Position Move] $pos");
if (_currentTrack != null && _currentPlaylist != null) {
int index = _currentPlaylist!.trackIds.indexOf(_currentTrack!.id!) + pos;
@ -228,6 +242,7 @@ class Playback extends ChangeNotifier {
}
Future<void> startPlaying([Track? track]) async {
_logger.v("[Track Playing] ${track?.name} - ${track?.id}");
try {
// the track is already playing so no need to change that
if (track != null && track.id == _currentTrack?.id) return;
@ -242,9 +257,10 @@ class Playback extends ChangeNotifier {
artUri: Uri.parse(imageToUrlString(track.album?.images)),
);
if (parsedUri != null && parsedUri.hasAbsolutePath) {
_currentAudioSource = AudioSource.uri(parsedUri, tag: tag);
await player
.setAudioSource(
AudioSource.uri(parsedUri, tag: tag),
_currentAudioSource!,
preload: true,
)
.then((value) async {
@ -256,9 +272,11 @@ class Playback extends ChangeNotifier {
}
final ytTrack = await toYoutubeTrack(youtube, track);
if (setTrackUriById(track.id!, ytTrack.uri!)) {
_currentAudioSource =
AudioSource.uri(Uri.parse(ytTrack.uri!), tag: tag);
await player
.setAudioSource(
AudioSource.uri(Uri.parse(ytTrack.uri!), tag: tag),
_currentAudioSource!,
preload: true,
)
.then((value) {

View File

@ -23,7 +23,7 @@ class UserPreferences extends ChangeNotifier {
onInit();
}
final logger = createLogger(UserPreferences);
final logger = getLogger(UserPreferences);
Future<HotKey?> _getHotKeyFromLocalStorage(
SharedPreferences preferences, String key) async {