From feed9b898a8879d437c72ada759543b9c53ccaad Mon Sep 17 00:00:00 2001 From: chuxuehaocai Date: Sun, 24 May 2026 16:25:51 +0800 Subject: [PATCH] 1 --- android/app/build.gradle.kts | 2 +- lib/pages/home_page.dart | 27 ++++++++++++++++----------- lib/pages/ticket_page.dart | 11 +++++++++++ lib/services/title_api_service.dart | 18 ++++++++++++++---- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 9cab723..d6e58b6 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -16,7 +16,7 @@ android { defaultConfig { applicationId = "com.example.rapollo" - minSdk = 23 + minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 46c80bc..69f916f 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -92,6 +92,7 @@ class _HomePageState extends State { Future _performLogout() async { setState(() => _loggingOut = true); + await Future.delayed(const Duration(seconds: 5)); try { if (TitleServerConfigHolder().isConfigured && _data != null && _data!.isLogin) { final service = TitleApiService(TitleServerConfigHolder().config!); @@ -114,17 +115,21 @@ class _HomePageState extends State { appBar: AppBar( title: Text(_tabTitles[_currentTab]), actions: [ - IconButton( - icon: _loggingOut - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Icon(Icons.logout), - tooltip: AppStrings.logoutTooltip, - onPressed: _loggingOut ? null : _performLogout, - ), + if (_loggingOut) + const Padding( + padding: EdgeInsets.only(right: 12), + child: SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator(strokeWidth: 2), + ), + ) + else + IconButton( + icon: const Icon(Icons.logout), + tooltip: AppStrings.logoutTooltip, + onPressed: _performLogout, + ), ], ), body: IndexedStack( diff --git a/lib/pages/ticket_page.dart b/lib/pages/ticket_page.dart index f405af7..3656219 100644 --- a/lib/pages/ticket_page.dart +++ b/lib/pages/ticket_page.dart @@ -206,6 +206,9 @@ class _TicketPageState extends State { // ignore: avoid_print print('[TICKET] user already logged in, force-logout stale session...'); 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); // ignore: avoid_print print('[TICKET] force-logout done'); @@ -226,6 +229,11 @@ class _TicketPageState extends State { // ignore: avoid_print 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) // ignore: avoid_print print('[TICKET] ── Step 3: getUserData ──'); @@ -324,6 +332,9 @@ class _TicketPageState extends State { print('[TICKET] ── Step 7: userLogout (loginId=$loginId, loginTimestamp=$loginTimestamp) ──'); try { _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); // ignore: avoid_print print('[TICKET] userLogout OK'); diff --git a/lib/services/title_api_service.dart b/lib/services/title_api_service.dart index c3c46e2..0d59619 100644 --- a/lib/services/title_api_service.dart +++ b/lib/services/title_api_service.dart @@ -90,10 +90,16 @@ class TitleApiService { } Map _processResponseBody(Uint8List bodyBytes) { - final decrypted = _aesDecrypt(bodyBytes); - final decompressed = _decompress(decrypted); - final jsonStr = utf8.decode(decompressed); - return jsonDecode(jsonStr) as Map; + try { + final decrypted = _aesDecrypt(bodyBytes); + final decompressed = _decompress(decrypted); + final jsonStr = utf8.decode(decompressed); + return jsonDecode(jsonStr) as Map; + } 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) { @@ -155,6 +161,10 @@ class TitleApiService { throw TitleApiException('$apiName returned ${response.statusCode}'); } + if (response.bodyBytes.isEmpty) { + throw TitleApiException('$apiName returned empty body'); + } + final json = _processResponseBody(response.bodyBytes); final raw = const JsonEncoder.withIndent(' ').convert(json); // ignore: avoid_print