bug fix
This commit is contained in:
parent
92bbbcb0eb
commit
f2e9ac3c60
@ -1,11 +1,13 @@
|
|||||||
import 'package:fluro/fluro.dart' as fluro;
|
import 'package:fluro/fluro.dart' as fluro;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:yumi/app/routes/sc_router_init.dart';
|
import 'package:yumi/app/routes/sc_router_init.dart';
|
||||||
import 'package:yumi/modules/country/country_route.dart';
|
import 'package:yumi/modules/country/country_route.dart';
|
||||||
import 'package:yumi/modules/index/main_route.dart';
|
import 'package:yumi/modules/index/main_route.dart';
|
||||||
import 'package:yumi/modules/chat/chat_route.dart';
|
import 'package:yumi/modules/chat/chat_route.dart';
|
||||||
import 'package:yumi/modules/store/store_route.dart';
|
import 'package:yumi/modules/store/store_route.dart';
|
||||||
import 'package:yumi/modules/index/index_page.dart';
|
import 'package:yumi/modules/index/index_page.dart';
|
||||||
|
import 'package:yumi/services/room/rc_room_manager.dart';
|
||||||
import 'package:yumi/modules/user/settings/settings_route.dart';
|
import 'package:yumi/modules/user/settings/settings_route.dart';
|
||||||
import 'package:yumi/modules/user/task/task_route.dart';
|
import 'package:yumi/modules/user/task/task_route.dart';
|
||||||
import 'package:yumi/modules/user/vip/vip_route.dart';
|
import 'package:yumi/modules/user/vip/vip_route.dart';
|
||||||
@ -32,7 +34,7 @@ class SCRoutes {
|
|||||||
handler: fluro.Handler(
|
handler: fluro.Handler(
|
||||||
handlerFunc:
|
handlerFunc:
|
||||||
(BuildContext? context, Map<String, List<String>> params) =>
|
(BuildContext? context, Map<String, List<String>> params) =>
|
||||||
SCIndexPage(),
|
_buildHomePage(context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -57,6 +59,13 @@ class SCRoutes {
|
|||||||
routerProvider.initRouter(router);
|
routerProvider.initRouter(router);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Widget _buildHomePage(BuildContext? context) {
|
||||||
|
return ChangeNotifierProvider<SocialChatRoomManager>.value(
|
||||||
|
value: resolveSocialChatRoomManager(context),
|
||||||
|
child: const SCIndexPage(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PS:路由使用方法
|
// PS:路由使用方法
|
||||||
|
|||||||
@ -241,9 +241,8 @@ class RootAppWithProviders extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// 房间与社交功能Provider - 懒加载
|
// 房间与社交功能Provider - 懒加载
|
||||||
ChangeNotifierProvider<SocialChatRoomManager>(
|
ChangeNotifierProvider<SocialChatRoomManager>.value(
|
||||||
lazy: true,
|
value: socialChatRoomManager,
|
||||||
create: (context) => SocialChatRoomManager(),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
// 礼物与动画系统Provider - 懒加载
|
// 礼物与动画系统Provider - 懒加载
|
||||||
|
|||||||
@ -640,7 +640,9 @@ class _SCEditProfilePageState extends State<SCEditProfilePage> {
|
|||||||
authType = SCAuthType.GOOGLE.name;
|
authType = SCAuthType.GOOGLE.name;
|
||||||
idToken = googleUid;
|
idToken = googleUid;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (_) {
|
||||||
|
// Fallback auth lookup is best effort; the form will ask to sign in again below.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (authType.isEmpty || idToken.isEmpty) {
|
if (authType.isEmpty || idToken.isEmpty) {
|
||||||
SCLoadingManager.hide();
|
SCLoadingManager.hide();
|
||||||
|
|||||||
@ -563,7 +563,8 @@ class _SCIndexPageState extends State<SCIndexPage>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await SCEntryPopupCoordinator.openFirstPartyRoomRandomGame(context);
|
await SCEntryPopupCoordinator.openFirstPartyRoomRandomGame(context);
|
||||||
} catch (error) {
|
} catch (_) {
|
||||||
|
// The entry popup is optional; failure should not block the home page.
|
||||||
} finally {
|
} finally {
|
||||||
_isOpeningFirstRegisterRoomGame = false;
|
_isOpeningFirstRegisterRoomGame = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2708,13 +2708,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_startRoomStatePolling();
|
_startRoomStatePolling();
|
||||||
final currentContext = context;
|
socialChatRoomManager.fetchContributionLevelData(roomId);
|
||||||
if (currentContext != null && currentContext.mounted) {
|
|
||||||
Provider.of<SocialChatRoomManager>(
|
|
||||||
currentContext,
|
|
||||||
listen: false,
|
|
||||||
).fetchContributionLevelData(roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
failureType = RoomStartupFailureType.rtc;
|
failureType = RoomStartupFailureType.rtc;
|
||||||
final rtcTokenResult = await rtcTokenFuture;
|
final rtcTokenResult = await rtcTokenFuture;
|
||||||
@ -3400,13 +3394,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
|||||||
|
|
||||||
void _clearRoomContributionLevelData([BuildContext? targetContext]) {
|
void _clearRoomContributionLevelData([BuildContext? targetContext]) {
|
||||||
final currentContext = targetContext ?? context;
|
final currentContext = targetContext ?? context;
|
||||||
if (currentContext == null || !currentContext.mounted) {
|
resolveSocialChatRoomManager(currentContext).clearContributionLevelData();
|
||||||
return;
|
|
||||||
}
|
|
||||||
Provider.of<SocialChatRoomManager>(
|
|
||||||
currentContext,
|
|
||||||
listen: false,
|
|
||||||
).clearContributionLevelData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -32,8 +32,12 @@ class SocialChatAuthenticationManager extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initializeAuthentication() async {
|
Future<void> _initializeAuthentication() async {
|
||||||
await SCGoogleAuthService.initialize();
|
try {
|
||||||
await _verifyExistingSession();
|
await SCGoogleAuthService.initialize();
|
||||||
|
await _verifyExistingSession();
|
||||||
|
} catch (_) {
|
||||||
|
// Login buttons should remain usable even if silent Google restore fails.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _verifyExistingSession() async {
|
Future<void> _verifyExistingSession() async {
|
||||||
@ -51,10 +55,11 @@ class SocialChatAuthenticationManager extends ChangeNotifier {
|
|||||||
if (authType == SCAuthType.GOOGLE.name) {
|
if (authType == SCAuthType.GOOGLE.name) {
|
||||||
this.authType = authType;
|
this.authType = authType;
|
||||||
try {
|
try {
|
||||||
_user ??= await SCGoogleAuthService.signInWithGoogle();
|
final signedInUser = await SCGoogleAuthService.signInWithGoogle();
|
||||||
if (_user == null) {
|
if (signedInUser == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_user = signedInUser;
|
||||||
uid = _user!.uid;
|
uid = _user!.uid;
|
||||||
SCLoadingManager.show();
|
SCLoadingManager.show();
|
||||||
if (uid.isNotEmpty) {
|
if (uid.isNotEmpty) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:yumi/app_localizations.dart';
|
import 'package:yumi/app_localizations.dart';
|
||||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||||
@ -9,6 +10,25 @@ import 'package:yumi/shared/business_logic/models/res/sc_edit_room_info_res.dart
|
|||||||
import 'package:yumi/shared/business_logic/models/res/my_room_res.dart';
|
import 'package:yumi/shared/business_logic/models/res/my_room_res.dart';
|
||||||
import 'package:yumi/shared/business_logic/models/res/sc_room_contribute_level_res.dart';
|
import 'package:yumi/shared/business_logic/models/res/sc_room_contribute_level_res.dart';
|
||||||
|
|
||||||
|
final SocialChatRoomManager socialChatRoomManager = SocialChatRoomManager();
|
||||||
|
|
||||||
|
SocialChatRoomManager resolveSocialChatRoomManager(BuildContext? context) {
|
||||||
|
if (context != null && context.mounted) {
|
||||||
|
try {
|
||||||
|
final manager = Provider.of<SocialChatRoomManager?>(
|
||||||
|
context,
|
||||||
|
listen: false,
|
||||||
|
);
|
||||||
|
if (manager != null) {
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// A stale route context can be outside the provider tree after logout.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return socialChatRoomManager;
|
||||||
|
}
|
||||||
|
|
||||||
class SocialChatRoomManager extends ChangeNotifier {
|
class SocialChatRoomManager extends ChangeNotifier {
|
||||||
MyRoomRes? myRoom;
|
MyRoomRes? myRoom;
|
||||||
SCRoomContributeLevelRes? roomContributeLevelRes;
|
SCRoomContributeLevelRes? roomContributeLevelRes;
|
||||||
|
|||||||
@ -107,6 +107,7 @@ Future<bool> _isCurrentSessionStillValid(DioException e) async {
|
|||||||
class BaseNetworkClient {
|
class BaseNetworkClient {
|
||||||
final Dio dio;
|
final Dio dio;
|
||||||
static const String silentErrorToastKey = 'silentErrorToast';
|
static const String silentErrorToastKey = 'silentErrorToast';
|
||||||
|
static const String suppressAuthLogoutKey = 'suppressAuthLogout';
|
||||||
static const String baseUrlOverrideKey = 'baseUrlOverride';
|
static const String baseUrlOverrideKey = 'baseUrlOverride';
|
||||||
|
|
||||||
BaseNetworkClient() : dio = Dio() {
|
BaseNetworkClient() : dio = Dio() {
|
||||||
@ -292,6 +293,13 @@ class BaseNetworkClient {
|
|||||||
SCLoadingManager.hide();
|
SCLoadingManager.hide();
|
||||||
final bool silentErrorToast =
|
final bool silentErrorToast =
|
||||||
e.requestOptions.extra[BaseNetworkClient.silentErrorToastKey] == true;
|
e.requestOptions.extra[BaseNetworkClient.silentErrorToastKey] == true;
|
||||||
|
final handledBusinessError = await _handleBusinessErrorResponse(
|
||||||
|
e,
|
||||||
|
silentErrorToast: silentErrorToast,
|
||||||
|
);
|
||||||
|
if (handledBusinessError != null) {
|
||||||
|
return handledBusinessError;
|
||||||
|
}
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case DioExceptionType.connectionTimeout:
|
case DioExceptionType.connectionTimeout:
|
||||||
return DioException(requestOptions: e.requestOptions, error: '连接超时');
|
return DioException(requestOptions: e.requestOptions, error: '连接超时');
|
||||||
@ -300,50 +308,10 @@ class BaseNetworkClient {
|
|||||||
case DioExceptionType.receiveTimeout:
|
case DioExceptionType.receiveTimeout:
|
||||||
return DioException(requestOptions: e.requestOptions, error: '接收超时');
|
return DioException(requestOptions: e.requestOptions, error: '接收超时');
|
||||||
case DioExceptionType.badResponse:
|
case DioExceptionType.badResponse:
|
||||||
final responseData = e.response?.data;
|
|
||||||
final errorCode =
|
|
||||||
responseData is Map ? responseData["errorCode"] : null;
|
|
||||||
final errorMsg =
|
|
||||||
responseData is Map
|
|
||||||
? responseData["errorMsg"]
|
|
||||||
: responseData?.toString();
|
|
||||||
if (errorCode == SCErroCode.userNotRegistered.code) {
|
|
||||||
//用户还没有注册
|
|
||||||
SCTts.show("Please register an account first.");
|
|
||||||
BuildContext? context = navigatorKey.currentContext;
|
|
||||||
if (context != null) {
|
|
||||||
SCNavigatorUtils.push(
|
|
||||||
context,
|
|
||||||
LoginRouter.editProfile,
|
|
||||||
replace: false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (errorCode == SCErroCode.authUnauthorized.code) {
|
|
||||||
//token过期
|
|
||||||
final shouldLogout =
|
|
||||||
!SCNavigatorUtils.inLoginPage &&
|
|
||||||
!await _isCurrentSessionStillValid(e);
|
|
||||||
final BuildContext? context = navigatorKey.currentContext;
|
|
||||||
if (context != null && context.mounted && shouldLogout) {
|
|
||||||
AccountStorage().logout(context);
|
|
||||||
SCNavigatorUtils.inLoginPage = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (errorMsg.toString().endsWith("balance not made")) {
|
|
||||||
BuildContext? context = navigatorKey.currentContext;
|
|
||||||
if (context != null) {
|
|
||||||
SCRoomUtils.goRecharge(context);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!silentErrorToast) {
|
|
||||||
SCTts.show(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DioException(
|
return DioException(
|
||||||
requestOptions: e.requestOptions,
|
requestOptions: e.requestOptions,
|
||||||
response: e.response,
|
response: e.response,
|
||||||
error: '服务器错误: $errorCode ${errorMsg ?? ""}'.trim(),
|
error: e.error ?? e.message ?? 'Server fail',
|
||||||
);
|
);
|
||||||
case DioExceptionType.cancel:
|
case DioExceptionType.cancel:
|
||||||
return DioException(
|
return DioException(
|
||||||
@ -362,6 +330,95 @@ class BaseNetworkClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<DioException?> _handleBusinessErrorResponse(
|
||||||
|
DioException e, {
|
||||||
|
required bool silentErrorToast,
|
||||||
|
}) async {
|
||||||
|
final responseData = e.response?.data;
|
||||||
|
if (responseData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final errorCode = _readErrorCode(responseData);
|
||||||
|
final errorMsg = _readErrorMessage(responseData);
|
||||||
|
if (errorCode == null && errorMsg == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorCode == SCErroCode.userNotRegistered.code) {
|
||||||
|
// 用户还没有注册:Google/Apple 登录后需要继续补充资料。
|
||||||
|
SCTts.show("Please register an account first.");
|
||||||
|
final BuildContext? context = navigatorKey.currentContext;
|
||||||
|
if (context != null && context.mounted) {
|
||||||
|
SCNavigatorUtils.push(context, LoginRouter.editProfile, replace: false);
|
||||||
|
}
|
||||||
|
} else if (errorCode == SCErroCode.authUnauthorized.code) {
|
||||||
|
// token过期
|
||||||
|
if (e.requestOptions.extra[BaseNetworkClient.suppressAuthLogoutKey] ==
|
||||||
|
true) {
|
||||||
|
return DioException(
|
||||||
|
requestOptions: e.requestOptions,
|
||||||
|
response: e.response,
|
||||||
|
type: e.type,
|
||||||
|
error: '服务器错误: ${errorCode ?? ""} ${errorMsg ?? ""}'.trim(),
|
||||||
|
message: e.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final shouldLogout =
|
||||||
|
!SCNavigatorUtils.inLoginPage &&
|
||||||
|
!await _isCurrentSessionStillValid(e);
|
||||||
|
final BuildContext? context = navigatorKey.currentContext;
|
||||||
|
if (context != null && context.mounted && shouldLogout) {
|
||||||
|
AccountStorage().logout(context);
|
||||||
|
SCNavigatorUtils.inLoginPage = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final message = errorMsg ?? "";
|
||||||
|
if (message.endsWith("balance not made")) {
|
||||||
|
final BuildContext? context = navigatorKey.currentContext;
|
||||||
|
if (context != null && context.mounted) {
|
||||||
|
SCRoomUtils.goRecharge(context);
|
||||||
|
}
|
||||||
|
} else if (!silentErrorToast && message.isNotEmpty) {
|
||||||
|
SCTts.show(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DioException(
|
||||||
|
requestOptions: e.requestOptions,
|
||||||
|
response: e.response,
|
||||||
|
type: e.type,
|
||||||
|
error: '服务器错误: ${errorCode ?? ""} ${errorMsg ?? ""}'.trim(),
|
||||||
|
message: e.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int? _readErrorCode(dynamic responseData) {
|
||||||
|
if (responseData is! Map) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final value = responseData["errorCode"] ?? responseData["code"];
|
||||||
|
if (value is int) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (value is num) {
|
||||||
|
return value.toInt();
|
||||||
|
}
|
||||||
|
if (value is String) {
|
||||||
|
return int.tryParse(value);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _readErrorMessage(dynamic responseData) {
|
||||||
|
if (responseData is Map) {
|
||||||
|
return responseData["errorMsg"]?.toString() ??
|
||||||
|
responseData["message"]?.toString();
|
||||||
|
}
|
||||||
|
final message = responseData?.toString().trim();
|
||||||
|
return message == null || message.isEmpty ? null : message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotSuccessException implements Exception {
|
class NotSuccessException implements Exception {
|
||||||
|
|||||||
@ -213,6 +213,10 @@ class SCAccountRepository implements SocialChatUserRepository {
|
|||||||
final result = await http.post(
|
final result = await http.post(
|
||||||
"58f9485b5b9f401c6a14bc1e6534122c7a085bb5f6a613094188ca56fe8bc03d",
|
"58f9485b5b9f401c6a14bc1e6534122c7a085bb5f6a613094188ca56fe8bc03d",
|
||||||
data: parm,
|
data: parm,
|
||||||
|
extra: const {
|
||||||
|
BaseNetworkClient.silentErrorToastKey: true,
|
||||||
|
BaseNetworkClient.suppressAuthLogoutKey: true,
|
||||||
|
},
|
||||||
fromJson: (json) => {},
|
fromJson: (json) => {},
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
@ -352,6 +356,10 @@ class SCAccountRepository implements SocialChatUserRepository {
|
|||||||
final result = await http.get(
|
final result = await http.get(
|
||||||
"d28c7d4eeb945fb765c8206c8f79d77f",
|
"d28c7d4eeb945fb765c8206c8f79d77f",
|
||||||
queryParams: {"roomId": roomId},
|
queryParams: {"roomId": roomId},
|
||||||
|
extra: const {
|
||||||
|
BaseNetworkClient.silentErrorToastKey: true,
|
||||||
|
BaseNetworkClient.suppressAuthLogoutKey: true,
|
||||||
|
},
|
||||||
fromJson: (json) => {},
|
fromJson: (json) => {},
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user