137 lines
3.5 KiB
Dart
137 lines
3.5 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
import '../../domain/models/profile_model.dart';
|
|
import '../../domain/models/profile_stats_model.dart';
|
|
|
|
class ProfileService {
|
|
const ProfileService(this._client);
|
|
|
|
final SupabaseClient _client;
|
|
|
|
User get _currentUser {
|
|
final user = _client.auth.currentUser;
|
|
if (user == null) {
|
|
throw StateError('No authenticated user');
|
|
}
|
|
return user;
|
|
}
|
|
|
|
Future<ProfileModel> fetchMyProfile() async {
|
|
final user = _currentUser;
|
|
final response = await _client
|
|
.from('profiles')
|
|
.select()
|
|
.eq('user_id', user.id)
|
|
.maybeSingle();
|
|
|
|
if (response == null) {
|
|
final created = await _client
|
|
.from('profiles')
|
|
.insert({
|
|
'user_id': user.id,
|
|
'username': (user.userMetadata?['username'] as String?) ?? '',
|
|
'bio': '',
|
|
'avatar_url': '',
|
|
})
|
|
.select()
|
|
.single();
|
|
|
|
return ProfileModel.fromJson(created);
|
|
}
|
|
|
|
return ProfileModel.fromJson(response);
|
|
}
|
|
|
|
Future<ProfileModel> updateUsername(String username) async {
|
|
final user = _currentUser;
|
|
await _client.auth.updateUser(UserAttributes(data: {'username': username}));
|
|
final updated = await _client
|
|
.from('profiles')
|
|
.update({'username': username})
|
|
.eq('user_id', user.id)
|
|
.select()
|
|
.single();
|
|
return ProfileModel.fromJson(updated);
|
|
}
|
|
|
|
Future<ProfileModel> updateBio(String bio) async {
|
|
final user = _currentUser;
|
|
final updated = await _client
|
|
.from('profiles')
|
|
.update({'bio': bio})
|
|
.eq('user_id', user.id)
|
|
.select()
|
|
.single();
|
|
return ProfileModel.fromJson(updated);
|
|
}
|
|
|
|
Future<ProfileModel> updateProfile({
|
|
required String username,
|
|
required String bio,
|
|
}) async {
|
|
final user = _currentUser;
|
|
await _client.auth.updateUser(UserAttributes(data: {'username': username}));
|
|
final updated = await _client
|
|
.from('profiles')
|
|
.update({
|
|
'username': username,
|
|
'bio': bio,
|
|
})
|
|
.eq('user_id', user.id)
|
|
.select()
|
|
.single();
|
|
return ProfileModel.fromJson(updated);
|
|
}
|
|
|
|
Future<ProfileModel> uploadAvatar({
|
|
required Uint8List bytes,
|
|
required String extension,
|
|
}) async {
|
|
final user = _currentUser;
|
|
final path =
|
|
'avatars/${user.id}/${DateTime.now().millisecondsSinceEpoch}.$extension';
|
|
|
|
await _client.storage.from('avatars').uploadBinary(
|
|
path,
|
|
bytes,
|
|
fileOptions: const FileOptions(upsert: true),
|
|
);
|
|
|
|
final avatarUrl = _client.storage.from('avatars').getPublicUrl(path);
|
|
final updated = await _client
|
|
.from('profiles')
|
|
.update({'avatar_url': avatarUrl})
|
|
.eq('user_id', user.id)
|
|
.select()
|
|
.single();
|
|
return ProfileModel.fromJson(updated);
|
|
}
|
|
|
|
Future<ProfileStatsModel> fetchMyStats() async {
|
|
final user = _currentUser;
|
|
|
|
final postResponse = await _client
|
|
.from('posts')
|
|
.select('*')
|
|
.eq('user_id', user.id);
|
|
|
|
final commentResponse = await _client
|
|
.from('comments')
|
|
.select('*')
|
|
.eq('user_id', user.id);
|
|
|
|
final trackResponse = await _client
|
|
.from('tracks')
|
|
.select('*')
|
|
.eq('user_id', user.id);
|
|
|
|
return ProfileStatsModel(
|
|
postsCount: (postResponse as List).length,
|
|
commentsCount: (commentResponse as List).length,
|
|
tracksCount: (trackResponse as List).length,
|
|
);
|
|
}
|
|
}
|