first commit

This commit is contained in:
Lucas Saburido
2026-05-13 16:26:45 +01:00
commit cabf2025cd
252 changed files with 13524 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:supabase_flutter/supabase_flutter.dart';
import '../../domain/models/track_model.dart';
class MusicService {
const MusicService(this._client);
final SupabaseClient _client;
User get _currentUser {
final user = _client.auth.currentUser;
if (user == null) {
throw StateError('No authenticated user');
}
return user;
}
/// Uploads a new track with an MP3 file and metadata.
Future<void> uploadTrack({
required Uint8List bytes,
required String title,
required String genreTag,
required String extension,
}) async {
final user = _currentUser;
final ts = DateTime.now().millisecondsSinceEpoch;
final random = Random().nextInt(99999);
final fileName = '$ts-$random.$extension';
final path = 'tracks/${user.id}/$fileName';
// Upload audio to Supabase Storage
await _client.storage.from('tracks').uploadBinary(
path,
bytes,
fileOptions: const FileOptions(upsert: false),
);
final audioUrl = _client.storage.from('tracks').getPublicUrl(path);
// Insert track record into PostgreSQL
await _client.from('tracks').insert({
'user_id': user.id,
'title': title.trim().isEmpty ? 'UNTITLED' : title.trim().toUpperCase(),
'audio_url': audioUrl,
'genre_tag': genreTag.trim().isEmpty ? 'UNKNOWN' : genreTag.trim().toUpperCase(),
'plays': 0,
});
}
/// Lists all tracks in chronological order.
Future<List<TrackModel>> fetchTracks() async {
final response = await _client
.from('tracks')
.select('*, profiles(username)')
.order('created_at', ascending: false);
return List<Map<String, dynamic>>.from(response).map((row) {
final username = (row['profiles'] as Map<String, dynamic>?)?['username'] as String?;
return TrackModel.fromJson(row, username: username);
}).toList();
}
/// Increments the play count of a track.
Future<void> incrementPlays(String trackId) async {
await _client.rpc('increment_track_plays', params: {'track_id': trackId});
}
/// Fetches tracks for a specific user.
Future<List<TrackModel>> fetchUserTracks(String userId) async {
final response = await _client
.from('tracks')
.select('*, profiles(username)')
.eq('user_id', userId)
.order('created_at', ascending: false);
return List<Map<String, dynamic>>.from(response).map((row) {
final username = (row['profiles'] as Map<String, dynamic>?)?['username'] as String?;
return TrackModel.fromJson(row, username: username);
}).toList();
}
}