Skip to content

Commit

Permalink
fix: dropped flutter_downloader deps due to slow download speed and U…
Browse files Browse the repository at this point in the history
…serDownloads not showing for anonymous
  • Loading branch information
KRTirtho committed Aug 25, 2022
1 parent aba1ba9 commit 307a8e2
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 143 deletions.
60 changes: 30 additions & 30 deletions lib/components/Library/UserDownloads.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class UserDownloads extends HookConsumerWidget {
Widget build(BuildContext context, ref) {
final downloader = ref.watch(downloaderProvider);

final inQueue = downloader.inQueue.toList();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expand Down Expand Up @@ -43,39 +42,40 @@ class UserDownloads extends HookConsumerWidget {
],
),
),
ListView.builder(
itemCount: inQueue.length,
shrinkWrap: true,
itemBuilder: (context, index) {
final track = inQueue[index];
return ListTile(
title: Text(track.name!),
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: CachedNetworkImage(
height: 40,
width: 40,
imageUrl: TypeConversionUtils.image_X_UrlString(
track.album?.images,
Expanded(
child: ListView.builder(
itemCount: downloader.inQueue.length,
itemBuilder: (context, index) {
final track = downloader.inQueue.elementAt(index);
return ListTile(
title: Text(track.name!),
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: CachedNetworkImage(
height: 40,
width: 40,
imageUrl: TypeConversionUtils.image_X_UrlString(
track.album?.images,
),
),
),
),
),
trailing: const SizedBox(
width: 30,
height: 30,
child: CircularProgressIndicator.adaptive(),
),
horizontalTitleGap: 5,
subtitle: Text(
TypeConversionUtils.artists_X_String<Artist>(
track.artists ?? [],
trailing: const SizedBox(
width: 30,
height: 30,
child: CircularProgressIndicator.adaptive(),
),
),
);
},
horizontalTitleGap: 5,
subtitle: Text(
TypeConversionUtils.artists_X_String<Artist>(
track.artists ?? [],
),
),
);
},
),
),
],
);
Expand Down
17 changes: 6 additions & 11 deletions lib/components/Library/UserLibrary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import 'package:spotube/components/Library/UserArtists.dart';
import 'package:spotube/components/Library/UserDownloads.dart';
import 'package:spotube/components/Library/UserPlaylists.dart';
import 'package:spotube/components/Shared/AnonymousFallback.dart';
import 'package:spotube/provider/Auth.dart';

class UserLibrary extends ConsumerWidget {
const UserLibrary({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
final Auth auth = ref.watch(authProvider);

return Expanded(
child: DefaultTabController(
length: 4,
Expand All @@ -27,14 +24,12 @@ class UserLibrary extends ConsumerWidget {
Tab(text: "Downloads"),
],
),
body: auth.isLoggedIn
? TabBarView(children: [
const UserPlaylists(),
UserArtists(),
const UserAlbums(),
const UserDownloads(),
])
: const AnonymousFallback(),
body: TabBarView(children: [
const AnonymousFallback(child: UserPlaylists()),
AnonymousFallback(child: UserArtists()),
const AnonymousFallback(child: UserAlbums()),
const UserDownloads(),
]),
),
),
),
Expand Down
15 changes: 12 additions & 3 deletions lib/components/Shared/AnonymousFallback.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:spotube/provider/Auth.dart';

class AnonymousFallback extends StatelessWidget {
const AnonymousFallback({Key? key}) : super(key: key);
class AnonymousFallback extends ConsumerWidget {
final Widget? child;
const AnonymousFallback({
Key? key,
this.child,
}) : super(key: key);

@override
Widget build(BuildContext context) {
Widget build(BuildContext context, ref) {
final isLoggedIn = ref.watch(authProvider.select((s) => s.isLoggedIn));

if (isLoggedIn && child != null) return child!;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
Expand Down
12 changes: 0 additions & 12 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import 'dart:convert';

import 'package:audio_service/audio_service.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
Expand Down Expand Up @@ -48,11 +46,6 @@ void main() async {
}
appWindow.show();
});
} else if (kIsMobile) {
await FlutterDownloader.initialize(
debug: kDebugMode,
ignoreSsl: true,
);
}
MobileAudioService? audioServiceHandler;
runApp(
Expand Down Expand Up @@ -155,13 +148,8 @@ class _SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
super.initState();
SharedPreferences.getInstance().then(((value) => localStorage = value));
WidgetsBinding.instance.addObserver(this);
if (kIsMobile) FlutterDownloader.registerCallback(downloadCallback);
}

@pragma('vm:entry-point')
static void downloadCallback(
String id, DownloadTaskStatus status, int progress) {}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
Expand Down
141 changes: 62 additions & 79 deletions lib/provider/Downloader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:io';

import 'package:flutter/widgets.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:queue/queue.dart';
import 'package:path/path.dart' as path;
Expand All @@ -12,7 +11,6 @@ import 'package:spotube/models/SpotubeTrack.dart';
import 'package:spotube/provider/Playback.dart';
import 'package:spotube/provider/UserPreferences.dart';
import 'package:spotube/provider/YouTube.dart';
import 'package:spotube/utils/platform.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';

Queue queueInstance = Queue(delay: const Duration(seconds: 5));
Expand All @@ -38,101 +36,86 @@ class Downloader with ChangeNotifier {

final logger = getLogger(Downloader);

Playback get _playback => ref.read(playbackProvider);

void addToQueue(Track baseTrack) async {
if (inQueue.any((t) => t.id == baseTrack.id!)) return;
inQueue.add(baseTrack);
currentlyRunning++;
notifyListeners();
if (kIsMobile) {
grabberQueue.add(() async {
final track = await ref.read(playbackProvider).toSpotubeTrack(
baseTrack,
noSponsorBlock: true,
);

final filename = '${track.ytTrack.title}.mp3';

final url =
((await yt.videos.streamsClient.getManifest(track.ytTrack.url)))
.audioOnly
.where((audio) => audio.codec.mimeType == "audio/mp4")
.withHighestBitrate()
.url;
await FlutterDownloader.enqueue(
savedDir: downloadPath,
url: url.toString(),
fileName: filename,
openFileFromNotification: true,
showNotification: true,
// Using android Audio Focus to keep the app run in background
_playback.mobileAudioService?.session?.setActive(true);
grabberQueue.add(() async {
final track = await ref.read(playbackProvider).toSpotubeTrack(
baseTrack,
noSponsorBlock: true,
);
_queue.add(() async {
final cleanTitle = track.ytTrack.title.replaceAll(
RegExp(r'[/\\?%*:|"<>]'),
"",
);
});
} else {
grabberQueue.add(() async {
final track = await ref.read(playbackProvider).toSpotubeTrack(
baseTrack,
noSponsorBlock: true,
);
_queue.add(() async {
final filename = '${track.ytTrack.title}.mp3';
final file = File(path.join(downloadPath, filename));
try {
logger.v("[addToQueue] Download starting for ${file.path}");
if (file.existsSync() && await onFileExists?.call(track) != true) {
return;
}
file.createSync(recursive: true);
StreamManifest manifest =
await yt.videos.streamsClient.getManifest(track.ytTrack.url);
logger.v(
"[addToQueue] Getting download information for ${file.path}",
);
final audioStream = yt.videos.streamsClient
.get(
manifest.audioOnly
.where((audio) => audio.codec.mimeType == "audio/mp4")
.withHighestBitrate(),
)
.asBroadcastStream();
final filename = '$cleanTitle.mp3';
final file = File(path.join(downloadPath, filename));
try {
logger.v("[addToQueue] Download starting for ${file.path}");
if (file.existsSync() && await onFileExists?.call(track) != true) {
return;
}
file.createSync(recursive: true);
StreamManifest manifest =
await yt.videos.streamsClient.getManifest(track.ytTrack.url);
logger.v(
"[addToQueue] Getting download information for ${file.path}",
);
final audioStream = yt.videos.streamsClient
.get(
manifest.audioOnly
.where(
(audio) => audio.codec.mimeType == "audio/mp4",
)
.withHighestBitrate(),
)
.asBroadcastStream();

logger.v(
"[addToQueue] ${file.path} download started",
);
logger.v(
"[addToQueue] ${file.path} download started",
);

IOSink outputFileStream = file.openWrite();
await audioStream.pipe(outputFileStream);
await outputFileStream.flush();
logger.v(
"[addToQueue] Download of ${file.path} is done successfully",
);
} catch (e, stack) {
logger.e(
"[addToQueue] Failed download of ${file.path}",
e,
stack,
);
rethrow;
} finally {
currentlyRunning--;
inQueue.removeWhere((t) => t.id == track.id);
notifyListeners();
IOSink outputFileStream = file.openWrite();
await audioStream.pipe(outputFileStream);
await outputFileStream.flush();
logger.v(
"[addToQueue] Download of ${file.path} is done successfully",
);
} catch (e, stack) {
logger.e(
"[addToQueue] Failed download of ${file.path}",
e,
stack,
);
rethrow;
} finally {
currentlyRunning--;
inQueue.removeWhere((t) => t.id == track.id);
if (currentlyRunning == 0 && !_playback.isPlaying) {
_playback.mobileAudioService?.session?.setActive(false);
}
});
notifyListeners();
}
});
}
});
}

cancelAll() {
grabberQueue.cancel();
grabberQueue = Queue();
inQueue.clear();
currentlyRunning = 0;
if (kIsMobile) {
FlutterDownloader.cancelAll();
} else {
_queue.cancel();
queueInstance = Queue();
_queue = queueInstance;
}
_queue.cancel();
queueInstance = Queue();
_queue = queueInstance;
notifyListeners();
}
}
Expand Down
7 changes: 0 additions & 7 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -552,13 +552,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.9"
flutter_downloader:
dependency: "direct main"
description:
name: flutter_downloader
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
flutter_hooks:
dependency: "direct main"
description:
Expand Down
1 change: 0 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ dependencies:
file_picker: ^4.6.1
popover: ^0.2.6+3
queue: ^3.1.0+1
flutter_downloader: ^1.8.1
auto_size_text: ^3.0.0
badges: ^2.0.3

Expand Down

0 comments on commit 307a8e2

Please sign in to comment.