added duration to Song entity

This commit is contained in:
Moritz Weber 2020-04-11 14:27:49 +02:00
parent eff0dc29a6
commit 3b7588831c
14 changed files with 90 additions and 20 deletions

View file

@ -2,7 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
class Album extends Equatable {
Album({
const Album({
@required this.title,
@required this.artist,
this.albumArtPath,

View file

@ -1,9 +1,9 @@
import 'package:equatable/equatable.dart';
class Artist extends Equatable {
final String name;
const Artist(this.name);
Artist(this.name);
final String name;
@override
List<Object> get props => [name];

View file

@ -2,11 +2,12 @@ import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
class Song extends Equatable {
Song({
const Song({
@required this.title,
@required this.album,
@required this.artist,
@required this.path,
@required this.duration,
this.trackNumber,
this.albumArtPath,
});
@ -14,8 +15,10 @@ class Song extends Equatable {
final String title;
final String album;
final String artist;
final int trackNumber;
final String path;
/// Duration in milliseconds.
final int duration;
final int trackNumber;
final String albumArtPath;
@override

View file

@ -18,8 +18,8 @@ class _LibraryPageState extends State<LibraryPage> {
length: 3,
child: SafeArea(
child: Column(
children: <Widget>[
const TabBar(
children: const <Widget>[
TabBar(
tabs: <Tab>[
Tab(
text: 'Artists',
@ -35,14 +35,14 @@ class _LibraryPageState extends State<LibraryPage> {
Expanded(
child: TabBarView(
children: <Widget>[
const Center(
Center(
child: Text('Artists'),
),
AlbumsPage(
key: const PageStorageKey('AlbumsPage'),
key: PageStorageKey('AlbumsPage'),
),
SongsPage(
key: const PageStorageKey('SongsPage'),
key: PageStorageKey('SongsPage'),
),
],
),

View file

@ -1,7 +1,7 @@
import 'package:flutter_audio_query/flutter_audio_query.dart';
import 'package:mosh/system/models/song_model.dart';
import '../models/album_model.dart';
import '../models/song_model.dart';
import 'local_music_fetcher_contract.dart';
class LocalMusicFetcherImpl implements LocalMusicFetcher {

View file

@ -2,11 +2,11 @@ import 'dart:io';
import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:mosh/system/models/song_model.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import '../models/album_model.dart';
import '../models/song_model.dart';
import 'music_data_source_contract.dart';
part 'moor_music_data_source.g.dart';
@ -28,6 +28,7 @@ class Songs extends Table {
TextColumn get album => text()();
TextColumn get artist => text()();
TextColumn get path => text()();
IntColumn get duration => integer().nullable()();
TextColumn get albumArtPath => text().nullable()();
IntColumn get trackNumber => integer().nullable()();
}

View file

@ -260,6 +260,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
final String album;
final String artist;
final String path;
final int duration;
final String albumArtPath;
final int trackNumber;
MoorSong(
@ -267,6 +268,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
@required this.album,
@required this.artist,
@required this.path,
this.duration,
this.albumArtPath,
this.trackNumber});
factory MoorSong.fromData(Map<String, dynamic> data, GeneratedDatabase db,
@ -282,6 +284,8 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
artist:
stringType.mapFromDatabaseResponse(data['${effectivePrefix}artist']),
path: stringType.mapFromDatabaseResponse(data['${effectivePrefix}path']),
duration:
intType.mapFromDatabaseResponse(data['${effectivePrefix}duration']),
albumArtPath: stringType
.mapFromDatabaseResponse(data['${effectivePrefix}album_art_path']),
trackNumber: intType
@ -296,6 +300,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
album: serializer.fromJson<String>(json['album']),
artist: serializer.fromJson<String>(json['artist']),
path: serializer.fromJson<String>(json['path']),
duration: serializer.fromJson<int>(json['duration']),
albumArtPath: serializer.fromJson<String>(json['albumArtPath']),
trackNumber: serializer.fromJson<int>(json['trackNumber']),
);
@ -308,6 +313,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
'album': serializer.toJson<String>(album),
'artist': serializer.toJson<String>(artist),
'path': serializer.toJson<String>(path),
'duration': serializer.toJson<int>(duration),
'albumArtPath': serializer.toJson<String>(albumArtPath),
'trackNumber': serializer.toJson<int>(trackNumber),
};
@ -323,6 +329,9 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
artist:
artist == null && nullToAbsent ? const Value.absent() : Value(artist),
path: path == null && nullToAbsent ? const Value.absent() : Value(path),
duration: duration == null && nullToAbsent
? const Value.absent()
: Value(duration),
albumArtPath: albumArtPath == null && nullToAbsent
? const Value.absent()
: Value(albumArtPath),
@ -337,6 +346,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
String album,
String artist,
String path,
int duration,
String albumArtPath,
int trackNumber}) =>
MoorSong(
@ -344,6 +354,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
album: album ?? this.album,
artist: artist ?? this.artist,
path: path ?? this.path,
duration: duration ?? this.duration,
albumArtPath: albumArtPath ?? this.albumArtPath,
trackNumber: trackNumber ?? this.trackNumber,
);
@ -354,6 +365,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
..write('album: $album, ')
..write('artist: $artist, ')
..write('path: $path, ')
..write('duration: $duration, ')
..write('albumArtPath: $albumArtPath, ')
..write('trackNumber: $trackNumber')
..write(')'))
@ -367,8 +379,10 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
album.hashCode,
$mrjc(
artist.hashCode,
$mrjc(path.hashCode,
$mrjc(albumArtPath.hashCode, trackNumber.hashCode))))));
$mrjc(
path.hashCode,
$mrjc(duration.hashCode,
$mrjc(albumArtPath.hashCode, trackNumber.hashCode)))))));
@override
bool operator ==(dynamic other) =>
identical(this, other) ||
@ -377,6 +391,7 @@ class MoorSong extends DataClass implements Insertable<MoorSong> {
other.album == this.album &&
other.artist == this.artist &&
other.path == this.path &&
other.duration == this.duration &&
other.albumArtPath == this.albumArtPath &&
other.trackNumber == this.trackNumber);
}
@ -386,6 +401,7 @@ class SongsCompanion extends UpdateCompanion<MoorSong> {
final Value<String> album;
final Value<String> artist;
final Value<String> path;
final Value<int> duration;
final Value<String> albumArtPath;
final Value<int> trackNumber;
const SongsCompanion({
@ -393,6 +409,7 @@ class SongsCompanion extends UpdateCompanion<MoorSong> {
this.album = const Value.absent(),
this.artist = const Value.absent(),
this.path = const Value.absent(),
this.duration = const Value.absent(),
this.albumArtPath = const Value.absent(),
this.trackNumber = const Value.absent(),
});
@ -401,6 +418,7 @@ class SongsCompanion extends UpdateCompanion<MoorSong> {
@required String album,
@required String artist,
@required String path,
this.duration = const Value.absent(),
this.albumArtPath = const Value.absent(),
this.trackNumber = const Value.absent(),
}) : title = Value(title),
@ -412,6 +430,7 @@ class SongsCompanion extends UpdateCompanion<MoorSong> {
Value<String> album,
Value<String> artist,
Value<String> path,
Value<int> duration,
Value<String> albumArtPath,
Value<int> trackNumber}) {
return SongsCompanion(
@ -419,6 +438,7 @@ class SongsCompanion extends UpdateCompanion<MoorSong> {
album: album ?? this.album,
artist: artist ?? this.artist,
path: path ?? this.path,
duration: duration ?? this.duration,
albumArtPath: albumArtPath ?? this.albumArtPath,
trackNumber: trackNumber ?? this.trackNumber,
);
@ -477,6 +497,18 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> {
);
}
final VerificationMeta _durationMeta = const VerificationMeta('duration');
GeneratedIntColumn _duration;
@override
GeneratedIntColumn get duration => _duration ??= _constructDuration();
GeneratedIntColumn _constructDuration() {
return GeneratedIntColumn(
'duration',
$tableName,
true,
);
}
final VerificationMeta _albumArtPathMeta =
const VerificationMeta('albumArtPath');
GeneratedTextColumn _albumArtPath;
@ -507,7 +539,7 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> {
@override
List<GeneratedColumn> get $columns =>
[title, album, artist, path, albumArtPath, trackNumber];
[title, album, artist, path, duration, albumArtPath, trackNumber];
@override
$SongsTable get asDslTable => this;
@override
@ -542,6 +574,10 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> {
} else if (isInserting) {
context.missing(_pathMeta);
}
if (d.duration.present) {
context.handle(_durationMeta,
duration.isAcceptableValue(d.duration.value, _durationMeta));
}
if (d.albumArtPath.present) {
context.handle(
_albumArtPathMeta,
@ -578,6 +614,9 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> {
if (d.path.present) {
map['path'] = Variable<String, StringType>(d.path.value);
}
if (d.duration.present) {
map['duration'] = Variable<int, IntType>(d.duration.value);
}
if (d.albumArtPath.present) {
map['album_art_path'] =
Variable<String, StringType>(d.albumArtPath.value);

View file

@ -7,12 +7,13 @@ import '../../domain/entities/song.dart';
import '../datasources/moor_music_data_source.dart';
class SongModel extends Song {
SongModel({
const SongModel({
this.id,
@required String title,
@required String album,
@required String artist,
@required String path,
@required int duration,
int trackNumber,
String albumArtPath,
}) : super(
@ -20,6 +21,7 @@ class SongModel extends Song {
album: album,
artist: artist,
path: path,
duration: duration,
trackNumber: trackNumber,
albumArtPath: albumArtPath,
);
@ -29,20 +31,23 @@ class SongModel extends Song {
artist: moorSong.artist,
album: moorSong.album,
path: moorSong.path,
duration: moorSong.duration,
albumArtPath: moorSong.albumArtPath,
trackNumber: moorSong.trackNumber,
);
factory SongModel.fromSongInfo(SongInfo songInfo) {
final String _trackNumber = songInfo.track;
final String trackNumber = songInfo.track;
final String duration = songInfo.duration;
return SongModel(
title: songInfo.title,
artist: songInfo.artist,
albumArtPath: songInfo.albumArtwork,
album: songInfo.album,
path: songInfo.filePath,
trackNumber: _trackNumber == null ? null : int.parse(_trackNumber),
duration: duration == null ? null : int.parse(duration),
albumArtPath: songInfo.albumArtwork,
trackNumber: trackNumber == null ? null : int.parse(trackNumber),
);
}
@ -59,6 +64,7 @@ class SongModel extends Song {
album: mediaItem.album,
artist: mediaItem.artist,
path: mediaItem.id,
duration: mediaItem.duration,
albumArtPath: artUri,
);
}
@ -70,15 +76,17 @@ class SongModel extends Song {
artist: Value(artist),
title: Value(title),
path: Value(path),
duration: Value(duration),
albumArtPath: Value(albumArtPath),
trackNumber: Value(trackNumber),
);
MediaItem toMediaItem() => MediaItem(
id: path,
title: title,
album: album,
artist: artist,
duration: duration,
artUri: 'file://$albumArtPath',
id: path,
);
}

View file

@ -24,6 +24,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
),
@ -32,6 +33,7 @@ void main() {
artist: ARTIST_4,
title: SONG_TITLE_4,
path: PATH_4,
duration: DURATION_4,
albumArtPath: ALBUM_ART_PATH_4,
trackNumber: TRACKNUMBER_4,
),

View file

@ -27,6 +27,7 @@ void main() {
album: ALBUM_TITLE_3,
artist: ARTIST_3,
path: PATH_3,
duration: DURATION_3,
trackNumber: TRACKNUMBER_3,
albumArtPath: ALBUM_ART_PATH_3,
);

View file

@ -17,6 +17,7 @@ void main() {
album: ALBUM_TITLE_3,
artist: ARTIST_3,
path: PATH_3,
duration: DURATION_3,
trackNumber: TRACKNUMBER_3,
albumArtPath: ALBUM_ART_PATH_3,
);
@ -39,6 +40,7 @@ void main() {
artist: Value(ARTIST_3),
title: Value(SONG_TITLE_3),
path: Value(PATH_3),
duration: Value(DURATION_3),
albumArtPath: Value(ALBUM_ART_PATH_3),
trackNumber: Value(TRACKNUMBER_3),
);
@ -48,6 +50,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
);
@ -74,6 +77,7 @@ void main() {
title: SONG_TITLE_3,
album: ALBUM_TITLE_3,
artist: ARTIST_3,
duration: DURATION_3,
artUri: 'file://$ALBUM_ART_PATH_3',
);
@ -82,6 +86,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
);
@ -92,6 +97,7 @@ void main() {
expect(result.artist, expected.artist);
expect(result.title, expected.title);
expect(result.id, expected.id);
expect(result.duration, expected.duration);
expect(result.artUri, expected.artUri);
},
);
@ -107,6 +113,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
);
@ -116,6 +123,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
);
@ -137,6 +145,7 @@ void main() {
when(mockSongInfo.title).thenReturn(SONG_TITLE_3);
when(mockSongInfo.albumArtwork).thenReturn(ALBUM_ART_PATH_3);
when(mockSongInfo.filePath).thenReturn(PATH_3);
when(mockSongInfo.duration).thenReturn(DURATION_3.toString());
when(mockSongInfo.track).thenReturn(TRACKNUMBER_3.toString());
});
@ -149,6 +158,7 @@ void main() {
artist: ARTIST_3,
title: SONG_TITLE_3,
path: PATH_3,
duration: DURATION_3,
albumArtPath: ALBUM_ART_PATH_3,
trackNumber: TRACKNUMBER_3,
);

View file

@ -39,6 +39,7 @@ List<SongModel> setupSongList() => [
album: ALBUM_TITLE_3,
artist: ARTIST_3,
path: PATH_3,
duration: DURATION_3,
trackNumber: TRACKNUMBER_3,
albumArtPath: ALBUM_ART_PATH_3,
),
@ -47,6 +48,7 @@ List<SongModel> setupSongList() => [
album: ALBUM_TITLE_4,
artist: ARTIST_4,
path: PATH_4,
duration: DURATION_4,
trackNumber: TRACKNUMBER_4,
albumArtPath: ALBUM_ART_PATH_4,
),

View file

@ -179,6 +179,7 @@ List<SongModel> setupSongList() => [
album: ALBUM_TITLE_3,
artist: ARTIST_3,
path: PATH_3,
duration: DURATION_3,
trackNumber: TRACKNUMBER_3,
albumArtPath: ALBUM_ART_PATH_3,
),
@ -187,6 +188,7 @@ List<SongModel> setupSongList() => [
album: ALBUM_TITLE_4,
artist: ARTIST_4,
path: PATH_4,
duration: DURATION_4,
trackNumber: TRACKNUMBER_4,
albumArtPath: ALBUM_ART_PATH_4,
),

View file

@ -19,6 +19,7 @@ const String SONG_TITLE_3 = 'Bottom Feeder';
const String ALBUM_TITLE_3 = 'Ire';
const String ARTIST_3 = 'Parkway Drive';
const String PATH_3 = '/music/parkwaydrive/bottom_feeder.mp3';
const int DURATION_3 = 180000;
const String ALBUM_ART_PATH_3 = '/music/parkwaydrive/ire.jpg';
const int TRACKNUMBER_3 = 7;
@ -26,5 +27,6 @@ const String SONG_TITLE_4 = 'Black Flame';
const String ALBUM_TITLE_4 = 'Black Flame';
const String ARTIST_4 = 'Bury Tomorrow';
const String PATH_4 = '/music/burytomorrow/blackflame.mp3';
const int DURATION_4 = 240000;
const String ALBUM_ART_PATH_4 = '/music/parkwaydrive/blackflame.jpg';
const int TRACKNUMBER_4 = 3;