Files
AudiOhm/frontend/lib/domain/entities/track.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

120 lines
3.1 KiB
Dart

import 'package:equatable/equatable.dart';
import 'artist.dart';
import 'album.dart';
/// Track entity
class Track extends Equatable {
final String id;
final String title;
final int? duration;
final int? trackNumber;
final String? imageUrl;
final String? artistId;
final String? albumId;
final Artist? artist;
final Album? album;
final String? audioUrl;
final int? playCount;
final String? youtubeId;
final DateTime createdAt;
final DateTime updatedAt;
const Track({
required this.id,
required this.title,
this.duration,
this.trackNumber,
this.imageUrl,
this.artistId,
this.albumId,
this.artist,
this.album,
this.audioUrl,
this.playCount,
this.youtubeId,
required this.createdAt,
required this.updatedAt,
});
Track copyWith({
String? id,
String? title,
int? duration,
int? trackNumber,
String? imageUrl,
String? artistId,
String? albumId,
Artist? artist,
Album? album,
String? audioUrl,
int? playCount,
String? youtubeId,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return Track(
id: id ?? this.id,
title: title ?? this.title,
duration: duration ?? this.duration,
trackNumber: trackNumber ?? this.trackNumber,
imageUrl: imageUrl ?? this.imageUrl,
artistId: artistId ?? this.artistId,
albumId: albumId ?? this.albumId,
artist: artist ?? this.artist,
album: album ?? this.album,
audioUrl: audioUrl ?? this.audioUrl,
playCount: playCount ?? this.playCount,
youtubeId: youtubeId ?? this.youtubeId,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
/// Format duration as mm:ss
String get formattedDuration {
if (duration == null) return '--:--';
final minutes = duration! ~/ 60;
final seconds = duration! % 60;
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
}
/// Create Track from JSON
factory Track.fromJson(Map<String, dynamic> json) {
return Track(
id: json['id'] as String,
title: json['title'] as String,
duration: json['duration'] as int?,
trackNumber: json['track_number'] as int?,
imageUrl: json['image_url'] as String?,
artistId: json['artist_id'] as String?,
albumId: json['album_id'] as String?,
artist: json['artist'] != null
? Artist.fromJson(json['artist'] as Map<String, dynamic>)
: null,
album: json['album'] != null
? Album.fromJson(json['album'] as Map<String, dynamic>)
: null,
audioUrl: json['audio_url'] as String?,
playCount: json['play_count'] as int?,
youtubeId: json['youtube_id'] as String?,
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(),
);
}
@override
List<Object?> get props => [
id,
title,
duration,
artistId,
albumId,
youtubeId,
];
}