import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_web_browser/flutter_web_browser.dart'; import 'package:get/get.dart'; import 'package:isekai_wiki/api/mw/user.dart'; import 'package:isekai_wiki/global.dart'; import 'package:isekai_wiki/utils/dialog.dart'; import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class UserInfo { int userId; String userName; String? nickName; Map? avatarUrlSet; UserInfo({ required this.userId, required this.userName, this.nickName, this.avatarUrlSet, }); factory UserInfo.fromJson(Map json) => _$UserInfoFromJson(json); Map toJson() => _$UserInfoToJson(this); } class UserController extends GetxController { bool _ignoreSave = false; var authProcessing = false.obs; var loginRequestToken = "".obs; var userId = 0.obs; var userName = "".obs; var nickName = "".obs; var avatarUrlSet = RxMap({}); bool get isLoggedIn { return userId.value > 0; } String get getDisplayName { return nickName.isNotEmpty ? nickName.string : userName.string; } @override void onInit() async { super.onInit(); loadFromStorage(); updateProfile(); ever(loginRequestToken, (String token) { saveToStorage(); }); } /// 更新用户资料,并检测登录状态 Future updateProfile() async { var userInfoMWRes = await MWApiUser.getCurrentUserInfo(); if (!userInfoMWRes.ok) { if (kDebugMode) { print("Cannot update profile of current user"); print(userInfoMWRes.errorList); } } var userInfoRes = userInfoMWRes.data!; nickName.value = userInfoRes.userinfo.realname ?? ""; if (userInfoRes.useravatar != null) { avatarUrlSet.value = userInfoRes.useravatar!; } } String? getAvatar(int size) { if (avatarUrlSet.isEmpty) { return null; } for (var imgSize in avatarUrlSet.keys) { if (size < imgSize) { return avatarUrlSet[size]; } } return avatarUrlSet.values.last; } /// 从本地存储读取 void loadFromStorage() { try { final prefs = Global.sharedPreferences!; var userInfoJson = prefs.getString("userInfo"); if (userInfoJson == null) return; var userInfoObject = jsonDecode(userInfoJson); if (userInfoObject == null) return; var userInfo = UserInfo.fromJson(userInfoObject); _ignoreSave = true; userId.value = userInfo.userId; userName.value = userInfo.userName; nickName.value = userInfo.nickName ?? ""; avatarUrlSet.value = userInfo.avatarUrlSet ?? {}; _ignoreSave = false; var savedLoginRequestToken = prefs.getString("loginRequestToken"); if (savedLoginRequestToken != null) { _ignoreSave = true; loginRequestToken.value = savedLoginRequestToken; _ignoreSave = false; } } catch (ex) { if (kDebugMode) { print(ex); } } finally { _ignoreSave = false; } } /// 保存到本地存储 void saveToStorage() { if (_ignoreSave) return; final prefs = Global.sharedPreferences!; var userInfo = UserInfo( userId: userId.value, userName: userName.value, nickName: nickName.isNotEmpty ? nickName.value : null, avatarUrlSet: avatarUrlSet.isNotEmpty ? avatarUrlSet : null, ); var userInfoJson = jsonEncode(userInfo.toJson()); prefs.setString("userInfo", userInfoJson); if (loginRequestToken.isNotEmpty) { prefs.setString("loginRequestToken", loginRequestToken.value); } else if (prefs.containsKey("loginRequestToken")) { prefs.remove("loginRequestToken"); } } /// 开始登录流程 /// 从服务器获取loginRequestToken Future startAuthFlow() async { authProcessing.value = true; var startAuthRes = await MWApiUser.startAuth(); if (!startAuthRes.ok) { authProcessing.value = false; alert(Get.overlayContext!, startAuthRes.errorList?[0].info ?? "未知错误", title: "错误"); return; } var startAuthInfo = startAuthRes.data!; loginRequestToken.value = startAuthInfo.loginRequestKey; await FlutterWebBrowser.openWebPage( url: startAuthInfo.loginUrl, customTabsOptions: const CustomTabsOptions( defaultColorSchemeParams: CustomTabsColorSchemeParams( toolbarColor: Color.fromRGBO(33, 37, 41, 1), ), shareState: CustomTabsShareState.off, showTitle: true, ), safariVCOptions: const SafariViewControllerOptions( barCollapsingEnabled: true, )); } // 尝试通过登录请求Token完成登录 Future attemptFinishAuth() async { if (loginRequestToken.isEmpty) { authProcessing.value = false; return; } var attemptAuthRes = await MWApiUser.attemptAuth(loginRequestToken.value); if (!attemptAuthRes.ok) { authProcessing.value = false; alert(Get.overlayContext!, attemptAuthRes.errorList?[0].info ?? "未知错误", title: "错误"); return; } var attemptAuthInfo = attemptAuthRes.data!; if (attemptAuthInfo.status == "pending") { authProcessing.value = false; loginRequestToken.value = ""; alert(Get.overlayContext!, "已取消登录", title: "提示"); return; } else if (attemptAuthInfo.status == "success") { userId.value = attemptAuthInfo.userid!; userName.value = attemptAuthInfo.username!; try { await updateProfile(); } catch (err) { err.printError(info: 'Cannot update profile after auth'); } authProcessing.value = false; saveToStorage(); } } Future logout() async {} }