added duration to Song entity
This commit is contained in:
parent
eff0dc29a6
commit
3b7588831c
14 changed files with 90 additions and 20 deletions
|
@ -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,
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
|
|
|
@ -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;
|
Loading…
Add table
Reference in a new issue