Offline albums fix, adaptive icon, option to replace downloads
This commit is contained in:
parent
a494601ab0
commit
24e598fe99
|
@ -598,6 +598,14 @@ class Download {
|
|||
|
||||
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
|
||||
this.state = DownloadState.DOWNLOADING;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:freezer/api/deezer.dart';
|
||||
import 'package:freezer/ui/details_screens.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import 'package:connectivity/connectivity.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
@ -309,7 +310,12 @@ class AudioPlayerTask extends BackgroundAudioTask {
|
|||
MediaControl.skipToPrevious,
|
||||
if (_player.playing) MediaControl.pause else MediaControl.play,
|
||||
MediaControl.skipToNext,
|
||||
MediaControl.stop
|
||||
//Stop
|
||||
MediaControl(
|
||||
androidIcon: 'drawable/ic_action_stop',
|
||||
label: 'stop',
|
||||
action: MediaAction.stop
|
||||
)
|
||||
],
|
||||
systemActions: [
|
||||
MediaAction.seekTo,
|
||||
|
|
|
@ -45,6 +45,8 @@ class Settings {
|
|||
bool artistFolder;
|
||||
@JsonKey(defaultValue: false)
|
||||
bool albumDiscFolder;
|
||||
@JsonKey(defaultValue: false)
|
||||
bool overwriteDownload;
|
||||
|
||||
|
||||
//Appearance
|
||||
|
|
|
@ -28,6 +28,7 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) {
|
|||
..albumFolder = json['albumFolder'] as bool ?? true
|
||||
..artistFolder = json['artistFolder'] as bool ?? true
|
||||
..albumDiscFolder = json['albumDiscFolder'] as bool ?? false
|
||||
..overwriteDownload = json['overwriteDownload'] as bool ?? false
|
||||
..theme =
|
||||
_$enumDecodeNullable(_$ThemesEnumMap, json['theme']) ?? Themes.Light
|
||||
..primaryColor = Settings._colorFromJson(json['primaryColor'] as int)
|
||||
|
@ -48,6 +49,7 @@ Map<String, dynamic> _$SettingsToJson(Settings instance) => <String, dynamic>{
|
|||
'albumFolder': instance.albumFolder,
|
||||
'artistFolder': instance.artistFolder,
|
||||
'albumDiscFolder': instance.albumDiscFolder,
|
||||
'overwriteDownload': instance.overwriteDownload,
|
||||
'theme': _$ThemesEnumMap[instance.theme],
|
||||
'primaryColor': Settings._colorToJson(instance.primaryColor),
|
||||
'useArtColor': instance.useArtColor,
|
||||
|
|
|
@ -30,7 +30,7 @@ class AlbumDetails extends StatelessWidget {
|
|||
int get cdCount {
|
||||
int c = 1;
|
||||
for (Track t in album.tracks) {
|
||||
if (t.diskNumber > c) c = t.diskNumber;
|
||||
if ((t.diskNumber??1) > c) c = t.diskNumber;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ class AlbumDetails extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
...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(
|
||||
children: [
|
||||
Padding(
|
||||
|
@ -601,7 +601,11 @@ class _DiscographyScreenState extends State<DiscographyScreen> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
enum SortType {
|
||||
DEFAULT,
|
||||
ALPHABETIC,
|
||||
ARTIST
|
||||
}
|
||||
|
||||
class PlaylistDetails extends StatefulWidget {
|
||||
|
||||
|
@ -617,8 +621,25 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
|
|||
Playlist playlist;
|
||||
bool _loading = false;
|
||||
bool _error = false;
|
||||
SortType _sort = SortType.DEFAULT;
|
||||
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
|
||||
void _load() async {
|
||||
if (playlist.tracks.length < playlist.trackCount && !_loading) {
|
||||
|
@ -790,16 +811,40 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
|
|||
onPressed: () {
|
||||
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) {
|
||||
Track t = playlist.tracks[i];
|
||||
Track t = sorted[i];
|
||||
return TrackTile(
|
||||
t,
|
||||
onTap: () {
|
||||
playerHelper.playFromPlaylist(playlist, t.id);
|
||||
Playlist p = Playlist(
|
||||
title: playlist.title,
|
||||
id: playlist.id,
|
||||
tracks: sorted
|
||||
);
|
||||
playerHelper.playFromPlaylist(p, t.id);
|
||||
},
|
||||
onHold: () {
|
||||
MenuSheet m = MenuSheet(context);
|
||||
|
|
|
@ -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(
|
||||
title: Text('Copy ARL'),
|
||||
subtitle: Text('Copy userToken/ARL Cookie for use in other apps.'),
|
||||
|
|
Loading…
Reference in New Issue