import 'dart:typed_data'; import '../data/models/user_setting_model.dart'; import '../data/models/user_model.dart'; import 'api_service.dart'; /// 用户设置服务 class UserSettingService { UserSettingService._internal(); static final UserSettingService _instance = UserSettingService._internal(); static UserSettingService get instance => _instance; /// 获取当前用户设置 /// _parseResponse 已自动提取 data 字段,返回值即 json['data'] Future getUserSetting() async { final response = await ApiService.instance.get>( '/user/setting', ); return UserSettingModel.fromJson(response); } /// 更新用户设置(仅发送非null字段) /// PATCH /user/setting 返回的 data 字段可能为 null,不应强转为 Map Future updateUserSetting({ String? nick, bool? groupExpires, String? language, String? preferredTheme, bool? versionRetentionEnabled, List? versionRetentionExt, int? versionRetentionMax, String? currentPassword, String? newPassword, bool? twoFaEnabled, String? twoFaCode, bool? disableViewSync, String? shareLinksInProfile, }) async { final data = {}; if (nick != null) data['nick'] = nick; if (groupExpires != null) data['group_expires'] = groupExpires; if (language != null) data['language'] = language; if (preferredTheme != null) data['preferred_theme'] = preferredTheme; if (versionRetentionEnabled != null) { data['version_retention_enabled'] = versionRetentionEnabled; } if (versionRetentionExt != null) { data['version_retention_ext'] = versionRetentionExt; } if (versionRetentionMax != null) { data['version_retention_max'] = versionRetentionMax; } if (currentPassword != null) data['current_password'] = currentPassword; if (newPassword != null) data['new_password'] = newPassword; if (twoFaEnabled != null) data['two_fa_enabled'] = twoFaEnabled; if (twoFaCode != null) data['two_fa_code'] = twoFaCode; if (disableViewSync != null) data['disable_view_sync'] = disableViewSync; if (shareLinksInProfile != null) { data['share_links_in_profile'] = shareLinksInProfile; } // PATCH 响应的 data 字段通常为 null,使用 void 避免类型转换错误 await ApiService.instance.patch( '/user/setting', data: data, ); } /// 更新头像(传图片二进制数据,传null则重置为Gravatar) Future updateAvatar(Uint8List? imageBytes) async { await ApiService.instance.put( '/user/setting/avatar', data: imageBytes, isNoData: true, ); } /// 获取存储用量 /// _parseResponse 已自动提取 data 字段 Future getUserCapacity() async { final response = await ApiService.instance.get>( '/user/capacity', ); return UserCapacityModel.fromJson(response); } /// 准备启用2FA(获取TOTP密钥) /// _parseResponse 自动提取 data 字段,后端 data 是 TOTP secret 字符串 Future prepare2FA() async { return await ApiService.instance.get( '/user/setting/2fa', ); } /// 启用2FA Future enable2FA(String code) async { await updateUserSetting(twoFaEnabled: true, twoFaCode: code); } /// 禁用2FA Future disable2FA(String code) async { await updateUserSetting(twoFaEnabled: false, twoFaCode: code); } /// 修改密码 Future changePassword({ required String currentPassword, required String newPassword, }) async { await updateUserSetting( currentPassword: currentPassword, newPassword: newPassword, ); } /// 修改昵称 Future updateNick(String nick) async { await updateUserSetting(nick: nick); } /// 修改主题色偏好 Future updatePreferredTheme(String themeColor) async { await updateUserSetting(preferredTheme: themeColor); } /// 修改语言偏好 Future updateLanguage(String language) async { await updateUserSetting(language: language); } /// 获取当前用户信息(用于刷新用户资料) /// _parseResponse 已自动提取 data 字段 Future getCurrentUser() async { final response = await ApiService.instance.get>( '/session/user', ); return UserModel.fromJson(response); } /// 撤销OAuth应用授权 Future revokeOAuthGrant(String appId) async { await ApiService.instance.delete( '/session/oauth/grant/$appId', ); } /// 解绑OIDC提供商 Future unlinkOpenId(int provider) async { await ApiService.instance.post( '/session/oidc/unlink', data: {'provider': provider}, ); } /// 删除Passkey Future deletePasskey(String passkeyId) async { await ApiService.instance.delete( '/user/authn', queryParameters: {'id': passkeyId}, ); } /// 获取积分变动记录 /// _parseResponse 已自动提取 data 字段 Future getCreditChanges({ int pageSize = 20, String? nextPageToken, }) async { final queryParams = { 'page_size': pageSize, 'next_page_token': ?nextPageToken, }; final response = await ApiService.instance.get>( '/user/creditChanges', queryParameters: queryParams, ); return CreditChangeList.fromJson(response); } }