highlighted songs per artist
This commit is contained in:
parent
caae3bf8dd
commit
5f58570bc2
9 changed files with 115 additions and 5 deletions
|
@ -41,15 +41,11 @@ class AudioPlayerActor {
|
||||||
void _handlePosition(Duration position, Song song) {
|
void _handlePosition(Duration position, Song song) {
|
||||||
if (song == null || position == null) return;
|
if (song == null || position == null) return;
|
||||||
|
|
||||||
print('HANDLE POSITION');
|
|
||||||
|
|
||||||
final int pos = position.inMilliseconds;
|
final int pos = position.inMilliseconds;
|
||||||
|
|
||||||
if (pos < song.duration * 0.05) {
|
if (pos < song.duration * 0.05) {
|
||||||
print('COUNT -> TRUE');
|
|
||||||
_countSongPlayback = true;
|
_countSongPlayback = true;
|
||||||
} else if (pos > song.duration * 0.95 && _countSongPlayback) {
|
} else if (pos > song.duration * 0.95 && _countSongPlayback) {
|
||||||
print('INCREMENT PLAY COUNT: ${song.title}');
|
|
||||||
_countSongPlayback = false;
|
_countSongPlayback = false;
|
||||||
_incrementPlayCount(song);
|
_incrementPlayCount(song);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ abstract class MusicDataInfoRepository {
|
||||||
Stream<List<Song>> get songStream;
|
Stream<List<Song>> get songStream;
|
||||||
Stream<List<Song>> getAlbumSongStream(Album album);
|
Stream<List<Song>> getAlbumSongStream(Album album);
|
||||||
Stream<List<Song>> getArtistSongStream(Artist artist);
|
Stream<List<Song>> getArtistSongStream(Artist artist);
|
||||||
|
Stream<List<Song>> getArtistHighlightedSongStream(Artist artist);
|
||||||
|
|
||||||
Stream<List<Album>> get albumStream;
|
Stream<List<Album>> get albumStream;
|
||||||
Stream<List<Album>> getArtistAlbumStream(Artist artist);
|
Stream<List<Album>> getArtistAlbumStream(Artist artist);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import '../state/music_data_store.dart';
|
||||||
import '../theming.dart';
|
import '../theming.dart';
|
||||||
import '../widgets/artist_albums.dart';
|
import '../widgets/artist_albums.dart';
|
||||||
import '../widgets/artist_header.dart';
|
import '../widgets/artist_header.dart';
|
||||||
|
import '../widgets/artist_highlighted_songs.dart';
|
||||||
import 'album_details_page.dart';
|
import 'album_details_page.dart';
|
||||||
|
|
||||||
class ArtistDetailsPage extends StatelessWidget {
|
class ArtistDetailsPage extends StatelessWidget {
|
||||||
|
@ -40,6 +41,34 @@ class ArtistDetailsPage extends StatelessWidget {
|
||||||
onPressed: () => audioStore.shuffleArtist(artist),
|
onPressed: () => audioStore.shuffleArtist(artist),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: HORIZONTAL_PADDING + 2,
|
||||||
|
right: HORIZONTAL_PADDING + 2,
|
||||||
|
bottom: 4.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Highlights',
|
||||||
|
style: TEXT_HEADER,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: HORIZONTAL_PADDING,
|
||||||
|
vertical: 4.0,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
height: 1.0,
|
||||||
|
color: Colors.white10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ArtistHighlightedSongs(songs: musicDataStore.artistHighlightedSongStream.value),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
[
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: HORIZONTAL_PADDING + 2,
|
left: HORIZONTAL_PADDING + 2,
|
||||||
|
|
|
@ -31,6 +31,7 @@ class _ArtistsPageState extends State<ArtistsPage> with AutomaticKeepAliveClient
|
||||||
title: Text(artist.name),
|
title: Text(artist.name),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
musicDataStore.fetchAlbumsFromArtist(artist);
|
musicDataStore.fetchAlbumsFromArtist(artist);
|
||||||
|
musicDataStore.fetchHighlightedSongsFromArtist(artist);
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute<Widget>(
|
MaterialPageRoute<Widget>(
|
||||||
|
|
|
@ -68,6 +68,9 @@ abstract class _MusicDataStore with Store {
|
||||||
@observable
|
@observable
|
||||||
ObservableStream<List<Album>> artistAlbumStream;
|
ObservableStream<List<Album>> artistAlbumStream;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ObservableStream<List<Song>> artistHighlightedSongStream;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool isUpdatingDatabase = false;
|
bool isUpdatingDatabase = false;
|
||||||
|
|
||||||
|
@ -92,12 +95,20 @@ abstract class _MusicDataStore with Store {
|
||||||
_musicDataInfoRepository.getAlbumSongStream(album).asObservable(initialValue: []);
|
_musicDataInfoRepository.getAlbumSongStream(album).asObservable(initialValue: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: das hier ist komplett bescheuert... brauchen einen eigenen Store für die ArtistDetailsPage
|
||||||
@action
|
@action
|
||||||
Future<void> fetchAlbumsFromArtist(Artist artist) async {
|
Future<void> fetchAlbumsFromArtist(Artist artist) async {
|
||||||
artistAlbumStream =
|
artistAlbumStream =
|
||||||
_musicDataInfoRepository.getArtistAlbumStream(artist).asObservable(initialValue: []);
|
_musicDataInfoRepository.getArtistAlbumStream(artist).asObservable(initialValue: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> fetchHighlightedSongsFromArtist(Artist artist) async {
|
||||||
|
artistHighlightedSongStream = _musicDataInfoRepository
|
||||||
|
.getArtistHighlightedSongStream(artist)
|
||||||
|
.asObservable(initialValue: []);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> setSongBlocked(Song song, bool blocked) => _setSongBlocked(song, blocked);
|
Future<void> setSongBlocked(Song song, bool blocked) => _setSongBlocked(song, blocked);
|
||||||
|
|
||||||
Future<void> toggleNextSongLink(Song song) async {
|
Future<void> toggleNextSongLink(Song song) async {
|
||||||
|
|
|
@ -93,6 +93,23 @@ mixin _$MusicDataStore on _MusicDataStore, Store {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final _$artistHighlightedSongStreamAtom =
|
||||||
|
Atom(name: '_MusicDataStore.artistHighlightedSongStream');
|
||||||
|
|
||||||
|
@override
|
||||||
|
ObservableStream<List<Song>> get artistHighlightedSongStream {
|
||||||
|
_$artistHighlightedSongStreamAtom.reportRead();
|
||||||
|
return super.artistHighlightedSongStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
set artistHighlightedSongStream(ObservableStream<List<Song>> value) {
|
||||||
|
_$artistHighlightedSongStreamAtom
|
||||||
|
.reportWrite(value, super.artistHighlightedSongStream, () {
|
||||||
|
super.artistHighlightedSongStream = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final _$isUpdatingDatabaseAtom =
|
final _$isUpdatingDatabaseAtom =
|
||||||
Atom(name: '_MusicDataStore.isUpdatingDatabase');
|
Atom(name: '_MusicDataStore.isUpdatingDatabase');
|
||||||
|
|
||||||
|
@ -135,6 +152,15 @@ mixin _$MusicDataStore on _MusicDataStore, Store {
|
||||||
.run(() => super.fetchAlbumsFromArtist(artist));
|
.run(() => super.fetchAlbumsFromArtist(artist));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final _$fetchHighlightedSongsFromArtistAsyncAction =
|
||||||
|
AsyncAction('_MusicDataStore.fetchHighlightedSongsFromArtist');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> fetchHighlightedSongsFromArtist(Artist artist) {
|
||||||
|
return _$fetchHighlightedSongsFromArtistAsyncAction
|
||||||
|
.run(() => super.fetchHighlightedSongsFromArtist(artist));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return '''
|
return '''
|
||||||
|
@ -143,6 +169,7 @@ albumStream: ${albumStream},
|
||||||
artistStream: ${artistStream},
|
artistStream: ${artistStream},
|
||||||
albumSongStream: ${albumSongStream},
|
albumSongStream: ${albumSongStream},
|
||||||
artistAlbumStream: ${artistAlbumStream},
|
artistAlbumStream: ${artistAlbumStream},
|
||||||
|
artistHighlightedSongStream: ${artistHighlightedSongStream},
|
||||||
isUpdatingDatabase: ${isUpdatingDatabase},
|
isUpdatingDatabase: ${isUpdatingDatabase},
|
||||||
sortedArtistAlbums: ${sortedArtistAlbums}
|
sortedArtistAlbums: ${sortedArtistAlbums}
|
||||||
''';
|
''';
|
||||||
|
|
27
lib/presentation/widgets/artist_highlighted_songs.dart
Normal file
27
lib/presentation/widgets/artist_highlighted_songs.dart
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/song.dart';
|
||||||
|
import 'song_list_tile.dart';
|
||||||
|
|
||||||
|
class ArtistHighlightedSongs extends StatelessWidget {
|
||||||
|
const ArtistHighlightedSongs({Key key, this.songs, this.onTap, this.onTapPlay}) : super(key: key);
|
||||||
|
|
||||||
|
final List<Song> songs;
|
||||||
|
final Function onTap;
|
||||||
|
final Function onTapPlay;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(_, int index) {
|
||||||
|
final Song song = songs[index];
|
||||||
|
return SongListTile(
|
||||||
|
song: song
|
||||||
|
);
|
||||||
|
},
|
||||||
|
childCount: songs.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import '../../domain/entities/song.dart';
|
||||||
import '../utils.dart' as utils;
|
import '../utils.dart' as utils;
|
||||||
|
|
||||||
class SongListTile extends StatelessWidget {
|
class SongListTile extends StatelessWidget {
|
||||||
const SongListTile({Key key, this.song, this.onTap, this.inAlbum, this.onTapMore})
|
const SongListTile({Key key, this.song, this.onTap, this.inAlbum = false, this.onTapMore})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
final Song song;
|
final Song song;
|
||||||
|
|
|
@ -52,6 +52,13 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
||||||
Stream<List<Song>> getArtistSongStream(Artist artist) =>
|
Stream<List<Song>> getArtistSongStream(Artist artist) =>
|
||||||
_musicDataSource.getArtistSongStream(artist as ArtistModel);
|
_musicDataSource.getArtistSongStream(artist as ArtistModel);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<List<Song>> getArtistHighlightedSongStream(Artist artist) {
|
||||||
|
return _musicDataSource
|
||||||
|
.getArtistSongStream(artist as ArtistModel)
|
||||||
|
.map((event) => _sortHighlightedSongs(event).take(5).toList());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<List<Album>> getArtistAlbumStream(Artist artist) =>
|
Stream<List<Album>> getArtistAlbumStream(Artist artist) =>
|
||||||
_musicDataSource.getArtistAlbumStream(artist as ArtistModel);
|
_musicDataSource.getArtistAlbumStream(artist as ArtistModel);
|
||||||
|
@ -137,4 +144,15 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
||||||
// TODO: implement resetSkipCount
|
// TODO: implement resetSkipCount
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Song> _sortHighlightedSongs(List<Song> songs) {
|
||||||
|
return songs
|
||||||
|
..sort(
|
||||||
|
(a, b) {
|
||||||
|
final r = -a.likeCount.compareTo(b.likeCount);
|
||||||
|
if (r != 0) return r;
|
||||||
|
return -a.playCount.compareTo(b.playCount);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue