Merge branch 'feature/scrollbar' of kilowatt36/freezer into master

This commit is contained in:
exttex 2020-11-01 20:37:01 +00:00 committed by Gogs
commit f877aa9d7b
2 changed files with 334 additions and 308 deletions

View File

@ -13,6 +13,7 @@ import 'package:freezer/ui/error.dart';
import 'package:freezer/ui/importer_screen.dart'; import 'package:freezer/ui/importer_screen.dart';
import 'package:freezer/ui/tiles.dart'; import 'package:freezer/ui/tiles.dart';
import 'package:freezer/translations.i18n.dart'; import 'package:freezer/translations.i18n.dart';
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
import 'menu.dart'; import 'menu.dart';
import 'settings_screen.dart'; import 'settings_screen.dart';
@ -399,97 +400,100 @@ class _LibraryTracksState extends State<LibraryTracks> {
Container(width: 8.0), Container(width: 8.0),
], ],
), ),
body: ListView( body: DraggableScrollbar.rrect(
controller: _scrollController, controller: _scrollController,
children: <Widget>[ backgroundColor: Theme.of(context).primaryColor,
Container( child: ListView(
child: Row( controller: _scrollController,
mainAxisSize: MainAxisSize.max, children: <Widget>[
mainAxisAlignment: MainAxisAlignment.spaceAround, Container(
children: <Widget>[ child: Row(
MakePlaylistOffline(_playlist), mainAxisSize: MainAxisSize.max,
FlatButton( mainAxisAlignment: MainAxisAlignment.spaceAround,
child: Row( children: <Widget>[
children: <Widget>[ MakePlaylistOffline(_playlist),
Icon(Icons.file_download, size: 32.0,), FlatButton(
Container(width: 4,), child: Row(
Text('Download'.i18n) children: <Widget>[
], Icon(Icons.file_download, size: 32.0,),
), Container(width: 4,),
onPressed: () async { Text('Download'.i18n)
if (await downloadManager.addOfflinePlaylist(_playlist, private: false, context: context) != false) ],
MenuSheet(context).showDownloadStartedToast(); ),
}, onPressed: () async {
) if (await downloadManager.addOfflinePlaylist(_playlist, private: false, context: context) != false)
], MenuSheet(context).showDownloadStartedToast();
) },
), )
FreezerDivider(), ],
//Loved tracks )
...List.generate(tracks.length, (i) {
Track t = (tracks.length == (trackCount??0))?_sorted[i]:tracks[i];
return TrackTile(
t,
onTap: () {
playerHelper.playFromTrackList((tracks.length == (trackCount??0))?_sorted:tracks, t.id, QueueSource(
id: deezerAPI.favoritesPlaylistId,
text: 'Favorites'.i18n,
source: 'playlist'
));
},
onHold: () {
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(
t,
onRemove: () {
setState(() {
tracks.removeWhere((track) => t.id == track.id);
});
}
);
},
);
}),
if (_loading)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: CircularProgressIndicator(),
)
],
), ),
FreezerDivider(), FreezerDivider(),
Text( //Loved tracks
'All offline tracks'.i18n, ...List.generate(tracks.length, (i) {
textAlign: TextAlign.center, Track t = (tracks.length == (trackCount??0))?_sorted[i]:tracks[i];
style: TextStyle( return TrackTile(
fontSize: 24, t,
fontWeight: FontWeight.bold onTap: () {
playerHelper.playFromTrackList((tracks.length == (trackCount??0))?_sorted:tracks, t.id, QueueSource(
id: deezerAPI.favoritesPlaylistId,
text: 'Favorites'.i18n,
source: 'playlist'
));
},
onHold: () {
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(
t,
onRemove: () {
setState(() {
tracks.removeWhere((track) => t.id == track.id);
});
}
);
},
);
}),
if (_loading)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: CircularProgressIndicator(),
)
],
),
FreezerDivider(),
Text(
'All offline tracks'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold
),
), ),
), Container(height: 8,),
Container(height: 8,), ...List.generate(allTracks.length, (i) {
...List.generate(allTracks.length, (i) { Track t = allTracks[i];
Track t = allTracks[i]; return TrackTile(
return TrackTile( t,
t, onTap: () {
onTap: () { playerHelper.playFromTrackList(allTracks, t.id, QueueSource(
playerHelper.playFromTrackList(allTracks, t.id, QueueSource( id: 'allTracks',
id: 'allTracks', text: 'All offline tracks'.i18n,
text: 'All offline tracks'.i18n, source: 'offline'
source: 'offline' ));
)); },
}, onHold: () {
onHold: () { MenuSheet m = MenuSheet(context);
MenuSheet m = MenuSheet(context); m.defaultTrackMenu(t);
m.defaultTrackMenu(t); },
}, );
); })
}) ],
],
) )
); ));
} }
} }
@ -510,6 +514,7 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
List<Album> _albums; List<Album> _albums;
AlbumSortType _sort = AlbumSortType.DEFAULT; AlbumSortType _sort = AlbumSortType.DEFAULT;
ScrollController _scrollController = ScrollController();
List<Album> get _sorted { List<Album> get _sorted {
List<Album> albums = List.from(_albums); List<Album> albums = List.from(_albums);
@ -581,80 +586,84 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
Container(width: 8.0), Container(width: 8.0),
], ],
), ),
body: ListView( body: DraggableScrollbar.rrect(
children: <Widget>[ controller: _scrollController,
Container(height: 8.0,), backgroundColor: Theme.of(context).primaryColor,
if (!settings.offlineMode && _albums == null) child: ListView(
Row( controller: _scrollController,
mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
children: <Widget>[ Container(height: 8.0,),
CircularProgressIndicator() if (!settings.offlineMode && _albums == null)
], Row(
), mainAxisAlignment: MainAxisAlignment.center,
if (_albums != null)
...List.generate(_albums.length, (int i) {
Album a = _sorted[i];
return AlbumTile(
a,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AlbumDetails(a))
);
},
onHold: () async {
MenuSheet m = MenuSheet(context);
m.defaultAlbumMenu(a, onRemove: () {
setState(() => _albums.remove(a));
});
},
);
}),
FutureBuilder(
future: downloadManager.getOfflineAlbums(),
builder: (context, snapshot) {
if (snapshot.hasError || !snapshot.hasData || snapshot.data.length == 0) return Container(height: 0, width: 0,);
List<Album> albums = snapshot.data;
return Column(
children: <Widget>[ children: <Widget>[
FreezerDivider(), CircularProgressIndicator()
Text(
'Offline albums'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0
),
),
...List.generate(albums.length, (i) {
Album a = albums[i];
return AlbumTile(
a,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AlbumDetails(a))
);
},
onHold: () async {
MenuSheet m = MenuSheet(context);
m.defaultAlbumMenu(a, onRemove: () {
setState(() {
albums.remove(a);
_albums.remove(a);
});
});
},
);
})
], ],
); ),
},
) if (_albums != null)
], ...List.generate(_albums.length, (int i) {
), Album a = _sorted[i];
); return AlbumTile(
a,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AlbumDetails(a))
);
},
onHold: () async {
MenuSheet m = MenuSheet(context);
m.defaultAlbumMenu(a, onRemove: () {
setState(() => _albums.remove(a));
});
},
);
}),
FutureBuilder(
future: downloadManager.getOfflineAlbums(),
builder: (context, snapshot) {
if (snapshot.hasError || !snapshot.hasData || snapshot.data.length == 0) return Container(height: 0, width: 0,);
List<Album> albums = snapshot.data;
return Column(
children: <Widget>[
FreezerDivider(),
Text(
'Offline albums'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0
),
),
...List.generate(albums.length, (i) {
Album a = albums[i];
return AlbumTile(
a,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AlbumDetails(a))
);
},
onHold: () async {
MenuSheet m = MenuSheet(context);
m.defaultAlbumMenu(a, onRemove: () {
setState(() {
albums.remove(a);
_albums.remove(a);
});
});
},
);
})
],
);
},
)
],
),
));
} }
} }
@ -676,6 +685,7 @@ class _LibraryArtistsState extends State<LibraryArtists> {
ArtistSortType _sort = ArtistSortType.DEFAULT; ArtistSortType _sort = ArtistSortType.DEFAULT;
bool _loading = true; bool _loading = true;
bool _error = false; bool _error = false;
ScrollController _scrollController = ScrollController();
List<Artist> get _sorted { List<Artist> get _sorted {
List<Artist> artists = List.from(_artists); List<Artist> artists = List.from(_artists);
@ -757,43 +767,47 @@ class _LibraryArtistsState extends State<LibraryArtists> {
Container(width: 8.0), Container(width: 8.0),
], ],
), ),
body: ListView( body: DraggableScrollbar.rrect(
children: <Widget>[ controller: _scrollController,
if (_loading) backgroundColor: Theme.of(context).primaryColor,
Padding( child: ListView(
padding: EdgeInsets.all(8.0), controller: _scrollController,
child: Row( children: <Widget>[
mainAxisAlignment: MainAxisAlignment.center, if (_loading)
children: [CircularProgressIndicator()], Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [CircularProgressIndicator()],
),
), ),
),
if (_error) if (_error)
Center(child: ErrorScreen()), Center(child: ErrorScreen()),
if (!_loading && !_error) if (!_loading && !_error)
...List.generate(_artists.length, (i) { ...List.generate(_artists.length, (i) {
Artist a = _sorted[i]; Artist a = _sorted[i];
return ArtistHorizontalTile( return ArtistHorizontalTile(
a, a,
onTap: () { onTap: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute(builder: (context) => ArtistDetails(a)) MaterialPageRoute(builder: (context) => ArtistDetails(a))
); );
}, },
onHold: () { onHold: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);
m.defaultArtistMenu(a, onRemove: () { m.defaultArtistMenu(a, onRemove: () {
setState(() { setState(() {
_artists.remove(a); _artists.remove(a);
});
}); });
}); },
}, );
); }),
}), ],
],
), ),
); ));
} }
} }
@ -814,6 +828,7 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
List<Playlist> _playlists; List<Playlist> _playlists;
PlaylistSortType _sort = PlaylistSortType.DEFAULT; PlaylistSortType _sort = PlaylistSortType.DEFAULT;
ScrollController _scrollController = ScrollController();
List<Playlist> get _sorted { List<Playlist> get _sorted {
List<Playlist> playlists = List.from(_playlists); List<Playlist> playlists = List.from(_playlists);
@ -902,111 +917,115 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
Container(width: 8.0), Container(width: 8.0),
], ],
), ),
body: ListView( body: DraggableScrollbar.rrect(
children: <Widget>[ controller: _scrollController,
ListTile( backgroundColor: Theme.of(context).primaryColor,
title: Text('Create new playlist'.i18n), child: ListView(
leading: LeadingIcon(Icons.playlist_add, color: Color(0xff009a85)), controller: _scrollController,
onTap: () async { children: <Widget>[
if (settings.offlineMode) { ListTile(
Fluttertoast.showToast( title: Text('Create new playlist'.i18n),
msg: 'Cannot create playlists in offline mode'.i18n, leading: LeadingIcon(Icons.playlist_add, color: Color(0xff009a85)),
gravity: ToastGravity.BOTTOM onTap: () async {
); if (settings.offlineMode) {
return; Fluttertoast.showToast(
} msg: 'Cannot create playlists in offline mode'.i18n,
MenuSheet m = MenuSheet(context); gravity: ToastGravity.BOTTOM
await m.createPlaylist(); );
await _load(); return;
}, }
), MenuSheet m = MenuSheet(context);
FreezerDivider(), await m.createPlaylist();
await _load();
},
),
FreezerDivider(),
if (!settings.offlineMode && _playlists == null) if (!settings.offlineMode && _playlists == null)
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
CircularProgressIndicator(), CircularProgressIndicator(),
], ],
),
//Favorites playlist
PlaylistTile(
favoritesPlaylist,
onTap: () async {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => PlaylistDetails(favoritesPlaylist)
));
},
onHold: () {
MenuSheet m = MenuSheet(context);
favoritesPlaylist.library = true;
m.defaultPlaylistMenu(favoritesPlaylist);
},
), ),
//Favorites playlist if (_playlists != null)
PlaylistTile( ...List.generate(_playlists.length, (int i) {
favoritesPlaylist, Playlist p = (_sorted??[])[i];
onTap: () async { return PlaylistTile(
Navigator.of(context).push(MaterialPageRoute( p,
builder: (context) => PlaylistDetails(favoritesPlaylist) onTap: () => Navigator.of(context).push(MaterialPageRoute(
)); builder: (context) => PlaylistDetails(p)
}, )),
onHold: () { onHold: () {
MenuSheet m = MenuSheet(context); MenuSheet m = MenuSheet(context);
favoritesPlaylist.library = true; m.defaultPlaylistMenu(
m.defaultPlaylistMenu(favoritesPlaylist);
},
),
if (_playlists != null)
...List.generate(_playlists.length, (int i) {
Playlist p = (_sorted??[])[i];
return PlaylistTile(
p,
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => PlaylistDetails(p)
)),
onHold: () {
MenuSheet m = MenuSheet(context);
m.defaultPlaylistMenu(
p,
onRemove: () {setState(() => _playlists.remove(p));},
onUpdate: () {_load();});
},
);
}),
FutureBuilder(
future: downloadManager.getOfflinePlaylists(),
builder: (context, snapshot) {
if (snapshot.hasError || !snapshot.hasData) return Container(height: 0, width: 0,);
if (snapshot.data.length == 0) return Container(height: 0, width: 0,);
List<Playlist> playlists = snapshot.data;
return Column(
children: <Widget>[
FreezerDivider(),
Text(
'Offline playlists'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold
),
),
...List.generate(playlists.length, (i) {
Playlist p = playlists[i];
return PlaylistTile(
p, p,
onTap: () => Navigator.of(context).push(MaterialPageRoute( onRemove: () {setState(() => _playlists.remove(p));},
builder: (context) => PlaylistDetails(p) onUpdate: () {_load();});
)), },
onHold: () { );
MenuSheet m = MenuSheet(context); }),
m.defaultPlaylistMenu(p, onRemove: () {
setState(() { FutureBuilder(
playlists.remove(p); future: downloadManager.getOfflinePlaylists(),
_playlists.remove(p); builder: (context, snapshot) {
if (snapshot.hasError || !snapshot.hasData) return Container(height: 0, width: 0,);
if (snapshot.data.length == 0) return Container(height: 0, width: 0,);
List<Playlist> playlists = snapshot.data;
return Column(
children: <Widget>[
FreezerDivider(),
Text(
'Offline playlists'.i18n,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold
),
),
...List.generate(playlists.length, (i) {
Playlist p = playlists[i];
return PlaylistTile(
p,
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => PlaylistDetails(p)
)),
onHold: () {
MenuSheet m = MenuSheet(context);
m.defaultPlaylistMenu(p, onRemove: () {
setState(() {
playlists.remove(p);
_playlists.remove(p);
});
}); });
}); },
}, );
); })
}) ],
], );
); },
}, )
)
], ],
), ),
); ));
} }
} }
@ -1016,6 +1035,7 @@ class HistoryScreen extends StatefulWidget {
} }
class _HistoryScreenState extends State<HistoryScreen> { class _HistoryScreenState extends State<HistoryScreen> {
ScrollController _scrollController = ScrollController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -1031,25 +1051,30 @@ class _HistoryScreenState extends State<HistoryScreen> {
) )
], ],
), ),
body: ListView.builder( body: DraggableScrollbar.rrect(
itemCount: (cache.history??[]).length, controller: _scrollController,
itemBuilder: (BuildContext context, int i) { backgroundColor: Theme.of(context).primaryColor,
Track t = cache.history[cache.history.length - i - 1]; child: ListView.builder(
return TrackTile( controller: _scrollController,
t, itemCount: (cache.history??[]).length,
onTap: () { itemBuilder: (BuildContext context, int i) {
playerHelper.playFromTrackList(cache.history.reversed.toList(), t.id, QueueSource( Track t = cache.history[cache.history.length - i - 1];
id: null, return TrackTile(
text: 'History'.i18n, t,
source: 'history' onTap: () {
)); playerHelper.playFromTrackList(cache.history.reversed.toList(), t.id, QueueSource(
}, id: null,
onHold: () { text: 'History'.i18n,
MenuSheet m = MenuSheet(context); source: 'history'
m.defaultTrackMenu(t); ));
}, },
); onHold: () {
}, MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(t);
},
);
},
)
), ),
); );
} }

View File

@ -70,6 +70,7 @@ dependencies:
numberpicker: ^1.2.1 numberpicker: ^1.2.1
quick_actions: ^0.4.0+10 quick_actions: ^0.4.0+10
photo_view: ^0.10.2 photo_view: ^0.10.2
draggable_scrollbar: 0.0.4
audio_session: ^0.0.9 audio_session: ^0.0.9
audio_service: audio_service: