This commit is contained in:
Cookiues committed 2026-08-22 16:52:33 +08:00
1 parent 0b3282da5c
commit 24ccd628d1
43 files changed
+2099 -1490

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
import 'package:flutter/foundation.dart';
import '../config/title_server_config.dart';
import '../services/api_service.dart';
import '../services/title_api_service.dart';
class SessionModel extends ChangeNotifier {
static final SessionModel instance = SessionModel._();
SessionModel._();
final ApiService _apiService = ApiService();
LoginResult? _loginResult;
UserLoginResult? _gameLogin;
String? _cookies;
LoginResult? get loginResult => _loginResult;
UserLoginResult? get gameLogin => _gameLogin;
String? get cookies => _cookies;
static String extractQRCode(String qrCodeToken) =>
ApiService.extractQRCode(qrCodeToken);
Future<LoginResult> loginWithQr(String qrCodeToken) async {
final result = await _apiService.login(qrCodeToken);
if (result.success) {
_loginResult = result;
notifyListeners();
}
return result;
}
Future<UserLoginResult> loginGame({
required int userId,
required String token,
}) async {
final config = TitleServerConfigHolder().config;
if (config == null) {
throw const TitleApiException('Title Server 未配置');
}
// Session cookie comes from the UserLoginApi response itself (empurple).
final service = TitleApiService(config);
final login = await service.userLoginFull(userId: userId, token: token);
updateCookies(service.cookies);
_gameLogin = login;
notifyListeners();
return login;
}
Future<void> logoutGame({
required int userId,
String? cookies,
}) async {
final login = _gameLogin;
if (login == null) return;
final config = TitleServerConfigHolder().config;
if (config == null) return;
final service = TitleApiService(config, cookies: cookies ?? _cookies);
try {
await service.userLogout(
userId: userId,
loginDateTime: login.loginDateTime,
);
} catch (_) {
// best-effort
}
_gameLogin = null;
notifyListeners();
}
void setGameLogin(UserLoginResult? login) {
_gameLogin = login;
notifyListeners();
}
void updateCookies(String? cookies) {
if (cookies != null && cookies.isNotEmpty) {
_cookies = cookies;
}
}
void reset() {
_loginResult = null;
_gameLogin = null;
_cookies = null;
notifyListeners();
}
}
-38
View File
@@ -1,38 +0,0 @@
/// The full UpsertUserAll API payload, constructed from fetched user data
/// and an editable single-song score.
class UpsertUserAllPayload {
final int userId;
final int playlogId;
final bool isEventMode;
final bool isFreePlay;
final int loginDateTime;
/// The entire [upsertUserAll] sub-object from the JSON.
final Map<String, dynamic> upsertUserAll;
/// Minimal playlog entry (required — server rejects empty playlogList).
final Map<String, dynamic>? userPlaylog;
const UpsertUserAllPayload({
required this.userId,
required this.playlogId,
this.isEventMode = false,
this.isFreePlay = false,
required this.loginDateTime,
required this.upsertUserAll,
this.userPlaylog,
});
/// Serialize to the JSON packet expected by UpsertUserAllApi.
Map<String, dynamic> toJson() {
return {
'userId': userId,
'playlogId': playlogId,
'isEventMode': isEventMode,
'isFreePlay': isFreePlay,
'loginDateTime': loginDateTime,
'userPlaylogList': userPlaylog != null ? [userPlaylog] : <dynamic>[],
'upsertUserAll': upsertUserAll,
};
}
}
+1 -1
View File
@@ -147,4 +147,4 @@ class UserDataBean {
banState: toInt(json['banState']),
);
}
}
}
+1 -1
View File
@@ -87,4 +87,4 @@ class UserPreviewDataBean {
errorId: toInt(json['errorId']),
);
}
}
}