-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f4bbc24
commit 3f7ab62
Showing
21 changed files
with
478 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,69 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CADisableMinimumFrameDurationOnPhone</key> | ||
<true/> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>$(DEVELOPMENT_LANGUAGE)</string> | ||
<key>CFBundleDisplayName</key> | ||
<string>$(BUNDLE_DISPLAY_NAME)</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(BUNDLE_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>APPL</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>$(FLUTTER_BUILD_NAME)</string> | ||
<key>CFBundleSignature</key> | ||
<string>????</string> | ||
<key>CFBundleVersion</key> | ||
<string>$(FLUTTER_BUILD_NUMBER)</string> | ||
<key>LSRequiresIPhoneOS</key> | ||
<true/> | ||
<key>UIApplicationSupportsIndirectInputEvents</key> | ||
<true/> | ||
<key>UILaunchStoryboardName</key> | ||
<string>$(LAUNCH_SCREEN)</string> | ||
<key>UIMainStoryboardFile</key> | ||
<string>Main</string> | ||
<key>UISupportedInterfaceOrientations</key> | ||
<array> | ||
<string>UIInterfaceOrientationLandscapeLeft</string> | ||
<string>UIInterfaceOrientationLandscapeRight</string> | ||
<string>UIInterfaceOrientationPortrait</string> | ||
</array> | ||
<key>UISupportedInterfaceOrientations~ipad</key> | ||
<array> | ||
<string>UIInterfaceOrientationLandscapeLeft</string> | ||
<string>UIInterfaceOrientationLandscapeRight</string> | ||
<string>UIInterfaceOrientationPortrait</string> | ||
<string>UIInterfaceOrientationPortraitUpsideDown</string> | ||
</array> | ||
<key>UIViewControllerBasedStatusBarAppearance</key> | ||
<false/> | ||
<key>UIBackgroundModes</key> | ||
<array> | ||
<string>audio</string> | ||
</array> | ||
<key>UIStatusBarHidden</key> | ||
<false/> | ||
<!-- Google Sign-in Section --> | ||
<key>CFBundleURLTypes</key> | ||
<array> | ||
<dict> | ||
<key>CFBundleTypeRole</key> | ||
<string>Editor</string> | ||
<key>CFBundleURLSchemes</key> | ||
<array> | ||
<!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID --> | ||
<string>$(GOOGLE_REVERSED_CLIENT_ID)</string> | ||
</array> | ||
</dict> | ||
</array> | ||
<!-- End of the Google Sign-in Section --> | ||
</dict> | ||
<dict> | ||
<key>CADisableMinimumFrameDurationOnPhone</key> | ||
<true/> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>$(DEVELOPMENT_LANGUAGE)</string> | ||
<key>CFBundleDisplayName</key> | ||
<string>$(BUNDLE_DISPLAY_NAME)</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(BUNDLE_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>APPL</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>$(FLUTTER_BUILD_NAME)</string> | ||
<key>CFBundleSignature</key> | ||
<string>????</string> | ||
<key>CFBundleURLTypes</key> | ||
<array> | ||
<dict> | ||
<key>CFBundleTypeRole</key> | ||
<string>Editor</string> | ||
<key>CFBundleURLSchemes</key> | ||
<array> | ||
<string>$(GOOGLE_REVERSED_CLIENT_ID)</string> | ||
</array> | ||
</dict> | ||
</array> | ||
<key>CFBundleVersion</key> | ||
<string>$(FLUTTER_BUILD_NUMBER)</string> | ||
<key>LSRequiresIPhoneOS</key> | ||
<true/> | ||
<key>UIApplicationSupportsIndirectInputEvents</key> | ||
<true/> | ||
<key>UIBackgroundModes</key> | ||
<array> | ||
<string>audio</string> | ||
<string>fetch</string> | ||
</array> | ||
<key>UILaunchStoryboardName</key> | ||
<string>$(LAUNCH_SCREEN)</string> | ||
<key>UIMainStoryboardFile</key> | ||
<string>Main</string> | ||
<key>UIStatusBarHidden</key> | ||
<false/> | ||
<key>UISupportedInterfaceOrientations</key> | ||
<array> | ||
<string>UIInterfaceOrientationLandscapeLeft</string> | ||
<string>UIInterfaceOrientationLandscapeRight</string> | ||
<string>UIInterfaceOrientationPortrait</string> | ||
</array> | ||
<key>UISupportedInterfaceOrientations~ipad</key> | ||
<array> | ||
<string>UIInterfaceOrientationLandscapeLeft</string> | ||
<string>UIInterfaceOrientationLandscapeRight</string> | ||
<string>UIInterfaceOrientationPortrait</string> | ||
<string>UIInterfaceOrientationPortraitUpsideDown</string> | ||
</array> | ||
<key>UIViewControllerBasedStatusBarAppearance</key> | ||
<false/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:background_downloader/background_downloader.dart'; | ||
import 'package:equatable/equatable.dart'; | ||
import 'package:hive_flutter/hive_flutter.dart'; | ||
import 'package:rxdart/rxdart.dart'; | ||
import 'package:varanasi_mobile_app/models/download.dart'; | ||
import 'package:varanasi_mobile_app/models/media_playlist.dart'; | ||
import 'package:varanasi_mobile_app/models/playable_item.dart'; | ||
import 'package:varanasi_mobile_app/models/song.dart'; | ||
import 'package:varanasi_mobile_app/utils/app_cubit.dart'; | ||
import 'package:varanasi_mobile_app/utils/constants/strings.dart'; | ||
import 'package:varanasi_mobile_app/utils/logger.dart'; | ||
|
||
part 'download_state.dart'; | ||
|
||
class DownloadCubit extends AppCubit<DownloadState> { | ||
DownloadCubit() : super(const DownloadState()); | ||
|
||
late final Box<DownloadedMedia> _downloadBox; | ||
late final FileDownloader _downloader; | ||
|
||
late final Map<String, Song> _expando; | ||
|
||
Logger get _logger => Logger.instance; | ||
|
||
@override | ||
FutureOr<void> init() async { | ||
_expando = {}; | ||
_downloadBox = | ||
await Hive.openBox<DownloadedMedia>(AppStrings.downloadBoxName); | ||
_downloader = FileDownloader(); | ||
_downloader.updates.listen((update) { | ||
if (update is TaskStatusUpdate) { | ||
_handleTaskStatusUpdate(update); | ||
} else if (update is TaskProgressUpdate) { | ||
_handleTaskProgressUpdate(update); | ||
} | ||
}); | ||
} | ||
|
||
void _handleTaskProgressUpdate(TaskProgressUpdate update) { | ||
final item = _downloadBox.get(update.task.taskId); | ||
if (item != null) { | ||
_downloadBox.put( | ||
update.task.taskId, | ||
item.copyWith(progress: update.progress), | ||
); | ||
_logger.i('Dl pro for ${item.id}: ${item.progress}'); | ||
} | ||
} | ||
|
||
void _handleTaskStatusUpdate(TaskStatusUpdate update) async { | ||
if (update.status == TaskStatus.enqueued) { | ||
_logger.i('Download enqueued for ${update.task.taskId}'); | ||
_downloadBox.put( | ||
update.task.taskId, | ||
DownloadedMedia( | ||
id: update.task.taskId, | ||
progress: 0, | ||
downloadComplete: false, | ||
media: _expando[update.task.taskId]!, | ||
path: '', | ||
), | ||
); | ||
return; | ||
} | ||
final item = _downloadBox.get(update.task.taskId); | ||
if (update.status.isNotFinalState && item != null) { | ||
_downloadBox.put( | ||
item.id, | ||
item.copyWith(downloading: update.status == TaskStatus.running), | ||
); | ||
_logger.i('Download status for ${update.task.taskId}: ' | ||
'${update.status}'); | ||
return; | ||
} | ||
|
||
if (item != null) { | ||
if (update.status == TaskStatus.complete) { | ||
final path = await update.task.filePath(); | ||
_downloadBox.put( | ||
item.id, | ||
item.copyWith( | ||
downloadComplete: true, | ||
progress: 1, | ||
path: path, | ||
downloading: false, | ||
), | ||
); | ||
_logger.i('Download complete for ${item.id} path: $path'); | ||
} else if (update.status.isFinalState) { | ||
_downloadBox.delete(item.id); | ||
_logger.i('Download failed for ${item.id}'); | ||
} | ||
} | ||
} | ||
|
||
String _fileNameFromSong(Song song) { | ||
final ext = song.itemUrl.split('.').last; | ||
return '${song.itemId}.$ext'; | ||
} | ||
|
||
DownloadTask _songToTask(Song song) { | ||
final fileName = _fileNameFromSong(song); | ||
return DownloadTask( | ||
taskId: song.itemId, | ||
url: song.itemUrl, | ||
filename: fileName, | ||
updates: Updates.statusAndProgress, | ||
); | ||
} | ||
|
||
Future<void> downloadSong(PlayableMedia song) async { | ||
assert(song is Song, 'Only songs can be downloaded'); | ||
if (song is! Song) return; | ||
_expando[song.itemId] = song; | ||
final queued = await _downloader.enqueue(_songToTask(song)); | ||
_logger.i('Queued ${song.itemId} status: $queued'); | ||
} | ||
|
||
Future<void> batchDownload(MediaPlaylist playlist) async { | ||
final songs = playlist.mediaItems ?? []; | ||
final filteredsong = songs.whereType<Song>(); | ||
final tasks = filteredsong.map(_songToTask).toList(); | ||
for (final song in filteredsong) { | ||
_expando[song.itemId] = song; | ||
} | ||
await _downloader.downloadBatch( | ||
tasks, | ||
taskStatusCallback: _handleTaskStatusUpdate, | ||
taskProgressCallback: _handleTaskProgressUpdate, | ||
); | ||
} | ||
|
||
Future<void> cancelDownload(PlayableMedia media) => | ||
_downloader.cancelTaskWithId(media.itemId); | ||
|
||
/// Returns a stream of [DownloadedMedia] for the given [song]. | ||
/// | ||
/// The stream will emit the current download status of the song and | ||
/// | ||
/// will continue to emit updates until the download is complete or | ||
Stream<DownloadedMedia?> listen(PlayableMedia song) { | ||
final curr = _downloadBox.get(song.itemId); | ||
return Rx.concat([ | ||
if (curr != null) Stream.value(curr), | ||
_downloadBox.watch(key: song.itemId).map((e) => e.value) | ||
]); | ||
} | ||
|
||
DownloadedMedia? getDownloadedMedia(PlayableMedia song) => | ||
_downloadBox.get(song.itemId); | ||
|
||
Future<void> deleteDownloadedMedia(PlayableMedia song) => | ||
_downloadBox.delete(song.itemId); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
part of 'download_cubit.dart'; | ||
|
||
class DownloadState extends Equatable { | ||
const DownloadState(); | ||
|
||
@override | ||
List<Object> get props => []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.