Offline albums fix, adaptive icon, option to replace downloads

This commit is contained in:
exttex 2020-09-13 16:06:12 +02:00
parent a494601ab0
commit 24e598fe99
6 changed files with 80 additions and 7 deletions

View File

@ -598,6 +598,14 @@ class Download {
this.path = p.join(this.path, _filename); this.path = p.join(this.path, _filename);
} }
//Check if file exists
if (await File(this.path).exists() && !settings.overwriteDownload) {
this.state = DownloadState.DONE;
onDone();
return;
}
//Download //Download
this.state = DownloadState.DOWNLOADING; this.state = DownloadState.DOWNLOADING;

View File

@ -1,6 +1,7 @@
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:freezer/api/deezer.dart'; import 'package:freezer/api/deezer.dart';
import 'package:freezer/ui/details_screens.dart';
import 'package:just_audio/just_audio.dart'; import 'package:just_audio/just_audio.dart';
import 'package:connectivity/connectivity.dart'; import 'package:connectivity/connectivity.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
@ -309,7 +310,12 @@ class AudioPlayerTask extends BackgroundAudioTask {
MediaControl.skipToPrevious, MediaControl.skipToPrevious,
if (_player.playing) MediaControl.pause else MediaControl.play, if (_player.playing) MediaControl.pause else MediaControl.play,
MediaControl.skipToNext, MediaControl.skipToNext,
MediaControl.stop //Stop
MediaControl(
androidIcon: 'drawable/ic_action_stop',
label: 'stop',
action: MediaAction.stop
)
], ],
systemActions: [ systemActions: [
MediaAction.seekTo, MediaAction.seekTo,

View File

@ -45,6 +45,8 @@ class Settings {
bool artistFolder; bool artistFolder;
@JsonKey(defaultValue: false) @JsonKey(defaultValue: false)
bool albumDiscFolder; bool albumDiscFolder;
@JsonKey(defaultValue: false)
bool overwriteDownload;
//Appearance //Appearance

View File

@ -28,6 +28,7 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) {
..albumFolder = json['albumFolder'] as bool ?? true ..albumFolder = json['albumFolder'] as bool ?? true
..artistFolder = json['artistFolder'] as bool ?? true ..artistFolder = json['artistFolder'] as bool ?? true
..albumDiscFolder = json['albumDiscFolder'] as bool ?? false ..albumDiscFolder = json['albumDiscFolder'] as bool ?? false
..overwriteDownload = json['overwriteDownload'] as bool ?? false
..theme = ..theme =
_$enumDecodeNullable(_$ThemesEnumMap, json['theme']) ?? Themes.Light _$enumDecodeNullable(_$ThemesEnumMap, json['theme']) ?? Themes.Light
..primaryColor = Settings._colorFromJson(json['primaryColor'] as int) ..primaryColor = Settings._colorFromJson(json['primaryColor'] as int)
@ -48,6 +49,7 @@ Map<String, dynamic> _$SettingsToJson(Settings instance) => <String, dynamic>{
'albumFolder': instance.albumFolder, 'albumFolder': instance.albumFolder,
'artistFolder': instance.artistFolder, 'artistFolder': instance.artistFolder,
'albumDiscFolder': instance.albumDiscFolder, 'albumDiscFolder': instance.albumDiscFolder,
'overwriteDownload': instance.overwriteDownload,
'theme': _$ThemesEnumMap[instance.theme], 'theme': _$ThemesEnumMap[instance.theme],
'primaryColor': Settings._colorToJson(instance.primaryColor), 'primaryColor': Settings._colorToJson(instance.primaryColor),
'useArtColor': instance.useArtColor, 'useArtColor': instance.useArtColor,

View File

@ -30,7 +30,7 @@ class AlbumDetails extends StatelessWidget {
int get cdCount { int get cdCount {
int c = 1; int c = 1;
for (Track t in album.tracks) { for (Track t in album.tracks) {
if (t.diskNumber > c) c = t.diskNumber; if ((t.diskNumber??1) > c) c = t.diskNumber;
} }
return c; return c;
} }
@ -163,7 +163,7 @@ class AlbumDetails extends StatelessWidget {
), ),
), ),
...List.generate(cdCount, (cdi) { ...List.generate(cdCount, (cdi) {
List<Track> tracks = album.tracks.where((t) => t.diskNumber == cdi + 1).toList(); List<Track> tracks = album.tracks.where((t) => (t.diskNumber??1) == cdi + 1).toList();
return Column( return Column(
children: [ children: [
Padding( Padding(
@ -601,7 +601,11 @@ class _DiscographyScreenState extends State<DiscographyScreen> {
} }
} }
enum SortType {
DEFAULT,
ALPHABETIC,
ARTIST
}
class PlaylistDetails extends StatefulWidget { class PlaylistDetails extends StatefulWidget {
@ -617,8 +621,25 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
Playlist playlist; Playlist playlist;
bool _loading = false; bool _loading = false;
bool _error = false; bool _error = false;
SortType _sort = SortType.DEFAULT;
ScrollController _scrollController = ScrollController(); ScrollController _scrollController = ScrollController();
//Get sorted playlist
List<Track> get sorted {
List<Track> tracks = new List.from(playlist.tracks??[]);
switch (_sort) {
case SortType.ALPHABETIC:
tracks.sort((a, b) => a.title.compareTo(b.title));
return tracks;
case SortType.ARTIST:
tracks.sort((a, b) => a.artists[0].name.compareTo(b.artists[0].name));
return tracks;
case SortType.DEFAULT:
default:
return tracks;
}
}
//Load tracks from api //Load tracks from api
void _load() async { void _load() async {
if (playlist.tracks.length < playlist.trackCount && !_loading) { if (playlist.tracks.length < playlist.trackCount && !_loading) {
@ -790,16 +811,40 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
onPressed: () { onPressed: () {
downloadManager.addOfflinePlaylist(playlist, private: false); downloadManager.addOfflinePlaylist(playlist, private: false);
}, },
) ),
PopupMenuButton(
child: Icon(Icons.sort, size: 32.0),
onSelected: (SortType s) => setState(() => _sort = s),
itemBuilder: (context) => <PopupMenuEntry<SortType>>[
const PopupMenuItem(
value: SortType.DEFAULT,
child: Text('Default'),
),
const PopupMenuItem(
value: SortType.ALPHABETIC,
child: Text('Alphabetic'),
),
const PopupMenuItem(
value: SortType.ARTIST,
child: Text('Artist'),
),
],
),
Container(width: 4.0)
], ],
), ),
), ),
...List.generate(playlist.tracks.length, (i) { ...List.generate(playlist.tracks.length, (i) {
Track t = playlist.tracks[i]; Track t = sorted[i];
return TrackTile( return TrackTile(
t, t,
onTap: () { onTap: () {
playerHelper.playFromPlaylist(playlist, t.id); Playlist p = Playlist(
title: playlist.title,
id: playlist.id,
tracks: sorted
);
playerHelper.playFromPlaylist(p, t.id);
}, },
onHold: () { onHold: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);

View File

@ -567,6 +567,16 @@ class _GeneralSettingsState extends State<GeneralSettings> {
}, },
), ),
), ),
ListTile(
title: Text('Overwrite already downloaded files'),
leading: Switch(
value: settings.overwriteDownload,
onChanged: (v) {
setState(() => settings.overwriteDownload = v);
settings.save();
},
),
),
ListTile( ListTile(
title: Text('Copy ARL'), title: Text('Copy ARL'),
subtitle: Text('Copy userToken/ARL Cookie for use in other apps.'), subtitle: Text('Copy userToken/ARL Cookie for use in other apps.'),