scrollbars and queuepage

This commit is contained in:
Moritz Weber 2021-07-17 22:34:55 +02:00
parent 7418ffdded
commit d64250f6bf
7 changed files with 135 additions and 93 deletions

View file

@ -26,28 +26,30 @@ class _AlbumsPageState extends State<AlbumsPage> with AutomaticKeepAliveClientMi
return Observer(builder: (_) {
print('AlbumsPage.build -> Observer.builder');
final List<Album> albums = store.albumStream.value ?? [];
return ListView.separated(
itemCount: albums.length,
itemBuilder: (_, int index) {
final Album album = albums[index];
return AlbumArtListTile(
title: album.title,
subtitle: album.artist,
albumArtPath: album.albumArtPath,
onTap: () {
navStore.push(
context,
MaterialPageRoute<Widget>(
builder: (BuildContext context) => AlbumDetailsPage(
album: album,
return Scrollbar(
child: ListView.separated(
itemCount: albums.length,
itemBuilder: (_, int index) {
final Album album = albums[index];
return AlbumArtListTile(
title: album.title,
subtitle: album.artist,
albumArtPath: album.albumArtPath,
onTap: () {
navStore.push(
context,
MaterialPageRoute<Widget>(
builder: (BuildContext context) => AlbumDetailsPage(
album: album,
),
),
),
);
},
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
);
},
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
),
),
);
});

View file

@ -25,26 +25,28 @@ class _ArtistsPageState extends State<ArtistsPage> with AutomaticKeepAliveClient
return Observer(builder: (_) {
print('ArtistsPage.build -> Observer.builder');
final List<Artist> artists = musicDataStore.artistStream.value ?? [];
return ListView.separated(
itemCount: artists.length,
itemBuilder: (_, int index) {
final Artist artist = artists[index];
return ListTile(
title: Text(artist.name),
onTap: () {
navStore.push(
context,
MaterialPageRoute<Widget>(
builder: (BuildContext context) => ArtistDetailsPage(
artist: artist,
return Scrollbar(
child: ListView.separated(
itemCount: artists.length,
itemBuilder: (_, int index) {
final Artist artist = artists[index];
return ListTile(
title: Text(artist.name),
onTap: () {
navStore.push(
context,
MaterialPageRoute<Widget>(
builder: (BuildContext context) => ArtistDetailsPage(
artist: artist,
),
),
),
);
},
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
);
},
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
),
),
);
});

View file

@ -57,7 +57,6 @@ class CurrentlyPlayingPage extends StatelessWidget {
padding: const EdgeInsets.only(
left: 12.0,
right: 12.0,
top: 8.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View file

@ -8,7 +8,9 @@ import 'package:reorderables/reorderables.dart';
import '../../domain/entities/song.dart';
import '../state/audio_store.dart';
import '../widgets/album_art_list_tile.dart';
import '../theming.dart';
import '../widgets/song_bottom_sheet.dart';
import '../widgets/song_list_tile.dart';
class QueuePage extends StatelessWidget {
const QueuePage({Key? key}) : super(key: key);
@ -24,6 +26,33 @@ class QueuePage extends StatelessWidget {
ScrollController(initialScrollOffset: initialIndex * 72.0);
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.only(left: 12.0),
child: IconButton(
icon: const Icon(Icons.expand_more),
onPressed: () => Navigator.pop(context),
),
),
leadingWidth: 60.0,
title: const Text(
'Currently Playing',
style: TEXT_HEADER,
),
actions: [
IconButton(
icon: const Icon(Icons.play_arrow_outlined),
onPressed: () {
_scrollController.animateTo(
max((queueIndexStream.value ?? 0) - 2, 0) * 72.0,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
},
)
],
centerTitle: true,
),
body: SafeArea(
child: Observer(
builder: (BuildContext context) {
@ -33,35 +62,38 @@ class QueuePage extends StatelessWidget {
switch (queueStream.status) {
case StreamStatus.active:
final int activeIndex = queueIndexStream.value ?? -1;
return CustomScrollView(
controller: _scrollController,
slivers: [
ReorderableSliverList(
delegate: ReorderableSliverChildBuilderDelegate(
(context, int index) {
final Song? song = queueStream.value?[index];
if (song == null)
return Container();
return Dismissible(
key: ValueKey(song.path),
child: AlbumArtListTile(
title: song.title,
subtitle: '${song.artist}',
albumArtPath: song.albumArtPath,
highlight: index == activeIndex,
onTap: () => audioStore.seekToIndex(index),
),
onDismissed: (direction) {
audioStore.removeQueueIndex(index);
},
);
},
childCount: queueStream.value?.length,
),
onReorder: (oldIndex, newIndex) =>
audioStore.moveQueueItem(oldIndex, newIndex),
)
],
return Scrollbar(
child: CustomScrollView(
controller: _scrollController,
slivers: [
ReorderableSliverList(
delegate: ReorderableSliverChildBuilderDelegate(
(context, int index) {
final Song? song = queueStream.value?[index];
if (song == null) return Container();
return Dismissible(
key: ValueKey(song.path),
child: SongListTile(
song: song,
highlight: index == activeIndex,
onTap: () async {
await audioStore.seekToIndex(index);
audioStore.play();
},
onTapMore: () => SongBottomSheet()(song, context),
),
onDismissed: (direction) {
audioStore.removeQueueIndex(index);
},
);
},
childCount: queueStream.value?.length,
),
onReorder: (oldIndex, newIndex) =>
audioStore.moveQueueItem(oldIndex, newIndex),
)
],
),
);
case StreamStatus.waiting:
case StreamStatus.done:

View file

@ -32,20 +32,22 @@ class _SongsPageState extends State<SongsPage> with AutomaticKeepAliveClientMixi
switch (songStream.status) {
case StreamStatus.active:
final List<Song> songs = songStream.value ?? [];
return ListView.separated(
itemCount: songs.length,
itemBuilder: (_, int index) {
final Song song = songs[index];
return SongListTile(
song: song,
showAlbum: true,
subtitle: Subtitle.artistAlbum,
onTap: () => audioStore.playSong(index, songs),
onTapMore: () => SongBottomSheet()(song, context),
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
return Scrollbar(
child: ListView.separated(
itemCount: songs.length,
itemBuilder: (_, int index) {
final Song song = songs[index];
return SongListTile(
song: song,
showAlbum: true,
subtitle: Subtitle.artistAlbum,
onTap: () => audioStore.playSong(index, songs),
onTapMore: () => SongBottomSheet()(song, context),
);
},
separatorBuilder: (BuildContext context, int index) => const SizedBox(
height: 4.0,
),
),
);
case StreamStatus.waiting:

View file

@ -27,8 +27,10 @@ class CurrentlyPlayingHeader extends StatelessWidget {
child: GestureDetector(
onTap: () => onTap(context),
child: Container(
height: 56.0,
color: Colors.transparent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(

View file

@ -7,18 +7,20 @@ import '../utils.dart' as utils;
enum Subtitle { artist, artistAlbum, stats }
class SongListTile extends StatelessWidget {
const SongListTile(
{Key? key,
required this.song,
required this.onTap,
required this.onTapMore,
this.showAlbum = true,
this.subtitle = Subtitle.artist})
: super(key: key);
const SongListTile({
Key? key,
required this.song,
required this.onTap,
required this.onTapMore,
this.highlight = false,
this.showAlbum = true,
this.subtitle = Subtitle.artist,
}) : super(key: key);
final Song song;
final Function onTap;
final Function onTapMore;
final bool highlight;
final bool showAlbum;
final Subtitle subtitle;
@ -90,6 +92,7 @@ class SongListTile extends StatelessWidget {
),
subtitle: subtitleWidget,
onTap: () => onTap(),
tileColor: highlight ? Colors.white10 : Colors.transparent,
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [