Restore original swingmusic_mobile folder from 9f1623b

This commit is contained in:
Tomas Dvorak
2026-03-18 19:43:40 +01:00
parent e5c7c0ca16
commit 6ca75aedf3
159 changed files with 18429 additions and 0 deletions
@@ -0,0 +1,236 @@
import 'package:equatable/equatable.dart';
import 'track_model.dart';
class AlbumModel extends Equatable {
final List<ArtistModel> albumartists;
final String albumhash;
final List<String> artisthashes;
final String baseTitle;
final String color;
final int createdDate;
final int date;
final int duration;
final List<GenreModel> genres;
final List<String> genrehashes;
final String originalTitle;
final String title;
final int trackcount;
final int lastplayed;
final int playcount;
final int playduration;
final Map<String, dynamic> extra;
final String pathhash;
final int id;
final String type;
final String image;
final double score;
final List<String> versions;
final List<int> favUserids;
final String weakHash;
final bool isFavorite;
const AlbumModel({
required this.albumartists,
required this.albumhash,
required this.artisthashes,
required this.baseTitle,
this.color = '#6750A4',
required this.createdDate,
required this.date,
required this.duration,
required this.genres,
required this.genrehashes,
this.originalTitle = '',
required this.title,
required this.trackcount,
this.lastplayed = 0,
this.playcount = 0,
this.playduration = 0,
this.extra = const {},
this.pathhash = '',
this.id = -1,
this.type = 'album',
this.image = '',
this.score = 0.0,
this.versions = const [],
this.favUserids = const [],
this.weakHash = '',
this.isFavorite = false,
});
AlbumModel copyWith({
List<ArtistModel>? albumartists,
String? albumhash,
List<String>? artisthashes,
String? baseTitle,
String? color,
int? createdDate,
int? date,
int? duration,
List<GenreModel>? genres,
List<String>? genrehashes,
String? originalTitle,
String? title,
int? trackcount,
int? lastplayed,
int? playcount,
int? playduration,
Map<String, dynamic>? extra,
String? pathhash,
int? id,
String? type,
String? image,
double? score,
List<String>? versions,
List<int>? favUserids,
String? weakHash,
bool? isFavorite,
}) {
return AlbumModel(
albumartists: albumartists ?? this.albumartists,
albumhash: albumhash ?? this.albumhash,
artisthashes: artisthashes ?? this.artisthashes,
baseTitle: baseTitle ?? this.baseTitle,
color: color ?? this.color,
createdDate: createdDate ?? this.createdDate,
date: date ?? this.date,
duration: duration ?? this.duration,
genres: genres ?? this.genres,
genrehashes: genrehashes ?? this.genrehashes,
originalTitle: originalTitle ?? this.originalTitle,
title: title ?? this.title,
trackcount: trackcount ?? this.trackcount,
lastplayed: lastplayed ?? this.lastplayed,
playcount: playcount ?? this.playcount,
playduration: playduration ?? this.playduration,
extra: extra ?? this.extra,
pathhash: pathhash ?? this.pathhash,
id: id ?? this.id,
type: type ?? this.type,
image: image ?? this.image,
score: score ?? this.score,
versions: versions ?? this.versions,
favUserids: favUserids ?? this.favUserids,
weakHash: weakHash ?? this.weakHash,
isFavorite: isFavorite ?? this.isFavorite,
);
}
@override
List<Object?> get props => [
albumartists,
albumhash,
artisthashes,
baseTitle,
color,
createdDate,
date,
duration,
genres,
genrehashes,
originalTitle,
title,
trackcount,
lastplayed,
playcount,
playduration,
extra,
pathhash,
id,
type,
image,
score,
versions,
favUserids,
weakHash,
isFavorite,
];
String get displayTitle => originalTitle.isNotEmpty ? originalTitle : title;
String get artistNames => albumartists.map((artist) => artist.name).join(', ');
String get durationFormatted {
final hours = duration ~/ 3600;
final minutes = (duration % 3600) ~/ 60;
final seconds = duration % 60;
if (hours > 0) {
return '${hours}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
} else {
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
}
String get year {
if (date == 0) return '';
final dateTime = DateTime.fromMillisecondsSinceEpoch(date * 1000);
return dateTime.year.toString();
}
factory AlbumModel.fromJson(Map<String, dynamic> json) {
return AlbumModel(
albumartists: (json['albumartists'] as List<dynamic>?)
?.map((artist) => ArtistModel.fromJson(artist))
.toList() ?? [],
albumhash: json['albumhash'] ?? '',
artisthashes: List<String>.from(json['artisthashes'] ?? []),
baseTitle: json['base_title'] ?? '',
color: json['color'] ?? '#6750A4',
createdDate: json['created_date'] ?? 0,
date: json['date'] ?? 0,
duration: json['duration'] ?? 0,
genres: (json['genres'] as List<dynamic>?)
?.map((genre) => GenreModel.fromJson(genre))
.toList() ?? [],
genrehashes: List<String>.from(json['genrehashes'] ?? []),
originalTitle: json['original_title'] ?? '',
title: json['title'] ?? '',
trackcount: json['trackcount'] ?? 0,
lastplayed: json['lastplayed'] ?? 0,
playcount: json['playcount'] ?? 0,
playduration: json['playduration'] ?? 0,
extra: json['extra'] ?? {},
pathhash: json['pathhash'] ?? '',
id: json['id'] ?? -1,
type: json['type'] ?? 'album',
image: json['image'] ?? '',
score: (json['score'] ?? 0).toDouble(),
versions: List<String>.from(json['versions'] ?? []),
favUserids: List<int>.from(json['fav_userids'] ?? []),
weakHash: json['weak_hash'] ?? '',
isFavorite: json['is_favorite'] ?? false,
);
}
Map<String, dynamic> toJson() {
return {
'albumartists': albumartists.map((artist) => artist.toJson()).toList(),
'albumhash': albumhash,
'artisthashes': artisthashes,
'base_title': baseTitle,
'color': color,
'created_date': createdDate,
'date': date,
'duration': duration,
'genres': genres.map((genre) => genre.toJson()).toList(),
'genrehashes': genrehashes,
'original_title': originalTitle,
'title': title,
'trackcount': trackcount,
'lastplayed': lastplayed,
'playcount': playcount,
'playduration': playduration,
'extra': extra,
'pathhash': pathhash,
'id': id,
'type': type,
'image': image,
'score': score,
'versions': versions,
'fav_userids': favUserids,
'weak_hash': weakHash,
'is_favorite': isFavorite,
};
}
}
@@ -0,0 +1,96 @@
import 'package:equatable/equatable.dart';
import 'album_model.dart';
import 'track_model.dart';
class ArtistModel extends Equatable {
final String name;
final String artisthash;
final String image;
final int trackcount;
final int albumcount;
final int duration;
final int lastplayed;
final int playcount;
final int playduration;
final List<int> favUserids;
final bool isFavorite;
final List<AlbumModel> albums;
final List<TrackModel> tracks;
const ArtistModel({
required this.name,
required this.artisthash,
this.image = '',
this.trackcount = 0,
this.albumcount = 0,
this.duration = 0,
this.lastplayed = 0,
this.playcount = 0,
this.playduration = 0,
this.favUserids = const [],
this.isFavorite = false,
this.albums = const [],
this.tracks = const [],
});
ArtistModel copyWith({
String? name,
String? artisthash,
String? image,
int? trackcount,
int? albumcount,
int? duration,
int? lastplayed,
int? playcount,
int? playduration,
List<int>? favUserids,
bool? isFavorite,
List<AlbumModel>? albums,
List<TrackModel>? tracks,
}) {
return ArtistModel(
name: name ?? this.name,
artisthash: artisthash ?? this.artisthash,
image: image ?? this.image,
trackcount: trackcount ?? this.trackcount,
albumcount: albumcount ?? this.albumcount,
duration: duration ?? this.duration,
lastplayed: lastplayed ?? this.lastplayed,
playcount: playcount ?? this.playcount,
playduration: playduration ?? this.playduration,
favUserids: favUserids ?? this.favUserids,
isFavorite: isFavorite ?? this.isFavorite,
albums: albums ?? this.albums,
tracks: tracks ?? this.tracks,
);
}
@override
List<Object?> get props => [
name,
artisthash,
image,
trackcount,
albumcount,
duration,
lastplayed,
playcount,
playduration,
favUserids,
isFavorite,
albums,
tracks,
];
String get durationFormatted {
final hours = duration ~/ 3600;
final minutes = (duration % 3600) ~/ 60;
final seconds = duration % 60;
if (hours > 0) {
return '${hours}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
} else {
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
}
}
@@ -0,0 +1,123 @@
import 'package:equatable/equatable.dart';
import 'track_model.dart';
class FolderModel extends Equatable {
final String name;
final String path;
final String? parent;
final int trackcount;
final List<FolderModel> subfolders;
final List<TrackModel> tracks;
final String? image;
final bool isFavorite;
const FolderModel({
required this.name,
required this.path,
this.parent,
this.trackcount = 0,
this.subfolders = const [],
this.tracks = const [],
this.image,
this.isFavorite = false,
});
FolderModel copyWith({
String? name,
String? path,
String? parent,
int? trackcount,
List<FolderModel>? subfolders,
List<TrackModel>? tracks,
String? image,
bool? isFavorite,
}) {
return FolderModel(
name: name ?? this.name,
path: path ?? this.path,
parent: parent ?? this.parent,
trackcount: trackcount ?? this.trackcount,
subfolders: subfolders ?? this.subfolders,
tracks: tracks ?? this.tracks,
image: image ?? this.image,
isFavorite: isFavorite ?? this.isFavorite,
);
}
factory FolderModel.fromJson(Map<String, dynamic> json) {
return FolderModel(
name: json['name'] ?? '',
path: json['path'] ?? '',
parent: json['parent'],
trackcount: json['trackcount'] ?? 0,
subfolders: (json['subfolders'] as List<dynamic>?)
?.map((folder) => FolderModel.fromJson(folder))
.toList() ?? [],
tracks: (json['tracks'] as List<dynamic>?)
?.map((track) => TrackModel.fromJson(track))
.toList() ?? [],
image: json['image'],
isFavorite: json['is_favorite'] ?? false,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'path': path,
'parent': parent,
'trackcount': trackcount,
'subfolders': subfolders.map((folder) => folder.toJson()).toList(),
'tracks': tracks.map((track) => track.toJson()).toList(),
'image': image,
'is_favorite': isFavorite,
};
}
@override
List<Object?> get props => [
name,
path,
parent,
trackcount,
subfolders,
tracks,
image,
isFavorite,
];
}
class FoldersAndTracksModel extends Equatable {
final List<FolderModel> folders;
final List<TrackModel> tracks;
final String currentPath;
const FoldersAndTracksModel({
required this.folders,
required this.tracks,
required this.currentPath,
});
factory FoldersAndTracksModel.fromJson(Map<String, dynamic> json) {
return FoldersAndTracksModel(
folders: (json['folders'] as List<dynamic>?)
?.map((folder) => FolderModel.fromJson(folder))
.toList() ?? [],
tracks: (json['tracks'] as List<dynamic>?)
?.map((track) => TrackModel.fromJson(track))
.toList() ?? [],
currentPath: json['current_path'] ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'folders': folders.map((folder) => folder.toJson()).toList(),
'tracks': tracks.map((track) => track.toJson()).toList(),
'current_path': currentPath,
};
}
@override
List<Object?> get props => [folders, tracks, currentPath];
}
@@ -0,0 +1,152 @@
import 'package:equatable/equatable.dart';
import 'track_model.dart';
class PlaylistModel extends Equatable {
final String id;
final String name;
final String description;
final String image;
final List<TrackModel> tracks;
final int trackcount;
final int duration;
final DateTime createdDate;
final DateTime lastModified;
final bool isPublic;
final bool isCollaborative;
final String owner;
final List<String> collaboratorIds;
final Map<String, dynamic> extra;
const PlaylistModel({
required this.id,
required this.name,
this.description = '',
this.image = '',
this.tracks = const [],
this.trackcount = 0,
this.duration = 0,
required this.createdDate,
required this.lastModified,
this.isPublic = false,
this.isCollaborative = false,
this.owner = '',
this.collaboratorIds = const [],
this.extra = const {},
});
PlaylistModel copyWith({
String? id,
String? name,
String? description,
String? image,
List<TrackModel>? tracks,
int? trackcount,
int? duration,
DateTime? createdDate,
DateTime? lastModified,
bool? isPublic,
bool? isCollaborative,
String? owner,
List<String>? collaboratorIds,
Map<String, dynamic>? extra,
}) {
return PlaylistModel(
id: id ?? this.id,
name: name ?? this.name,
description: description ?? this.description,
image: image ?? this.image,
tracks: tracks ?? this.tracks,
trackcount: trackcount ?? this.trackcount,
duration: duration ?? this.duration,
createdDate: createdDate ?? this.createdDate,
lastModified: lastModified ?? this.lastModified,
isPublic: isPublic ?? this.isPublic,
isCollaborative: isCollaborative ?? this.isCollaborative,
owner: owner ?? this.owner,
collaboratorIds: collaboratorIds ?? this.collaboratorIds,
extra: extra ?? this.extra,
);
}
@override
List<Object?> get props => [
id,
name,
description,
image,
tracks,
trackcount,
duration,
createdDate,
lastModified,
isPublic,
isCollaborative,
owner,
collaboratorIds,
extra,
];
String get durationFormatted {
final hours = duration ~/ 3600;
final minutes = (duration % 3600) ~/ 60;
final seconds = duration % 60;
if (hours > 0) {
return '${hours}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
} else {
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
}
String get createdDateFormatted {
return '${createdDate.day.toString().padLeft(2, '0')}/${createdDate.month.toString().padLeft(2, '0')}/${createdDate.year}';
}
String get lastModifiedFormatted {
return '${lastModified.day.toString().padLeft(2, '0')}/${lastModified.month.toString().padLeft(2, '0')}/${lastModified.year}';
}
factory PlaylistModel.fromJson(Map<String, dynamic> json) {
return PlaylistModel(
id: json['id'] ?? '',
name: json['name'] ?? '',
description: json['description'] ?? '',
image: json['image'] ?? '',
tracks: (json['tracks'] as List<dynamic>?)
?.map((track) => TrackModel.fromJson(track))
.toList() ?? [],
trackcount: json['trackcount'] ?? 0,
duration: json['duration'] ?? 0,
createdDate: json['created_date'] != null
? DateTime.parse(json['created_date'])
: DateTime.now(),
lastModified: json['last_modified'] != null
? DateTime.parse(json['last_modified'])
: DateTime.now(),
isPublic: json['is_public'] ?? false,
isCollaborative: json['is_collaborative'] ?? false,
owner: json['owner'] ?? '',
collaboratorIds: List<String>.from(json['collaborator_ids'] ?? []),
extra: json['extra'] ?? {},
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'description': description,
'image': image,
'tracks': tracks.map((track) => track.toJson()).toList(),
'trackcount': trackcount,
'duration': duration,
'created_date': createdDate.toIso8601String(),
'last_modified': lastModified.toIso8601String(),
'is_public': isPublic,
'is_collaborative': isCollaborative,
'owner': owner,
'collaborator_ids': collaboratorIds,
'extra': extra,
};
}
}
@@ -0,0 +1,153 @@
import 'package:equatable/equatable.dart';
import 'album_model.dart';
import 'folder_model.dart';
import 'playlist_model.dart';
import 'track_model.dart';
class SearchResultsModel extends Equatable {
final List<TrackModel> tracks;
final List<AlbumModel> albums;
final List<ArtistModel> artists;
final List<FolderModel> folders;
final List<PlaylistModel> playlists;
const SearchResultsModel({
this.tracks = const [],
this.albums = const [],
this.artists = const [],
this.folders = const [],
this.playlists = const [],
});
SearchResultsModel copyWith({
List<TrackModel>? tracks,
List<AlbumModel>? albums,
List<ArtistModel>? artists,
List<FolderModel>? folders,
List<PlaylistModel>? playlists,
}) {
return SearchResultsModel(
tracks: tracks ?? this.tracks,
albums: albums ?? this.albums,
artists: artists ?? this.artists,
folders: folders ?? this.folders,
playlists: playlists ?? this.playlists,
);
}
factory SearchResultsModel.fromJson(Map<String, dynamic> json) {
return SearchResultsModel(
tracks: (json['tracks'] as List<dynamic>?)
?.map((track) => TrackModel.fromJson(track))
.toList() ?? [],
albums: (json['albums'] as List<dynamic>?)
?.map((album) => AlbumModel.fromJson(album))
.toList() ?? [],
artists: (json['artists'] as List<dynamic>?)
?.map((artist) => ArtistModel.fromJson(artist))
.toList() ?? [],
folders: (json['folders'] as List<dynamic>?)
?.map((folder) => FolderModel.fromJson(folder))
.toList() ?? [],
playlists: (json['playlists'] as List<dynamic>?)
?.map((playlist) => PlaylistModel.fromJson(playlist))
.toList() ?? [],
);
}
Map<String, dynamic> toJson() {
return {
'tracks': tracks.map((track) => track.toJson()).toList(),
'albums': albums.map((album) => album.toJson()).toList(),
'artists': artists.map((artist) => artist.toJson()).toList(),
'folders': folders.map((folder) => folder.toJson()).toList(),
'playlists': playlists.map((playlist) => playlist.toJson()).toList(),
};
}
bool get isEmpty =>
tracks.isEmpty &&
albums.isEmpty &&
artists.isEmpty &&
folders.isEmpty &&
playlists.isEmpty;
bool get isNotEmpty => !isEmpty;
@override
List<Object?> get props => [
tracks,
albums,
artists,
folders,
playlists,
];
}
class TopSearchResultsModel extends Equatable {
final List<TopResultItemModel> topResults;
final SearchResultsModel allResults;
const TopSearchResultsModel({
required this.topResults,
required this.allResults,
});
factory TopSearchResultsModel.fromJson(Map<String, dynamic> json) {
return TopSearchResultsModel(
topResults: (json['top_results'] as List<dynamic>?)
?.map((item) => TopResultItemModel.fromJson(item))
.toList() ?? [],
allResults: SearchResultsModel.fromJson(json['all_results'] ?? {}),
);
}
Map<String, dynamic> toJson() {
return {
'top_results': topResults.map((item) => item.toJson()).toList(),
'all_results': allResults.toJson(),
};
}
@override
List<Object?> get props => [topResults, allResults];
}
class TopResultItemModel extends Equatable {
final String type; // 'track', 'album', 'artist', 'folder', 'playlist'
final String title;
final String subtitle;
final String? image;
final dynamic data; // The actual model object
const TopResultItemModel({
required this.type,
required this.title,
required this.subtitle,
this.image,
this.data,
});
factory TopResultItemModel.fromJson(Map<String, dynamic> json) {
return TopResultItemModel(
type: json['type'] ?? '',
title: json['title'] ?? '',
subtitle: json['subtitle'] ?? '',
image: json['image'],
data: json['data'],
);
}
Map<String, dynamic> toJson() {
return {
'type': type,
'title': title,
'subtitle': subtitle,
'image': image,
'data': data,
};
}
@override
List<Object?> get props => [type, title, subtitle, image, data];
}
@@ -0,0 +1,15 @@
class SearchSuggestion {
final String id;
final String title;
final String? imageUrl;
final String type; // 'track', 'album', 'artist', 'playlist'
final dynamic data;
SearchSuggestion({
required this.id,
required this.title,
this.imageUrl,
required this.type,
this.data,
});
}
@@ -0,0 +1,316 @@
import 'package:equatable/equatable.dart';
class TrackModel extends Equatable {
final int id;
final String title;
final String album;
final String originalTitle;
final String albumhash;
final String originalAlbum;
final List<ArtistModel> artists;
final List<ArtistModel> albumartists;
final List<String> artisthashes;
final int track;
final int disc;
final int duration;
final int bitrate;
final String filepath;
final String folder;
final List<GenreModel> genres;
final List<String> genrehashes;
final String copyright;
final int date;
final int lastModified;
final String trackhash;
final String image;
final String weakHash;
final Map<String, dynamic> extra;
final int lastplayed;
final int playcount;
final int playduration;
final bool explicit;
final List<int> favUserids;
final bool isFavorite;
final double score;
const TrackModel({
required this.id,
required this.title,
required this.album,
this.originalTitle = '',
required this.albumhash,
this.originalAlbum = '',
required this.artists,
required this.albumartists,
required this.artisthashes,
required this.track,
required this.disc,
required this.duration,
required this.bitrate,
required this.filepath,
required this.folder,
required this.genres,
required this.genrehashes,
this.copyright = '',
required this.date,
required this.lastModified,
required this.trackhash,
this.image = '',
this.weakHash = '',
required this.extra,
this.lastplayed = 0,
this.playcount = 0,
this.playduration = 0,
this.explicit = false,
this.favUserids = const [],
this.isFavorite = false,
this.score = 0.0,
});
TrackModel copyWith({
int? id,
String? title,
String? album,
String? originalTitle,
String? albumhash,
String? originalAlbum,
List<ArtistModel>? artists,
List<ArtistModel>? albumartists,
List<String>? artisthashes,
int? track,
int? disc,
int? duration,
int? bitrate,
String? filepath,
String? folder,
List<GenreModel>? genres,
List<String>? genrehashes,
String? copyright,
int? date,
int? lastModified,
String? trackhash,
String? image,
String? weakHash,
Map<String, dynamic>? extra,
int? lastplayed,
int? playcount,
int? playduration,
bool? explicit,
List<int>? favUserids,
bool? isFavorite,
double? score,
}) {
return TrackModel(
id: id ?? this.id,
title: title ?? this.title,
album: album ?? this.album,
originalTitle: originalTitle ?? this.originalTitle,
albumhash: albumhash ?? this.albumhash,
originalAlbum: originalAlbum ?? this.originalAlbum,
artists: artists ?? this.artists,
albumartists: albumartists ?? this.albumartists,
artisthashes: artisthashes ?? this.artisthashes,
track: track ?? this.track,
disc: disc ?? this.disc,
duration: duration ?? this.duration,
bitrate: bitrate ?? this.bitrate,
filepath: filepath ?? this.filepath,
folder: folder ?? this.folder,
genres: genres ?? this.genres,
genrehashes: genrehashes ?? this.genrehashes,
copyright: copyright ?? this.copyright,
date: date ?? this.date,
lastModified: lastModified ?? this.lastModified,
trackhash: trackhash ?? this.trackhash,
image: image ?? this.image,
weakHash: weakHash ?? this.weakHash,
extra: extra ?? this.extra,
lastplayed: lastplayed ?? this.lastplayed,
playcount: playcount ?? this.playcount,
playduration: playduration ?? this.playduration,
explicit: explicit ?? this.explicit,
favUserids: favUserids ?? this.favUserids,
isFavorite: isFavorite ?? this.isFavorite,
score: score ?? this.score,
);
}
@override
List<Object?> get props => [
id,
title,
album,
originalTitle,
albumhash,
originalAlbum,
artists,
albumartists,
artisthashes,
track,
disc,
duration,
bitrate,
filepath,
folder,
genres,
genrehashes,
copyright,
date,
lastModified,
trackhash,
image,
weakHash,
extra,
lastplayed,
playcount,
playduration,
explicit,
favUserids,
isFavorite,
score,
];
String get displayTitle => originalTitle.isNotEmpty ? originalTitle : title;
String get displayAlbum => originalAlbum.isNotEmpty ? originalAlbum : album;
String get artistNames => artists.map((artist) => artist.name).join(', ');
String get durationFormatted {
final minutes = duration ~/ 60;
final seconds = duration % 60;
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
factory TrackModel.fromJson(Map<String, dynamic> json) {
return TrackModel(
id: json['id'] ?? 0,
title: json['title'] ?? '',
album: json['album'] ?? '',
originalTitle: json['original_title'] ?? '',
albumhash: json['albumhash'] ?? '',
originalAlbum: json['original_album'] ?? '',
artists: (json['artists'] as List<dynamic>?)
?.map((artist) => ArtistModel.fromJson(artist))
.toList() ?? [],
albumartists: (json['albumartists'] as List<dynamic>?)
?.map((artist) => ArtistModel.fromJson(artist))
.toList() ?? [],
artisthashes: List<String>.from(json['artisthashes'] ?? []),
track: json['track'] ?? 0,
disc: json['disc'] ?? 1,
duration: json['duration'] ?? 0,
bitrate: json['bitrate'] ?? 0,
filepath: json['filepath'] ?? '',
folder: json['folder'] ?? '',
genres: (json['genres'] as List<dynamic>?)
?.map((genre) => GenreModel.fromJson(genre))
.toList() ?? [],
genrehashes: List<String>.from(json['genrehashes'] ?? []),
copyright: json['copyright'] ?? '',
date: json['date'] ?? 0,
lastModified: json['last_modified'] ?? 0,
trackhash: json['trackhash'] ?? '',
image: json['image'] ?? '',
weakHash: json['weak_hash'] ?? '',
extra: json['extra'] ?? {},
lastplayed: json['lastplayed'] ?? 0,
playcount: json['playcount'] ?? 0,
playduration: json['playduration'] ?? 0,
explicit: json['explicit'] ?? false,
favUserids: List<int>.from(json['fav_userids'] ?? []),
isFavorite: json['is_favorite'] ?? false,
score: (json['score'] ?? 0).toDouble(),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'album': album,
'original_title': originalTitle,
'albumhash': albumhash,
'original_album': originalAlbum,
'artists': artists.map((artist) => artist.toJson()).toList(),
'albumartists': albumartists.map((artist) => artist.toJson()).toList(),
'artisthashes': artisthashes,
'track': track,
'disc': disc,
'duration': duration,
'bitrate': bitrate,
'filepath': filepath,
'folder': folder,
'genres': genres.map((genre) => genre.toJson()).toList(),
'genrehashes': genrehashes,
'copyright': copyright,
'date': date,
'last_modified': lastModified,
'trackhash': trackhash,
'image': image,
'weak_hash': weakHash,
'extra': extra,
'lastplayed': lastplayed,
'playcount': playcount,
'playduration': playduration,
'explicit': explicit,
'fav_userids': favUserids,
'is_favorite': isFavorite,
'score': score,
};
}
}
class ArtistModel extends Equatable {
final String name;
final String artisthash;
const ArtistModel({
required this.name,
required this.artisthash,
});
factory ArtistModel.fromJson(Map<String, dynamic> json) {
return ArtistModel(
name: json['name'] ?? '',
artisthash: json['artisthash'] ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'artisthash': artisthash,
};
}
@override
List<Object?> get props => [name, artisthash];
}
class GenreModel extends Equatable {
final String name;
final String genrehash;
const GenreModel({
required this.name,
required this.genrehash,
});
factory GenreModel.fromJson(Map<String, dynamic> json) {
return GenreModel(
name: json['name'] ?? '',
genrehash: json['genrehash'] ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'genrehash': genrehash,
};
}
@override
List<Object?> get props => [name, genrehash];
}