Files
eryao/apps/lib/features/settings/data/apis/profile_api.dart
T

162 lines
5.5 KiB
Dart
Raw Normal View History

import 'package:dio/dio.dart';
import '../../../../core/network/api_problem.dart';
import '../../../../data/network/api_client.dart';
import '../models/profile_settings.dart';
class ProfileApi {
const ProfileApi({required ApiClient apiClient}) : _apiClient = apiClient;
final ApiClient _apiClient;
Future<ProfileSettingsV1> getProfile() async {
final json = await _apiClient.getJson('/api/v1/users/me/profile');
return _toSettings(json);
}
Future<ProfileSettingsV1> updateProfile(ProfileSettingsV1 next) async {
final payload = <String, dynamic>{
'display_name': next.displayName,
'bio': next.bio,
if (next.avatarPath != null && next.avatarPath!.isNotEmpty)
'avatar_path': next.avatarPath,
};
final json = await _apiClient.rawDio.patch<Map<String, dynamic>>(
'/api/v1/users/me/profile',
data: payload,
);
final data = json.data;
if (data is! Map<String, dynamic>) {
throw ApiProblem(
status: 502,
title: 'Invalid profile payload',
detail: 'Expected profile response object',
);
}
return _toSettings(data);
}
Future<ProfileSettingsV1> updateSettings(ProfileSettingsV1 settings) async {
final payload = <String, dynamic>{
'settings': {
'version': settings.version,
'preferences': {
'interface_language': settings.preferences.interfaceLanguage,
'ai_language': settings.preferences.aiLanguage,
'timezone': settings.preferences.timezone,
'country': settings.preferences.country,
},
'privacy': settings.privacy,
'notification': {
'allow_notifications': settings.notification.allowNotifications,
'allow_vibration': settings.notification.allowVibration,
},
'divination_tutorial': {
'divination_entry_shown':
settings.divinationTutorial.divinationEntryShown,
'auto_divination_shown':
settings.divinationTutorial.autoDivinationShown,
'manual_divination_shown':
settings.divinationTutorial.manualDivinationShown,
},
},
};
final json = await _apiClient.rawDio.patch<Map<String, dynamic>>(
'/api/v1/users/me/settings',
data: payload,
);
final data = json.data;
if (data is! Map<String, dynamic>) {
throw ApiProblem(
status: 502,
title: 'Invalid settings payload',
detail: 'Expected settings response object',
);
}
return _toSettings(data);
}
Future<ProfileSettingsV1> uploadAvatar(String filePath) async {
final formData = FormData.fromMap({
'file': await MultipartFile.fromFile(filePath),
});
final response = await _apiClient.rawDio.post<Map<String, dynamic>>(
'/api/v1/users/me/avatar',
data: formData,
);
final data = response.data;
if (data is! Map<String, dynamic>) {
throw ApiProblem(
status: 502,
title: 'Invalid profile payload',
detail: 'Expected profile response object',
);
}
return _toSettings(data);
}
2026-04-10 10:40:44 +08:00
Future<void> deleteAccount() async {
await _apiClient.deleteNoContent('/api/v1/users/me');
}
ProfileSettingsV1 _toSettings(Map<String, dynamic> json) {
final settingsRaw = json['settings'];
final preferencesRaw = settingsRaw is Map<String, dynamic>
? settingsRaw['preferences']
: null;
final preferences = preferencesRaw is Map<String, dynamic>
? PreferenceSettings(
interfaceLanguage:
(preferencesRaw['interface_language'] as String?) ?? 'zh-CN',
aiLanguage: (preferencesRaw['ai_language'] as String?) ?? 'zh-CN',
timezone:
(preferencesRaw['timezone'] as String?) ?? 'Asia/Shanghai',
2026-04-16 16:11:09 +08:00
country: (preferencesRaw['country'] as String?) ?? 'US',
)
: const PreferenceSettings();
final notificationRaw = settingsRaw is Map<String, dynamic>
? settingsRaw['notification']
: null;
final notification = notificationRaw is Map<String, dynamic>
? NotificationSettings(
allowNotifications:
(notificationRaw['allow_notifications'] as bool? ?? true),
allowVibration:
(notificationRaw['allow_vibration'] as bool? ?? true),
)
: const NotificationSettings();
final divinationTutorialRaw = settingsRaw is Map<String, dynamic>
? settingsRaw['divination_tutorial']
: null;
final divinationTutorial = divinationTutorialRaw is Map<String, dynamic>
? DivinationTutorialSettings(
divinationEntryShown:
(divinationTutorialRaw['divination_entry_shown'] as bool?) ??
true,
autoDivinationShown:
(divinationTutorialRaw['auto_divination_shown'] as bool?) ??
true,
manualDivinationShown:
(divinationTutorialRaw['manual_divination_shown'] as bool?) ??
true,
)
: const DivinationTutorialSettings();
return ProfileSettingsV1(
displayName: (json['display_name'] as String?) ?? '',
bio: (json['bio'] as String?) ?? '',
avatarPath: json['avatar_path'] as String?,
avatarUrl: json['avatar_url'] as String?,
preferences: preferences,
privacy: settingsRaw is Map<String, dynamic>
? (settingsRaw['privacy'] as Map<String, dynamic>? ??
const <String, dynamic>{})
: const <String, dynamic>{},
notification: notification,
divinationTutorial: divinationTutorial,
);
}
}