mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
feat: add download multi tracks support for mobile platform
This commit is contained in:
parent
9edcf537f8
commit
0476bf7cee
4
.fvm/fvm_config.json
Normal file
4
.fvm/fvm_config.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"flutterSdkVersion": "3.0.5",
|
||||||
|
"flavors": {}
|
||||||
|
}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -75,3 +75,4 @@ dist
|
|||||||
appimage-build
|
appimage-build
|
||||||
|
|
||||||
android/key.properties
|
android/key.properties
|
||||||
|
.fvm/flutter_sdk
|
@ -50,7 +50,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "oss.krtirtho.spotube"
|
applicationId "oss.krtirtho.spotube"
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 19
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<provider android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider" android:authorities="${applicationId}.flutter_downloader.provider" android:exported="false" android:grantUriPermissions="true">
|
||||||
|
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
|
||||||
|
</provider>
|
||||||
|
|
||||||
<service android:name="com.ryanheise.audioservice.AudioService" android:exported="false">
|
<service android:name="com.ryanheise.audioservice.AudioService" android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.media.browse.MediaBrowserService" />
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
@ -2,7 +2,9 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:audio_service/audio_service.dart';
|
import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
@ -26,8 +28,8 @@ void main() async {
|
|||||||
Hive.registerAdapter(CacheTrackAdapter());
|
Hive.registerAdapter(CacheTrackAdapter());
|
||||||
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
||||||
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
|
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
|
||||||
if (kIsDesktop) {
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
if (kIsDesktop) {
|
||||||
doWhenWindowReady(() async {
|
doWhenWindowReady(() async {
|
||||||
final localStorage = await SharedPreferences.getInstance();
|
final localStorage = await SharedPreferences.getInstance();
|
||||||
final rawSize = localStorage.getString(LocalStorageKeys.windowSizeInfo);
|
final rawSize = localStorage.getString(LocalStorageKeys.windowSizeInfo);
|
||||||
@ -44,6 +46,11 @@ void main() async {
|
|||||||
}
|
}
|
||||||
appWindow.show();
|
appWindow.show();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await FlutterDownloader.initialize(
|
||||||
|
debug: kDebugMode,
|
||||||
|
ignoreSsl: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
MobileAudioService? audioServiceHandler;
|
MobileAudioService? audioServiceHandler;
|
||||||
runApp(ProviderScope(
|
runApp(ProviderScope(
|
||||||
@ -102,8 +109,13 @@ class _SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
|
|||||||
super.initState();
|
super.initState();
|
||||||
SharedPreferences.getInstance().then(((value) => localStorage = value));
|
SharedPreferences.getInstance().then(((value) => localStorage = value));
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
FlutterDownloader.registerCallback(downloadCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@pragma('vm:entry-point')
|
||||||
|
static void downloadCallback(
|
||||||
|
String id, DownloadTaskStatus status, int progress) {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
@ -2,12 +2,14 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:queue/queue.dart';
|
import 'package:queue/queue.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
import 'package:spotube/models/SpotubeTrack.dart';
|
import 'package:spotube/models/SpotubeTrack.dart';
|
||||||
import 'package:spotube/provider/UserPreferences.dart';
|
import 'package:spotube/provider/UserPreferences.dart';
|
||||||
import 'package:spotube/provider/YouTube.dart';
|
import 'package:spotube/provider/YouTube.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
|
||||||
Queue _queueInstance = Queue(delay: const Duration(seconds: 5));
|
Queue _queueInstance = Queue(delay: const Duration(seconds: 5));
|
||||||
@ -27,15 +29,30 @@ class Downloader with ChangeNotifier {
|
|||||||
int currentlyRunning = 0;
|
int currentlyRunning = 0;
|
||||||
Set<String> inQueue = {};
|
Set<String> inQueue = {};
|
||||||
|
|
||||||
void addToQueue(SpotubeTrack track) {
|
void addToQueue(SpotubeTrack track) async {
|
||||||
if (inQueue.contains(track.id!)) return;
|
|
||||||
currentlyRunning++;
|
currentlyRunning++;
|
||||||
inQueue.add(track.id!);
|
inQueue.add(track.id!);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
final filename = '${track.ytTrack.title}.mp3';
|
||||||
|
if (kIsMobile) {
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (inQueue.contains(track.id!)) return;
|
||||||
_queue.add(() async {
|
_queue.add(() async {
|
||||||
try {
|
try {
|
||||||
final file =
|
final file = File(path.join(downloadPath, filename));
|
||||||
File(path.join(downloadPath, '${track.ytTrack.title}.mp3'));
|
|
||||||
if (file.existsSync() && await onFileExists?.call(track) != true) {
|
if (file.existsSync() && await onFileExists?.call(track) != true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -60,13 +77,18 @@ class Downloader with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cancel() {
|
cancelAll() {
|
||||||
|
if (kIsMobile) {
|
||||||
|
FlutterDownloader.cancelAll();
|
||||||
|
} else {
|
||||||
_queue.cancel();
|
_queue.cancel();
|
||||||
_queueInstance = Queue();
|
_queueInstance = Queue();
|
||||||
_queue = _queueInstance;
|
_queue = _queueInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final downloaderProvider = ChangeNotifierProvider(
|
final downloaderProvider = ChangeNotifierProvider(
|
||||||
(ref) {
|
(ref) {
|
||||||
|
Loading…
Reference in New Issue
Block a user