This commit is contained in:
2026-05-24 16:25:51 +08:00
parent 4ad57dc1cf
commit feed9b898a
4 changed files with 42 additions and 16 deletions

View File

@@ -16,7 +16,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "com.example.rapollo" applicationId = "com.example.rapollo"
minSdk = 23 minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
versionName = flutter.versionName versionName = flutter.versionName

View File

@@ -92,6 +92,7 @@ class _HomePageState extends State<HomePage> {
Future<void> _performLogout() async { Future<void> _performLogout() async {
setState(() => _loggingOut = true); setState(() => _loggingOut = true);
await Future.delayed(const Duration(seconds: 5));
try { try {
if (TitleServerConfigHolder().isConfigured && _data != null && _data!.isLogin) { if (TitleServerConfigHolder().isConfigured && _data != null && _data!.isLogin) {
final service = TitleApiService(TitleServerConfigHolder().config!); final service = TitleApiService(TitleServerConfigHolder().config!);
@@ -114,17 +115,21 @@ class _HomePageState extends State<HomePage> {
appBar: AppBar( appBar: AppBar(
title: Text(_tabTitles[_currentTab]), title: Text(_tabTitles[_currentTab]),
actions: [ actions: [
IconButton( if (_loggingOut)
icon: _loggingOut const Padding(
? const SizedBox( padding: EdgeInsets.only(right: 12),
width: 20, child: SizedBox(
height: 20, width: 20,
child: CircularProgressIndicator(strokeWidth: 2), height: 20,
) child: CircularProgressIndicator(strokeWidth: 2),
: const Icon(Icons.logout), ),
tooltip: AppStrings.logoutTooltip, )
onPressed: _loggingOut ? null : _performLogout, else
), IconButton(
icon: const Icon(Icons.logout),
tooltip: AppStrings.logoutTooltip,
onPressed: _performLogout,
),
], ],
), ),
body: IndexedStack( body: IndexedStack(

View File

@@ -206,6 +206,9 @@ class _TicketPageState extends State<TicketPage> {
// ignore: avoid_print // ignore: avoid_print
print('[TICKET] user already logged in, force-logout stale session...'); print('[TICKET] user already logged in, force-logout stale session...');
try { try {
print('[TICKET] force-logout: waiting 5s...');
await Future.delayed(const Duration(seconds: 5));
print('[TICKET] force-logout: sending...');
await service.userLogout(userId: userId, loginDateTime: DateTime.now().millisecondsSinceEpoch ~/ 1000); await service.userLogout(userId: userId, loginDateTime: DateTime.now().millisecondsSinceEpoch ~/ 1000);
// ignore: avoid_print // ignore: avoid_print
print('[TICKET] force-logout done'); print('[TICKET] force-logout done');
@@ -226,6 +229,11 @@ class _TicketPageState extends State<TicketPage> {
// ignore: avoid_print // ignore: avoid_print
print('[TICKET] loginId=$loginId lastLoginDate=$lastLoginDate loginDateTime=$loginTimestamp newToken=${loginResult.token}'); print('[TICKET] loginId=$loginId lastLoginDate=$lastLoginDate loginDateTime=$loginTimestamp newToken=${loginResult.token}');
// Wait 60s after LoginPacket for stability
// ignore: avoid_print
print('[TICKET] waiting 60s after LoginPacket...');
await Future.delayed(const Duration(seconds: 60));
// Step 3: Get user data (for playerRating) // Step 3: Get user data (for playerRating)
// ignore: avoid_print // ignore: avoid_print
print('[TICKET] ── Step 3: getUserData ──'); print('[TICKET] ── Step 3: getUserData ──');
@@ -324,6 +332,9 @@ class _TicketPageState extends State<TicketPage> {
print('[TICKET] ── Step 7: userLogout (loginId=$loginId, loginTimestamp=$loginTimestamp) ──'); print('[TICKET] ── Step 7: userLogout (loginId=$loginId, loginTimestamp=$loginTimestamp) ──');
try { try {
_updateStep(TicketStep.logout); _updateStep(TicketStep.logout);
print('[TICKET] ── Step 7: userLogout ── waiting 5s...');
await Future.delayed(const Duration(seconds: 5));
print('[TICKET] ── Step 7: userLogout ── sending...');
await service.userLogout(userId: userId, loginDateTime: loginTimestamp); await service.userLogout(userId: userId, loginDateTime: loginTimestamp);
// ignore: avoid_print // ignore: avoid_print
print('[TICKET] userLogout OK'); print('[TICKET] userLogout OK');

View File

@@ -90,10 +90,16 @@ class TitleApiService {
} }
Map<String, dynamic> _processResponseBody(Uint8List bodyBytes) { Map<String, dynamic> _processResponseBody(Uint8List bodyBytes) {
final decrypted = _aesDecrypt(bodyBytes); try {
final decompressed = _decompress(decrypted); final decrypted = _aesDecrypt(bodyBytes);
final jsonStr = utf8.decode(decompressed); final decompressed = _decompress(decrypted);
return jsonDecode(jsonStr) as Map<String, dynamic>; final jsonStr = utf8.decode(decompressed);
return jsonDecode(jsonStr) as Map<String, dynamic>;
} on FormatException catch (e) {
throw TitleApiException('Response body is not valid JSON: $e');
} on Exception catch (e) {
throw TitleApiException('Failed to process response body: $e');
}
} }
String _buildHash(String apiName) { String _buildHash(String apiName) {
@@ -155,6 +161,10 @@ class TitleApiService {
throw TitleApiException('$apiName returned ${response.statusCode}'); throw TitleApiException('$apiName returned ${response.statusCode}');
} }
if (response.bodyBytes.isEmpty) {
throw TitleApiException('$apiName returned empty body');
}
final json = _processResponseBody(response.bodyBytes); final json = _processResponseBody(response.bodyBytes);
final raw = const JsonEncoder.withIndent(' ').convert(json); final raw = const JsonEncoder.withIndent(' ').convert(json);
// ignore: avoid_print // ignore: avoid_print