-
Notifications
You must be signed in to change notification settings - Fork 18
feat: add album download button #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ import '../theme/app_theme.dart'; | |
| import '../widgets/widgets.dart'; | ||
| import 'artist_screen.dart'; | ||
| import '../l10n/app_localizations.dart'; | ||
| import '../services/offline_service.dart'; | ||
|
|
||
| class AlbumScreen extends StatefulWidget { | ||
| final String albumId; | ||
|
|
@@ -23,6 +24,7 @@ class _AlbumScreenState extends State<AlbumScreen> { | |
| Album? _album; | ||
| List<Song> _songs = []; | ||
| bool _isLoading = true; | ||
| bool _isDownloading = false; | ||
|
|
||
| @override | ||
| void initState() { | ||
|
|
@@ -81,6 +83,42 @@ class _AlbumScreenState extends State<AlbumScreen> { | |
| playerProvider.playSong(playlist.first, playlist: playlist, startIndex: 0); | ||
| } | ||
|
|
||
| Future<void> _downloadAlbum() async { | ||
| if (_songs.isEmpty) return; | ||
|
|
||
| final subsonicService = Provider.of<SubsonicService>( | ||
| context, | ||
| listen: false, | ||
| ); | ||
| final offlineService = OfflineService(); | ||
| await offlineService.initialize(); | ||
|
|
||
| setState(() => _isDownloading = true); | ||
|
|
||
| offlineService.startBackgroundDownload(_songs, subsonicService).then((_) { | ||
| if (mounted) { | ||
| setState(() => _isDownloading = false); | ||
| ScaffoldMessenger.of(context).showSnackBar( | ||
| SnackBar( | ||
| content: Text( | ||
| 'Downloaded ${_songs.length} songs from ${_album!.name}', | ||
| ), | ||
| duration: const Duration(seconds: 3), | ||
| ), | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
| if (mounted) { | ||
| ScaffoldMessenger.of(context).showSnackBar( | ||
| SnackBar( | ||
| content: Text('Downloading ${_songs.length} songs in background…'), | ||
|
Comment on lines
+104
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Localize newly added UI strings. At Lines 104, 115, and 253, strings are hardcoded in English. This bypasses Also applies to: 253-253 🤖 Prompt for AI Agents |
||
| duration: const Duration(seconds: 2), | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| final theme = Theme.of(context); | ||
|
|
@@ -160,6 +198,10 @@ class _AlbumScreenState extends State<AlbumScreen> { | |
| final hours = totalDuration ~/ 3600; | ||
| final minutes = (totalDuration % 3600) ~/ 60; | ||
|
|
||
| final isOffline = | ||
| Provider.of<AuthProvider>(context, listen: false).state == | ||
| AuthState.offlineMode; | ||
|
Comment on lines
+201
to
+203
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -type f -name "album_screen.dart" | head -5Repository: dddevid/Musly Length of output: 88 🏁 Script executed: find . -type f -name "auth_provider.dart" | head -5Repository: dddevid/Musly Length of output: 91 🏁 Script executed: cat -n lib/screens/album_screen.dart | sed -n '195,260p'Repository: dddevid/Musly Length of output: 2968 🏁 Script executed: cat -n lib/providers/auth_provider.dartRepository: dddevid/Musly Length of output: 11420 Make auth gating reactive and restrict download to authenticated state. At line 202, using Replace with reactive pattern using Also applies to: 251 🤖 Prompt for AI Agents |
||
|
|
||
| return Scaffold( | ||
| body: Stack( | ||
| children: [ | ||
|
|
@@ -205,6 +247,20 @@ class _AlbumScreenState extends State<AlbumScreen> { | |
| ], | ||
| ), | ||
| ), | ||
| actions: [ | ||
| if (!isOffline) | ||
| IconButton( | ||
| tooltip: 'Download album', | ||
| onPressed: _isDownloading ? null : _downloadAlbum, | ||
| icon: _isDownloading | ||
| ? const SizedBox( | ||
| width: 20, | ||
| height: 20, | ||
| child: CircularProgressIndicator(strokeWidth: 2), | ||
| ) | ||
| : const Icon(CupertinoIcons.cloud_download), | ||
| ), | ||
| ], | ||
| ), | ||
| SliverToBoxAdapter( | ||
| child: Padding( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid unconditional success messaging after completion.
At Line 104, the snackbar claims all songs were downloaded, but
OfflineService.startBackgroundDownload()absorbs failures and still completes normally. This can report success on partial/failed downloads.Suggested adjustment in this file (safe interim)
📝 Committable suggestion
🤖 Prompt for AI Agents