Files
AudiOhm/frontend/lib/domain/entities/playlist.dart
T
root a89c7894cf Initial commit: AudiOhm - Alternative Spotify avec streaming YouTube
Backend:
- FastAPI avec PostgreSQL et Redis
- Authentification JWT complète
- API REST pour musique, playlists, recherche
- Streaming audio via yt-dlp
- SQLAlchemy 2.0 async

Frontend:
- Flutter avec thème néon cyberpunk
- State management Riverpod
- Layout adaptatif desktop/mobile
- Lecteur audio avec mini-player

Infrastructure:
- Docker Compose (PostgreSQL + Redis)
- Scripts d'installation automatisés
- Scripts de build pour exécutables

Fichiers ajoutés:
- BUILD_CLIENT_*.bat/sh: Scripts de compilation
- BUILD_CLIENT_README.md: Documentation compilation
- CHECK_FLUTTER.sh: Vérificateur d'environnement
- requirements.txt mis à jour pour Python 3.13
- Modèles SQLAlchemy corrigés (metadata -> extra_metadata)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-18 20:08:36 +00:00

131 lines
3.5 KiB
Dart

import 'package:equatable/equatable.dart';
import 'track.dart';
/// Playlist entity
class Playlist extends Equatable {
final String id;
final String userId;
final String name;
final String? description;
final String? imageUrl;
final bool isPublic;
final bool isCollaborative;
final bool isSmart;
final int trackCount;
final int totalDuration;
final DateTime createdAt;
final DateTime updatedAt;
final List<PlaylistTrack>? tracks;
const Playlist({
required this.id,
required this.userId,
required this.name,
this.description,
this.imageUrl,
this.isPublic = false,
this.isCollaborative = false,
this.isSmart = false,
this.trackCount = 0,
this.totalDuration = 0,
required this.createdAt,
required this.updatedAt,
this.tracks,
});
/// Format total duration as Xh Ym or Ym Zs
String get formattedDuration {
final hours = totalDuration ~/ 3600;
final minutes = (totalDuration % 3600) ~/ 60;
final seconds = totalDuration % 60;
if (hours > 0) {
return '${hours}h ${minutes}m';
} else if (minutes > 0) {
return '${minutes}m ${seconds}s';
} else {
return '${seconds}s';
}
}
/// Create Playlist from JSON
factory Playlist.fromJson(Map<String, dynamic> json) {
return Playlist(
id: json['id'] as String,
userId: json['user_id'] as String,
name: json['name'] as String,
description: json['description'] as String?,
imageUrl: json['image_url'] as String?,
isPublic: json['is_public'] as bool? ?? false,
isCollaborative: json['is_collaborative'] as bool? ?? false,
isSmart: json['is_smart'] as bool? ?? false,
trackCount: json['track_count'] as int? ?? 0,
totalDuration: json['total_duration'] as int? ?? 0,
createdAt: json['created_at'] != null
? DateTime.parse(json['created_at'] as String)
: DateTime.now(),
updatedAt: json['updated_at'] != null
? DateTime.parse(json['updated_at'] as String)
: DateTime.now(),
tracks: json['tracks'] != null
? (json['tracks'] as List)
.map((item) => PlaylistTrack.fromJson(item as Map<String, dynamic>))
.toList()
: null,
);
}
@override
List<Object?> get props => [
id,
userId,
name,
isPublic,
isCollaborative,
trackCount,
totalDuration,
];
}
/// Playlist track association
class PlaylistTrack extends Equatable {
final String id;
final String playlistId;
final String trackId;
final int position;
final DateTime addedAt;
final String? addedBy;
final Track? track;
const PlaylistTrack({
required this.id,
required this.playlistId,
required this.trackId,
required this.position,
required this.addedAt,
this.adddedBy,
this.track,
});
/// Create PlaylistTrack from JSON
factory PlaylistTrack.fromJson(Map<String, dynamic> json) {
return PlaylistTrack(
id: json['id'] as String,
playlistId: json['playlist_id'] as String,
trackId: json['track_id'] as String,
position: json['position'] as int,
addedAt: json['added_at'] != null
? DateTime.parse(json['added_at'] as String)
: DateTime.now(),
addedBy: json['added_by'] as String?,
track: json['track'] != null
? Track.fromJson(json['track'] as Map<String, dynamic>)
: null,
);
}
@override
List<Object?> get props => [id, playlistId, trackId, position, addedAt];
}