倒计时以及日常
This commit is contained in:
parent
53dbacef91
commit
3bcbce71eb
@ -1,4 +1,3 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/app/config/configs/sc_variant1_config.dart';
|
||||
import 'package:yumi/app/config/business_logic_strategy.dart';
|
||||
|
||||
@ -145,17 +144,9 @@ abstract class AppConfig {
|
||||
case 'variant1':
|
||||
default:
|
||||
_current = SCVariant1Config();
|
||||
debugPrint('AppConfig initialized for variant1 ');
|
||||
}
|
||||
|
||||
// 验证配置是否有效
|
||||
try {
|
||||
_current!.validate();
|
||||
} catch (e) {
|
||||
// validate方法在调试模式下不会抛出异常
|
||||
// 只有在发布模式下验证失败才会抛出异常
|
||||
debugPrint('应用配置验证失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,10 +29,12 @@ class SCVariant1Config implements AppConfig {
|
||||
String get userAgreementUrl => 'https://h5.haiyihy.com/service.html'; // 正式用户协议页面
|
||||
|
||||
@override
|
||||
String get appDownloadUrlGoogle => 'https://play.google.com/store/apps/details?id=$packageName';
|
||||
String get appDownloadUrlGoogle =>
|
||||
'https://play.google.com/store/apps/details?id=$packageName';
|
||||
|
||||
@override
|
||||
String get appDownloadUrlApple => 'https://apps.apple.com/us/app/atuchat/id1234567890'; // 需要更新为真实App Store ID
|
||||
String get appDownloadUrlApple =>
|
||||
'https://apps.apple.com/us/app/atuchat/id1234567890'; // 需要更新为真实App Store ID
|
||||
|
||||
@override
|
||||
String get anchorAgentUrl => 'https://h5.haiyihy.com/apply/index.html'; // 正式 H5 页面
|
||||
@ -44,7 +46,8 @@ class SCVariant1Config implements AppConfig {
|
||||
String get bdCenterUrl => 'https://h5.haiyihy.com/bd-center/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get bdLeaderUrl => 'https://h5.haiyihy.com/bd-leader-center/index.html'; // 正式 H5 页面
|
||||
String get bdLeaderUrl =>
|
||||
'https://h5.haiyihy.com/bd-leader-center/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get coinSellerUrl => 'https://h5.haiyihy.com/coin-seller/index.html'; // 正式 H5 页面
|
||||
@ -53,22 +56,27 @@ class SCVariant1Config implements AppConfig {
|
||||
String get adminUrl => 'https://h5.haiyihy.com/admin-center/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get agencyCenterUrl => 'https://h5.haiyihy.com/agency-center/index.html'; // 正式 H5 页面
|
||||
String get agencyCenterUrl =>
|
||||
'https://h5.haiyihy.com/agency-center/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get gamesKingUrl => 'https://h5.haiyihy.com/games-king/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get wealthRankUrl => 'https://h5.haiyihy.com/ranking/index.html?first=Wealth'; // 正式 H5 页面
|
||||
String get wealthRankUrl =>
|
||||
'https://h5.haiyihy.com/ranking/index.html?first=Wealth'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get charmRankUrl => 'https://h5.haiyihy.com/ranking/index.html?first=Charm'; // 正式 H5 页面
|
||||
String get charmRankUrl =>
|
||||
'https://h5.haiyihy.com/ranking/index.html?first=Charm'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get roomRankUrl => 'https://h5.haiyihy.com/ranking/index.html?first=Room'; // 正式 H5 页面
|
||||
String get roomRankUrl =>
|
||||
'https://h5.haiyihy.com/ranking/index.html?first=Room'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
String get inviteNewUserUrl => 'https://h5.haiyihy.com/invitation/invite-new-user/index.html'; // 正式 H5 页面
|
||||
String get inviteNewUserUrl =>
|
||||
'https://h5.haiyihy.com/invitation/invite-new-user/index.html'; // 正式 H5 页面
|
||||
|
||||
@override
|
||||
int get primaryColor => 0xffFF5722; // 不同主色(橙色)
|
||||
@ -158,16 +166,10 @@ class SCVariant1Config implements AppConfig {
|
||||
if (errors.isNotEmpty) {
|
||||
final errorMessage = '应用配置验证失败:\n${errors.join('\n')}';
|
||||
|
||||
if (kDebugMode) {
|
||||
// 调试模式下只输出警告,不阻止应用启动(方便开发)
|
||||
debugPrint('⚠️ 警告: $errorMessage');
|
||||
debugPrint('⚠️ 在调试模式下,应用将继续启动,但某些功能可能无法正常工作');
|
||||
} else {
|
||||
if (!kDebugMode) {
|
||||
// 发布模式下抛出异常,阻止应用启动
|
||||
throw StateError(errorMessage);
|
||||
}
|
||||
} else {
|
||||
debugPrint('应用配置验证通过');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/shared/tools/sc_dialog_utils.dart';
|
||||
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
|
||||
|
||||
import '../../../modules/home/popular/event/home_event_page.dart';
|
||||
import '../../../modules/home/popular/mine/sc_home_mine_page.dart';
|
||||
import '../../../modules/home/popular/party/sc_home_party_page.dart';
|
||||
|
||||
@ -50,7 +49,6 @@ class Variant1BusinessLogicStrategy extends BaseBusinessLogicStrategy {
|
||||
// 马甲包:显示更详细的首充对话框
|
||||
SCDialogUtils.showFirstRechargeDialog(context);
|
||||
// 额外逻辑:记录点击事件或触发其他行为
|
||||
debugPrint('马甲包首充提示被点击');
|
||||
}
|
||||
|
||||
/// === 登录页面差异化方法实现(马甲包专属样式)===
|
||||
|
||||
@ -39,22 +39,26 @@ class SCNavigatorUtils {
|
||||
}
|
||||
|
||||
//不需要页面返回值的跳转
|
||||
static Future push(BuildContext context, String path,
|
||||
{bool replace = false,
|
||||
static Future push(
|
||||
BuildContext context,
|
||||
String path, {
|
||||
bool replace = false,
|
||||
bool clearStack = false,
|
||||
TransitionType? transition,
|
||||
Duration? transitionDuration,
|
||||
RouteTransitionsBuilder? transitionBuilder}) async {
|
||||
RouteTransitionsBuilder? transitionBuilder,
|
||||
}) async {
|
||||
FocusScope.of(context).unfocus();
|
||||
inLoginPage = path.startsWith(LoginRouter.login);
|
||||
inChatPage = path.startsWith(SCChatRouter.chat);
|
||||
final result = await SCLkApplication.router.navigateTo(context, path,
|
||||
final result = await SCLkApplication.router.navigateTo(
|
||||
context,
|
||||
path,
|
||||
replace: replace,
|
||||
clearStack: clearStack,
|
||||
|
||||
///在系统语言为ar语会有问题
|
||||
transition: (Platform.isAndroid
|
||||
? null
|
||||
: TransitionType.cupertino),
|
||||
transition: (Platform.isAndroid ? null : TransitionType.cupertino),
|
||||
// transitionDuration: transitionDuration ??
|
||||
// (Platform.isAndroid ? kAndroidTransitionDuration : null),
|
||||
// transitionBuilder: transitionBuilder ??
|
||||
@ -77,15 +81,20 @@ class SCNavigatorUtils {
|
||||
|
||||
//需要页面返回值的跳转
|
||||
static pushResult(
|
||||
BuildContext context, String path, Function(Object) function,
|
||||
{bool replace = false,
|
||||
BuildContext context,
|
||||
String path,
|
||||
Function(Object) function, {
|
||||
bool replace = false,
|
||||
bool clearStack = false,
|
||||
TransitionType? transition}) {
|
||||
TransitionType? transition,
|
||||
}) {
|
||||
FocusScope.of(context).unfocus();
|
||||
inLoginPage = path == LoginRouter.login;
|
||||
inChatPage = path.startsWith(SCChatRouter.chat);
|
||||
SCLkApplication.router
|
||||
.navigateTo(context, path,
|
||||
.navigateTo(
|
||||
context,
|
||||
path,
|
||||
replace: replace,
|
||||
clearStack: clearStack,
|
||||
// transition: transition ??
|
||||
@ -114,14 +123,13 @@ class SCNavigatorUtils {
|
||||
return;
|
||||
}
|
||||
function(result);
|
||||
}).catchError((error) {
|
||||
debugPrint('$error');
|
||||
});
|
||||
})
|
||||
.catchError((error) {});
|
||||
}
|
||||
|
||||
/// 直接返回
|
||||
static void goBack(BuildContext context) {
|
||||
if(inChatPage){
|
||||
if (inChatPage) {
|
||||
inChatPage = false;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
@ -130,7 +138,7 @@ class SCNavigatorUtils {
|
||||
|
||||
/// 带参数返回
|
||||
static void goBackWithParams(BuildContext context, result) {
|
||||
if(inChatPage){
|
||||
if (inChatPage) {
|
||||
inChatPage = false;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
@ -138,7 +146,7 @@ class SCNavigatorUtils {
|
||||
}
|
||||
|
||||
static void popUntil(BuildContext context, RoutePredicate predicate) {
|
||||
if(inChatPage){
|
||||
if (inChatPage) {
|
||||
inChatPage = false;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
|
||||
@ -23,7 +23,6 @@ class SCRoutes {
|
||||
/// 指定路由跳转错误返回页
|
||||
router.notFoundHandler = fluro.Handler(
|
||||
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
|
||||
debugPrint('未找到目标页');
|
||||
return SCWidgetNotFound();
|
||||
},
|
||||
);
|
||||
|
||||
@ -23,7 +23,7 @@ class ImagePick {
|
||||
);
|
||||
if (pickedFile != null) {
|
||||
if (!SCPathUtils.fileTypeIsPicAndMP4(pickedFile.path)) {
|
||||
SCTts.show( "Please select sc_images in .jpg, .jpeg, .png format.");
|
||||
SCTts.show("Please select sc_images in .jpg, .jpeg, .png format.");
|
||||
return null;
|
||||
}
|
||||
return [File(pickedFile.path)];
|
||||
@ -31,7 +31,6 @@ class ImagePick {
|
||||
return null;
|
||||
} catch (e) {
|
||||
// 处理异常,例如权限被拒绝或选择器被取消
|
||||
print("图片选择出错: $e");
|
||||
// 可以在这里添加用户友好的提示信息
|
||||
return null;
|
||||
}
|
||||
@ -58,7 +57,6 @@ class ImagePick {
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
print("多图选择出错: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -74,14 +72,13 @@ class ImagePick {
|
||||
);
|
||||
if (pickedFile != null) {
|
||||
if (!SCPathUtils.fileTypeIsPic(pickedFile.path)) {
|
||||
SCTts.show( "Please select sc_images in .jpg, .jpeg, .png format.");
|
||||
SCTts.show("Please select sc_images in .jpg, .jpeg, .png format.");
|
||||
return null;
|
||||
}
|
||||
return File(pickedFile.path);
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
print("图片选择出错: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -100,7 +97,6 @@ class ImagePick {
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
print("相机拍照出错: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import 'package:fluro/fluro.dart' as fluro;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
@ -126,33 +125,25 @@ Future<void> _warmUpDeferredServices() async {
|
||||
}
|
||||
_isCrashlyticsReady = true;
|
||||
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
||||
if (kDebugMode) {
|
||||
debugPrint('Firebase/Crashlytics 后台初始化完成');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint('Firebase 后台初始化异常: $e\n$stackTrace');
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _recordFlutterError(FlutterErrorDetails details) async {
|
||||
if (!_isCrashlyticsReady) {
|
||||
debugPrint(
|
||||
'Flutter Error before Crashlytics ready: ${details.exceptionAsString()}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await FirebaseCrashlytics.instance.recordFlutterFatalError(details);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint('Crashlytics 记录 Flutter 错误失败: $e\n$stackTrace');
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _recordFatalError(Object error, StackTrace stackTrace) async {
|
||||
if (!_isCrashlyticsReady) {
|
||||
debugPrint('Unhandled error before Crashlytics ready: $error');
|
||||
debugPrintStack(stackTrace: stackTrace);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -162,8 +153,8 @@ Future<void> _recordFatalError(Object error, StackTrace stackTrace) async {
|
||||
stackTrace,
|
||||
fatal: true,
|
||||
);
|
||||
} catch (e, recordStackTrace) {
|
||||
debugPrint('Crashlytics 记录异常失败: $e\n$recordStackTrace');
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,14 +169,8 @@ Future<void> _initStore() async {
|
||||
try {
|
||||
await DataPersistence.initialize();
|
||||
success = true;
|
||||
if (kDebugMode) {
|
||||
debugPrint('数据存储初始化成功(尝试次数: $attemptCount)');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('数据存储初始化尝试 $attemptCount 失败: $e');
|
||||
|
||||
} catch (_) {
|
||||
if (attemptCount >= maxAttempts) {
|
||||
debugPrint('数据存储初始化失败,已达最大重试次数: $maxAttempts');
|
||||
// 不抛出异常,允许应用继续运行
|
||||
return;
|
||||
}
|
||||
@ -337,7 +322,6 @@ class _YumiApplicationState extends State<YumiApplication>
|
||||
|
||||
void _handleLink(Uri uri) {
|
||||
// 这是处理链接的核心路由逻辑
|
||||
debugPrint('App 根层收到链接: $uri');
|
||||
}
|
||||
|
||||
void _initRouter() {
|
||||
|
||||
@ -640,9 +640,7 @@ class _SCEditProfilePageState extends State<SCEditProfilePage> {
|
||||
authType = SCAuthType.GOOGLE.name;
|
||||
idToken = googleUid;
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('resolve register auth failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
if (authType.isEmpty || idToken.isEmpty) {
|
||||
SCLoadingManager.hide();
|
||||
|
||||
@ -162,7 +162,6 @@ class _MessageItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
this.context = context;
|
||||
print('status:${message.status}');
|
||||
String time = SCMDateUtils.formatMessageTime(
|
||||
context,
|
||||
DateTime.fromMillisecondsSinceEpoch(int.parse(message.createdAt ?? "0")),
|
||||
|
||||
@ -388,14 +388,7 @@ class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||||
final home = await repository.vipHome();
|
||||
vipHome = home;
|
||||
chatBubble = _resolveSelfVipChatBubbleFromHome(home);
|
||||
debugPrint(
|
||||
'[VIP][ChatBubble] home active=${home.state?.active} '
|
||||
'level=${home.state?.level} levelCode=${home.state?.levelCode} '
|
||||
'selected=${_vipChatBubbleLogValue(chatBubble)}',
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[VIP][ChatBubble] home load failed error=$error');
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
if (chatBubble == null) {
|
||||
try {
|
||||
@ -412,14 +405,7 @@ class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||||
)?.chatBubble,
|
||||
]);
|
||||
}
|
||||
debugPrint(
|
||||
'[VIP][ChatBubble] status active=${status.active} '
|
||||
'level=${status.level} levelCode=${status.levelCode} '
|
||||
'selected=${_vipChatBubbleLogValue(chatBubble)}',
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[VIP][ChatBubble] status load failed error=$error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
@ -515,8 +501,10 @@ class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||||
if (text == null || text.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
final match = RegExp(r'(?:S?VIP)?\s*([1-9]\d*)', caseSensitive: false)
|
||||
.firstMatch(text);
|
||||
final match = RegExp(
|
||||
r'(?:S?VIP)?\s*([1-9]\d*)',
|
||||
caseSensitive: false,
|
||||
).firstMatch(text);
|
||||
return int.tryParse(match?.group(1) ?? '');
|
||||
}
|
||||
|
||||
@ -553,20 +541,16 @@ class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||||
|
||||
///消息列表
|
||||
Widget _msgList() {
|
||||
print('xiaoxiliebiao:${currentConversationMessageList.length}');
|
||||
return SmartRefresher(
|
||||
enablePullDown: false,
|
||||
enablePullUp: true,
|
||||
onLoading: () async {
|
||||
print('onLoading');
|
||||
if (currentConversationMessageList.isNotEmpty) {
|
||||
final messages = await _loadHistoryMessages(
|
||||
count: 30,
|
||||
lastMsgID: currentConversationMessageList.last.msgID,
|
||||
);
|
||||
print('加载前:${currentConversationMessageList.length}');
|
||||
currentConversationMessageList.addAll(messages);
|
||||
print('加载后:${currentConversationMessageList.length}');
|
||||
if (messages.length == 30) {
|
||||
_refreshController.loadComplete();
|
||||
} else {
|
||||
@ -687,7 +671,6 @@ class _SCMessageChatPageState extends State<SCMessageChatPage> {
|
||||
),
|
||||
);
|
||||
final messages = await _loadHistoryMessages(count: 100);
|
||||
print("messages : ${messages.length}");
|
||||
currentConversationMessageList.clear();
|
||||
|
||||
for (var msg in messages) {
|
||||
@ -1116,7 +1099,6 @@ class _MessageItem extends StatelessWidget {
|
||||
int preTimestamp = (preMessage?.timestamp ?? 0) * 1000;
|
||||
if (preMessage != null) {
|
||||
///5分钟以内 不显示
|
||||
// print('timestamp:$timestamp===preTimestamp:${preTimestamp}');
|
||||
if (DateTime.fromMillisecondsSinceEpoch(timestamp)
|
||||
.difference(DateTime.fromMillisecondsSinceEpoch(preTimestamp))
|
||||
.inMilliseconds <
|
||||
|
||||
@ -165,7 +165,6 @@ class _MessageItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
this.context = context;
|
||||
print('status:${message.status}');
|
||||
String time = SCMDateUtils.formatMessageTime(
|
||||
context,
|
||||
DateTime.fromMillisecondsSinceEpoch(int.parse(message.createdAt ?? "0")),
|
||||
|
||||
@ -94,7 +94,6 @@ class _MessageSystemPageState extends State<MessageSystemPage> {
|
||||
);
|
||||
List<V2TimMessage> messages = v2timValueCallback.data!;
|
||||
// List<V2TimMessage> messages = await FTIM.getMessageManager().getMessages(conversation: currentConversation);
|
||||
print("messages : ${messages?.length ?? 0}");
|
||||
currentConversationMessageList ??= [];
|
||||
currentConversationMessageList?.clear();
|
||||
|
||||
@ -175,12 +174,10 @@ class _MessageSystemPageState extends State<MessageSystemPage> {
|
||||
}
|
||||
|
||||
Widget _msgList() {
|
||||
print('xiaoxiliebiao:${currentConversationMessageList.length}');
|
||||
return SmartRefresher(
|
||||
enablePullDown: false,
|
||||
enablePullUp: true,
|
||||
onLoading: () async {
|
||||
print('onLoading');
|
||||
if (currentConversationMessageList.isNotEmpty) {
|
||||
// 拉取单聊历史消息
|
||||
// 首次拉取,lastMsgID 设置为 null
|
||||
@ -195,9 +192,7 @@ class _MessageSystemPageState extends State<MessageSystemPage> {
|
||||
);
|
||||
List<V2TimMessage> messages =
|
||||
v2timValueCallback.data as List<V2TimMessage>;
|
||||
print('加载前:${currentConversationMessageList.length}');
|
||||
currentConversationMessageList.addAll(messages);
|
||||
print('加载后:${currentConversationMessageList.length}');
|
||||
if (messages.length == 30) {
|
||||
_refreshController.loadComplete();
|
||||
} else {
|
||||
@ -275,7 +270,6 @@ class _MessageItem extends StatelessWidget {
|
||||
int preTimestamp = (preMessage?.timestamp ?? 0) * 1000;
|
||||
if (preMessage != null) {
|
||||
///5分钟以内 不显示
|
||||
// print('timestamp:$timestamp===preTimestamp:${preTimestamp}');
|
||||
if (DateTime.fromMillisecondsSinceEpoch(timestamp)
|
||||
.difference(DateTime.fromMillisecondsSinceEpoch(preTimestamp))
|
||||
.inMilliseconds <
|
||||
@ -295,11 +289,12 @@ class _MessageItem extends StatelessWidget {
|
||||
final data = jsonDecode(content);
|
||||
noticeType = data["noticeType"];
|
||||
if (noticeType == SCSysytemMessageType.CP_LOVE_LETTER.name) {
|
||||
var bean = SCSystemInvitMessageRes.fromJson(jsonDecode(data["content"]));
|
||||
var bean = SCSystemInvitMessageRes.fromJson(
|
||||
jsonDecode(data["content"]),
|
||||
);
|
||||
tagHead = bean.userAvatar ?? "";
|
||||
}
|
||||
}
|
||||
print('status:${message.status}');
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 15.w, vertical: 8.w),
|
||||
child: Column(
|
||||
@ -359,7 +354,8 @@ class _MessageItem extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
)
|
||||
: ExtendedImage.asset(
|
||||
SCGlobalConfig.businessLogicStrategy.getMessagePageSystemMessageIcon(),
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getMessagePageSystemMessageIcon(),
|
||||
width: 45.w,
|
||||
shape: BoxShape.circle,
|
||||
fit: BoxFit.cover,
|
||||
@ -464,8 +460,7 @@ class _MessageItem extends StatelessWidget {
|
||||
if ("ACTIVITY" == propType ||
|
||||
"ADMINISTRSCOR" == propType ||
|
||||
"ACHIEVEMENT" == propType) {
|
||||
|
||||
}else {
|
||||
} else {
|
||||
SCNavigatorUtils.push(
|
||||
context,
|
||||
StoreRoute.bags,
|
||||
@ -473,7 +468,11 @@ class _MessageItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
SCNavigatorUtils.push(context, StoreRoute.bags, replace: false);
|
||||
SCNavigatorUtils.push(
|
||||
context,
|
||||
StoreRoute.bags,
|
||||
replace: false,
|
||||
);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
@ -538,7 +537,8 @@ class _MessageItem extends StatelessWidget {
|
||||
},
|
||||
context,
|
||||
);
|
||||
} else if (type == SCSysytemMessageType.ADMIN_INVITE_RECHARGE_AGENT.name) {
|
||||
} else if (type ==
|
||||
SCSysytemMessageType.ADMIN_INVITE_RECHARGE_AGENT.name) {
|
||||
return SCSystemMessageUtils.buildAdminInviteRechargeAgentMessage(
|
||||
data,
|
||||
(ct, content) {
|
||||
@ -567,7 +567,10 @@ class _MessageItem extends StatelessWidget {
|
||||
context,
|
||||
);
|
||||
} else if (type == SCSysytemMessageType.CP_LOVE_LETTER.name) {
|
||||
return SCSystemMessageUtils.buildCPLoveLetterMessage(data, (ct, content) {
|
||||
return SCSystemMessageUtils.buildCPLoveLetterMessage(data, (
|
||||
ct,
|
||||
content,
|
||||
) {
|
||||
_showMsgItemMenu(ct, content);
|
||||
}, context);
|
||||
} else if (type == SCSysytemMessageType.USER_COINS_RECEIVED.name) {
|
||||
@ -697,7 +700,11 @@ class _MessageItem extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
SCGlobalConfig.businessLogicStrategy.getIdBackgroundImage(bean.account != bean.actualAccount),
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getIdBackgroundImage(
|
||||
bean.account !=
|
||||
bean.actualAccount,
|
||||
),
|
||||
),
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
@ -714,7 +721,8 @@ class _MessageItem extends StatelessWidget {
|
||||
),
|
||||
SizedBox(width: 5.w),
|
||||
Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy.getCopyIdIcon(),
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getCopyIdIcon(),
|
||||
width: 12.w,
|
||||
height: 12.w,
|
||||
),
|
||||
@ -759,8 +767,12 @@ class _MessageItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
SCAccountRepository().followNew(expand).then((result) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.followSucc);
|
||||
SCAccountRepository().followNew(expand).then((
|
||||
result,
|
||||
) {
|
||||
SCTts.show(
|
||||
SCAppLocalizations.of(context)!.followSucc,
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
@ -925,7 +937,8 @@ class _MessageItem extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy.getSCMessageChatPageMessageMenuDeleteIcon(),
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getSCMessageChatPageMessageMenuDeleteIcon(),
|
||||
width: 20.w,
|
||||
),
|
||||
SizedBox(height: 3.w),
|
||||
|
||||
@ -106,9 +106,7 @@ class _GiftPageState extends State<GiftPage> with TickerProviderStateMixin {
|
||||
Timer? _comboSendBatchTimer;
|
||||
bool _isComboSendBatchInFlight = false;
|
||||
|
||||
void _giftFxLog(String message) {
|
||||
debugPrint('[GiftFX][Send] $message');
|
||||
}
|
||||
void _giftFxLog(String message) {}
|
||||
|
||||
String _describeGiftSendError(Object error) {
|
||||
if (error is DioException) {
|
||||
|
||||
@ -120,7 +120,6 @@ class _HomeEventPageState extends State<HomeEventPage>
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
print('ads:${homeBanners[index].toJson()}');
|
||||
SCBannerUtils.openBanner(homeBanners[index], context);
|
||||
},
|
||||
child: netImage(
|
||||
|
||||
@ -74,9 +74,7 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
Provider.of<RtcProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).prewarmRtcEngine().catchError((error, stackTrace) {
|
||||
debugPrint('[Agora] prewarm on index failed: $error');
|
||||
}),
|
||||
).prewarmRtcEngine().catchError((error, stackTrace) {}),
|
||||
);
|
||||
Provider.of<RtmProvider>(context, listen: false).init(context);
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
@ -426,7 +424,6 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
if (!mounted) return;
|
||||
_taskClaimableCount.value = count;
|
||||
} catch (error) {
|
||||
debugPrint('[TaskCenter][TabBadge] load failed error=$error');
|
||||
if (!mounted) return;
|
||||
_taskClaimableCount.value = 0;
|
||||
}
|
||||
@ -437,7 +434,6 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
return;
|
||||
}
|
||||
_hasShownEntryDialogs = true;
|
||||
debugPrint('[SignInReward][Home] start entry dialog flow');
|
||||
|
||||
await _waitForRegisterRewardSocketIfNeeded();
|
||||
if (!mounted) {
|
||||
@ -456,18 +452,9 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
|
||||
final dialogData = await _loadDailySignInDialogData();
|
||||
if (!mounted || dialogData == null) {
|
||||
debugPrint(
|
||||
'[SignInReward][Home] skip daily sign-in dialog reason=no-data',
|
||||
);
|
||||
await _openFirstRegisterRoomGameIfNeeded();
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[SignInReward][Home] show daily sign-in dialog '
|
||||
'checkedToday=${dialogData.checkedToday} '
|
||||
'currentDay=${dialogData.currentItem?.day ?? 0} '
|
||||
'items=${dialogData.items.length}',
|
||||
);
|
||||
_isShowingDailySignInDialog = true;
|
||||
await DailySignInDialog.show(context, data: dialogData);
|
||||
_isShowingDailySignInDialog = false;
|
||||
@ -552,29 +539,13 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
|
||||
Future<DailySignInDialogData?> _loadDailySignInDialogData() async {
|
||||
try {
|
||||
debugPrint('[SignInReward][Home] loading status');
|
||||
final statusRes = await SCAccountRepository().signInRewardStatus();
|
||||
if (!statusRes.canShowDialog) {
|
||||
debugPrint(
|
||||
'[SignInReward][Home] dialog disabled '
|
||||
'configured=${statusRes.configured} '
|
||||
'enabled=${statusRes.enabled} '
|
||||
'available=${statusRes.available} '
|
||||
'signedToday=${statusRes.signedToday} '
|
||||
'days=${statusRes.days.length}',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
final dialogData = DailySignInDialogData.fromStatus(statusRes: statusRes);
|
||||
debugPrint(
|
||||
'[SignInReward][Home] mapped dialog data '
|
||||
'checkedToday=${dialogData.checkedToday} '
|
||||
'currentDay=${dialogData.currentItem?.day ?? 0} '
|
||||
'days=${dialogData.items.length}',
|
||||
);
|
||||
return dialogData;
|
||||
} catch (error) {
|
||||
debugPrint('[SignInReward][Home] load status failed error=$error');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -594,10 +565,8 @@ class _SCIndexPageState extends State<SCIndexPage>
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
debugPrint('[FirstRegisterGame] launch first party room random game');
|
||||
await SCEntryPopupCoordinator.openFirstPartyRoomRandomGame(context);
|
||||
} catch (error) {
|
||||
debugPrint('[FirstRegisterGame] launch failed error=$error');
|
||||
} finally {
|
||||
_isOpeningFirstRegisterRoomGame = false;
|
||||
}
|
||||
|
||||
@ -163,7 +163,6 @@ class SCMainRoute implements SCIRouterProvider {
|
||||
initialIndex = int.tryParse(params['initialIndex']!.first) ?? 0;
|
||||
}
|
||||
} catch (e) {
|
||||
print('解析图片预览参数失败: $e');
|
||||
// 可以返回错误页面或默认页面
|
||||
}
|
||||
|
||||
|
||||
@ -37,9 +37,6 @@ class RoomBackgroundApplyService {
|
||||
if (uploadedUrl.trim().isEmpty) {
|
||||
throw StateError("Uploaded background URL is empty");
|
||||
}
|
||||
debugPrint(
|
||||
"[Room Background Apply] source=$normalizedSource uploadedUrl=$uploadedUrl",
|
||||
);
|
||||
|
||||
final roomInfo = await SCAccountRepository().updateRoomBackground(
|
||||
roomId,
|
||||
@ -82,11 +79,7 @@ class RoomBackgroundApplyService {
|
||||
if (!sourceFile.existsSync()) {
|
||||
throw StateError("Room background source file does not exist");
|
||||
}
|
||||
debugPrint(
|
||||
"[Room Background Upload] upload local file path=${sourceFile.path} size=${sourceFile.lengthSync()}",
|
||||
);
|
||||
final uploadedUrl = await SCGeneralRepositoryImp().upload(sourceFile);
|
||||
debugPrint("[Room Background Upload] upload success url=$uploadedUrl");
|
||||
return uploadedUrl;
|
||||
}
|
||||
|
||||
@ -103,9 +96,6 @@ class RoomBackgroundApplyService {
|
||||
bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes),
|
||||
flush: true,
|
||||
);
|
||||
debugPrint(
|
||||
"[Room Background Upload] copied asset=$assetPath to temp=${file.path} size=${file.lengthSync()}",
|
||||
);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
@ -127,8 +127,6 @@ class _RoomBackgroundSelectPageState extends State<RoomBackgroundSelectPage>
|
||||
});
|
||||
SCTts.show(localizations.operationSuccessful);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint("[Room Background Select] apply failed error=$e");
|
||||
debugPrint("[Room Background Select] stackTrace=$stackTrace");
|
||||
if (mounted) {
|
||||
SCTts.show(localizations.operationFail);
|
||||
}
|
||||
|
||||
@ -66,8 +66,6 @@ class _RoomBackgroundUploadPageState extends State<RoomBackgroundUploadPage> {
|
||||
SCTts.show(localizations.operationSuccessful);
|
||||
SCNavigatorUtils.goBackWithParams(context, roomBackground);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint("[Room Background Save] failed error=$e");
|
||||
debugPrint("[Room Background Save] stackTrace=$stackTrace");
|
||||
if (mounted) {
|
||||
SCTts.show(localizations.operationFail);
|
||||
}
|
||||
|
||||
@ -183,9 +183,6 @@ class _RoomEditPageState extends State<RoomEditPage> {
|
||||
bool success,
|
||||
String url,
|
||||
) {
|
||||
debugPrint(
|
||||
"[Room Cover] upload callback success=$success url=$url",
|
||||
);
|
||||
if (success) {
|
||||
setState(() {
|
||||
roomCover = url;
|
||||
@ -530,9 +527,6 @@ class _RoomEditPageState extends State<RoomEditPage> {
|
||||
return;
|
||||
}
|
||||
SCLoadingManager.show(context: context);
|
||||
debugPrint(
|
||||
"[Room Cover] submit roomId=${rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? ""} roomCover=$submittedRoomCover roomName=$submittedRoomName roomDesc=$submittedRoomDesc",
|
||||
);
|
||||
var roomInfo = await SCAccountRepository().editRoomInfo(
|
||||
rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "",
|
||||
submittedRoomCover,
|
||||
@ -540,7 +534,6 @@ class _RoomEditPageState extends State<RoomEditPage> {
|
||||
submittedRoomDesc,
|
||||
SCRoomInfoEventType.AVAILABLE.name,
|
||||
);
|
||||
debugPrint("[Room Cover] editRoomInfo response: ${roomInfo.toJson()}");
|
||||
if (!context.mounted) {
|
||||
SCLoadingManager.hide();
|
||||
return;
|
||||
@ -557,9 +550,6 @@ class _RoomEditPageState extends State<RoomEditPage> {
|
||||
);
|
||||
roomManager.updateMyRoomInfo(mergedRoomInfo);
|
||||
if (widget.needRestCurrentRoomInfo != "true") {
|
||||
debugPrint(
|
||||
"[Room Cover Sync] dispatch roomSettingUpdate groupId=${rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount ?? ""} roomId=${mergedRoomInfo.id ?? rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? ""}",
|
||||
);
|
||||
currentRtmProvider.dispatchMessage(
|
||||
Msg(
|
||||
groupId:
|
||||
|
||||
@ -109,7 +109,6 @@ class VoiceRoomRoute implements SCIRouterProvider {
|
||||
}) {
|
||||
final navigator = Navigator.of(context, rootNavigator: rootNavigator);
|
||||
if (!replace && isVoiceRoomOpen) {
|
||||
debugPrint('[RoomRoute] skip duplicate voice room route');
|
||||
return Future<T?>.value();
|
||||
}
|
||||
final route = _buildRoute<T>(
|
||||
|
||||
@ -412,9 +412,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
|
||||
return '';
|
||||
}
|
||||
|
||||
void _log(String message) {
|
||||
debugPrint('$_logPrefix $message');
|
||||
}
|
||||
void _log(String message) {}
|
||||
|
||||
String _clip(String value, [int limit = 600]) {
|
||||
final trimmed = value.trim();
|
||||
|
||||
@ -385,9 +385,7 @@ class _LeaderGamePageState extends State<LeaderGamePage> {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
void _log(String message) {
|
||||
debugPrint('$_logPrefix $message');
|
||||
}
|
||||
void _log(String message) {}
|
||||
|
||||
String _maskValue(String value, {int keepStart = 6, int keepEnd = 4}) {
|
||||
final trimmed = value.trim();
|
||||
@ -523,7 +521,7 @@ class _LeaderGamePageState extends State<LeaderGamePage> {
|
||||
<h3>Leader Mock</h3>
|
||||
<p>Use these buttons to verify bridge wiring.</p>
|
||||
<button onclick="loadComplete()">loadComplete()</button>
|
||||
<button onclick="console.log(getConfig && getConfig())">getConfig()</button>
|
||||
<button onclick="getConfig && getConfig()">getConfig()</button>
|
||||
<button onclick="pay()">pay()</button>
|
||||
<button onclick="closeGame()">closeGame()</button>
|
||||
<button onclick="window.updateCoin && window.updateCoin()">updateCoin()</button>
|
||||
|
||||
@ -175,9 +175,7 @@ class _RoomGameListSheetState extends State<RoomGameListSheet> {
|
||||
}
|
||||
}
|
||||
|
||||
void _log(String message) {
|
||||
debugPrint('$_logPrefix $message');
|
||||
}
|
||||
void _log(String message) {}
|
||||
|
||||
String _clip(String value, [int limit = 600]) {
|
||||
final trimmed = value.trim();
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||||
|
||||
class LastWeeklyCPSplashEntry {
|
||||
@ -83,7 +82,6 @@ class LastWeeklyCPSplashCache {
|
||||
.toList()
|
||||
..sort((a, b) => a.rank.compareTo(b.rank));
|
||||
} catch (error, stackTrace) {
|
||||
debugPrint('LastWeeklyCPSplashCache parse failed: $error\n$stackTrace');
|
||||
return const [];
|
||||
}
|
||||
}
|
||||
@ -98,8 +96,6 @@ class LastWeeklyCPSplashCache {
|
||||
|
||||
try {
|
||||
// 当前占位逻辑已下线,等待正式 CP 榜接口接入。
|
||||
} catch (error, stackTrace) {
|
||||
debugPrint('LastWeeklyCPSplashCache refresh failed: $error\n$stackTrace');
|
||||
}
|
||||
} catch (error, stackTrace) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +495,6 @@ class _SplashPageState extends State<SplashPage> {
|
||||
await DataPersistence.clearPendingChannelAuth();
|
||||
return user;
|
||||
} catch (e) {
|
||||
debugPrint('restore login session failed: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_top_four_with_reward_res.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_config_repository_imp.dart';
|
||||
@ -72,7 +71,6 @@ class WeeklyStarSplashCache {
|
||||
.toList()
|
||||
..sort((a, b) => a.rank.compareTo(b.rank));
|
||||
} catch (error, stackTrace) {
|
||||
debugPrint('WeeklyStarSplashCache parse failed: $error\n$stackTrace');
|
||||
return const [];
|
||||
}
|
||||
}
|
||||
@ -95,9 +93,7 @@ class WeeklyStarSplashCache {
|
||||
_cacheKey,
|
||||
jsonEncode(entries.map((entry) => entry.toJson()).toList()),
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
debugPrint('WeeklyStarSplashCache refresh failed: $error\n$stackTrace');
|
||||
}
|
||||
} catch (error, stackTrace) {}
|
||||
}
|
||||
|
||||
static List<WeeklyStarSplashEntry> _mapTopThree(
|
||||
|
||||
@ -146,9 +146,6 @@ class _CropImageRouteState extends State<CropImagePage> {
|
||||
}) async {
|
||||
final originalExists = originalFile.existsSync();
|
||||
final originalSize = originalExists ? originalFile.lengthSync() : -1;
|
||||
debugPrint(
|
||||
"[Room Cover Upload] crop start originalPath=${originalFile.path} originalExists=$originalExists originalSize=$originalSize needUpload=$needUpload aspectRatio=${widget.aspectRatio}",
|
||||
);
|
||||
// 调用系统裁剪界面
|
||||
CroppedFile? cropped = await ImageCropper().cropImage(
|
||||
sourcePath: originalFile.path,
|
||||
@ -180,11 +177,7 @@ class _CropImageRouteState extends State<CropImagePage> {
|
||||
if (cropped == null) {
|
||||
if (widget.backOriginalFile ?? true) {
|
||||
fileToUpload = originalFile;
|
||||
debugPrint(
|
||||
"[Room Cover Upload] crop cancelled, fallback to original file path=${fileToUpload.path}",
|
||||
);
|
||||
} else {
|
||||
debugPrint("[Room Cover Upload] crop cancelled, no fallback file");
|
||||
widget.onUpLoadCallBack?.call(false, "");
|
||||
return;
|
||||
}
|
||||
@ -192,9 +185,6 @@ class _CropImageRouteState extends State<CropImagePage> {
|
||||
fileToUpload = File(cropped.path);
|
||||
final croppedExists = fileToUpload.existsSync();
|
||||
final croppedSize = croppedExists ? fileToUpload.lengthSync() : -1;
|
||||
debugPrint(
|
||||
"[Room Cover Upload] crop result path=${fileToUpload.path} exists=$croppedExists size=$croppedSize",
|
||||
);
|
||||
}
|
||||
if (needUpload) {
|
||||
// 弹出上传中的 loading
|
||||
@ -211,20 +201,12 @@ class _CropImageRouteState extends State<CropImagePage> {
|
||||
try {
|
||||
final fileExists = file.existsSync();
|
||||
final fileSize = fileExists ? file.lengthSync() : -1;
|
||||
debugPrint(
|
||||
"[Room Cover Upload] local file before request path=${file.path} exists=$fileExists size=$fileSize",
|
||||
);
|
||||
String fileUrl = await SCGeneralRepositoryImp().upload(file);
|
||||
debugPrint("[Room Cover Upload] upload success fileUrl=$fileUrl");
|
||||
SCLoadingManager.hide();
|
||||
SCNavigatorUtils.goBack(context);
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
widget.onUpLoadCallBack?.call(true, fileUrl);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint(
|
||||
"[Room Cover Upload] upload failed path=${file.path} error=$e",
|
||||
);
|
||||
debugPrint("[Room Cover Upload] stackTrace=$stackTrace");
|
||||
SCTts.show("upload fail $e");
|
||||
SCLoadingManager.hide();
|
||||
}
|
||||
|
||||
@ -223,7 +223,6 @@ class _EditUserInfoPage2State extends State<EditUserInfoPage2>
|
||||
String url,
|
||||
) {
|
||||
if (success) {
|
||||
debugPrint("[Profile Avatar] uploaded url: $url");
|
||||
userCover = url;
|
||||
setState(() {});
|
||||
submitAvatarOnly();
|
||||
@ -432,9 +431,6 @@ class _EditUserInfoPage2State extends State<EditUserInfoPage2>
|
||||
}
|
||||
_isSubmitting = true;
|
||||
SCLoadingManager.show();
|
||||
debugPrint(
|
||||
"[Profile Edit] incremental payload: {userAvatar: ${identical(userAvatarValue, _noChange) ? "<skip>" : userAvatarValue}, userNickname: ${identical(userNicknameValue, _noChange) ? "<skip>" : userNicknameValue}, userSex: ${identical(userSexValue, _noChange) ? "<skip>" : userSexValue}, age: ${identical(ageValue, _noChange) ? "<skip>" : ageValue}, bornYear: ${identical(bornYearValue, _noChange) ? "<skip>" : bornYearValue}, bornMonth: ${identical(bornMonthValue, _noChange) ? "<skip>" : bornMonthValue}, bornDay: ${identical(bornDayValue, _noChange) ? "<skip>" : bornDayValue}, hobby: ${identical(hobbyValue, _noChange) ? "<skip>" : hobbyValue}, autograph: ${identical(autographValue, _noChange) ? "<skip>" : autographValue}}",
|
||||
);
|
||||
try {
|
||||
final updatedProfile = await SCAccountRepository().updateUserInfo(
|
||||
userAvatar:
|
||||
@ -507,9 +503,6 @@ class _EditUserInfoPage2State extends State<EditUserInfoPage2>
|
||||
? birthdayDate?.year
|
||||
: bornYearValue as num?),
|
||||
);
|
||||
debugPrint(
|
||||
"[Profile Edit] merged profile avatar: ${mergedProfile.userAvatar ?? ""}",
|
||||
);
|
||||
_syncLocalProfileState(mergedProfile);
|
||||
if (!mounted) {
|
||||
return;
|
||||
@ -523,7 +516,6 @@ class _EditUserInfoPage2State extends State<EditUserInfoPage2>
|
||||
setState(() {});
|
||||
SCTts.show(SCAppLocalizations.of(context)!.operationSuccessful);
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
} finally {
|
||||
_isSubmitting = false;
|
||||
SCLoadingManager.hide();
|
||||
|
||||
@ -79,12 +79,6 @@ class _MePage2State extends State<MePage2> {
|
||||
|
||||
try {
|
||||
final status = await _loadVipEntryStatus();
|
||||
debugPrint(
|
||||
'[VIP][MeEntry] status loaded active=${status.active} '
|
||||
'level=${status.level} levelCode=${status.levelCode} '
|
||||
'expireAt=${status.expireAt} '
|
||||
'badge=${_vipEntryBadgeLogValue(status.badge)}',
|
||||
);
|
||||
if (!mounted) return;
|
||||
_syncCurrentProfileVipStatus(status);
|
||||
setState(() {
|
||||
@ -92,7 +86,6 @@ class _MePage2State extends State<MePage2> {
|
||||
_isVipStatusLoading = false;
|
||||
});
|
||||
} catch (error) {
|
||||
debugPrint('[VIP][MeEntry] status load failed error=$error');
|
||||
if (!mounted) return;
|
||||
setState(() => _isVipStatusLoading = false);
|
||||
}
|
||||
@ -104,13 +97,9 @@ class _MePage2State extends State<MePage2> {
|
||||
final home = await repository.vipHome();
|
||||
final state = home.state;
|
||||
if (state != null && state.levelInt > 0) {
|
||||
debugPrint('[VIP][MeEntry] use vip home state');
|
||||
return state;
|
||||
}
|
||||
debugPrint('[VIP][MeEntry] vip home state empty, fallback status');
|
||||
} catch (error) {
|
||||
debugPrint('[VIP][MeEntry] vip home load failed error=$error');
|
||||
}
|
||||
} catch (error) {}
|
||||
return repository.vipStatus();
|
||||
}
|
||||
|
||||
@ -134,7 +123,6 @@ class _MePage2State extends State<MePage2> {
|
||||
}
|
||||
|
||||
void _refreshAfterVipReturn(SocialChatUserProfileManager profileManager) {
|
||||
debugPrint('[VIP][MeEntry] refresh user data after vip page return');
|
||||
profileManager.fetchUserProfileData(loadGuardCount: false);
|
||||
profileManager.balance();
|
||||
_loadCounter();
|
||||
|
||||
@ -595,7 +595,6 @@ class _GiftWallSvgaEffectOverlayState extends State<_GiftWallSvgaEffectOverlay>
|
||||
..reset()
|
||||
..repeat(count: 1);
|
||||
} catch (error) {
|
||||
debugPrint("[GiftWallSVGA] load failed ${widget.sourceUrl}: $error");
|
||||
_finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,6 @@ class _TaskPageState extends State<TaskPage>
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
debugPrint('[TaskCenter][Page] refresh on app resumed');
|
||||
unawaited(_loadTasks());
|
||||
_scheduleTaskStatusCacheRefresh('app resumed');
|
||||
}
|
||||
@ -81,18 +80,15 @@ class _TaskPageState extends State<TaskPage>
|
||||
|
||||
@override
|
||||
void didPopNext() {
|
||||
debugPrint('[TaskCenter][Page] refresh on route return');
|
||||
unawaited(_loadTasks());
|
||||
_scheduleTaskStatusCacheRefresh('route return');
|
||||
}
|
||||
|
||||
Future<void> _loadTasks() async {
|
||||
if (_loadingTasks) {
|
||||
debugPrint('[TaskCenter][Page] load skipped: request in flight');
|
||||
return;
|
||||
}
|
||||
_loadingTasks = true;
|
||||
debugPrint('[TaskCenter][Page] load start');
|
||||
try {
|
||||
final tasks = await _repository.tasks();
|
||||
if (!mounted) return;
|
||||
@ -101,18 +97,12 @@ class _TaskPageState extends State<TaskPage>
|
||||
final dailyCount =
|
||||
sortedTasks.where((task) => (task.taskType ?? 0).toInt() == 0).length;
|
||||
final exclusiveCount = sortedTasks.length - dailyCount;
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] load success total=${sortedTasks.length} '
|
||||
'daily=$dailyCount exclusive=$exclusiveCount '
|
||||
'sample=${_taskDebugSample(sortedTasks)}',
|
||||
);
|
||||
setState(() {
|
||||
_tasks = sortedTasks;
|
||||
_loading = false;
|
||||
});
|
||||
widget.onTaskStatusChanged?.call();
|
||||
} catch (error) {
|
||||
debugPrint('[TaskCenter][Page] load failed error=$error');
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_tasks = [];
|
||||
@ -130,16 +120,9 @@ class _TaskPageState extends State<TaskPage>
|
||||
|
||||
void _scheduleTaskStatusCacheRefresh(String reason) {
|
||||
_cacheRefreshTimer?.cancel();
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] schedule cache refresh reason=$reason '
|
||||
'delayMs=${_taskStatusCacheRefreshDelay.inMilliseconds}',
|
||||
);
|
||||
_cacheRefreshTimer = Timer(_taskStatusCacheRefreshDelay, () {
|
||||
_cacheRefreshTimer = null;
|
||||
if (!mounted) return;
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] refresh after cache window reason=$reason',
|
||||
);
|
||||
unawaited(_loadTasks());
|
||||
});
|
||||
}
|
||||
@ -271,10 +254,6 @@ class _TaskPageState extends State<TaskPage>
|
||||
List<_TaskUiItem> dailyTasks,
|
||||
List<_TaskUiItem> newcomerTasks,
|
||||
) {
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] build sections raw=${_tasks.length} '
|
||||
'daily=${dailyTasks.length} exclusive=${newcomerTasks.length}',
|
||||
);
|
||||
final sections = <Widget>[];
|
||||
final l10n = SCAppLocalizations.of(context)!;
|
||||
if (dailyTasks.isNotEmpty) {
|
||||
@ -376,18 +355,10 @@ class _TaskPageState extends State<TaskPage>
|
||||
}
|
||||
|
||||
Future<void> _handleTaskAction(_TaskUiItem task) async {
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] action id=${task.id} status=${task.status.name} '
|
||||
'fromApi=${task.fromApi} conditionType=${task.conditionType} '
|
||||
'jumpType=${task.jumpType} jumpPage=${task.jumpPage} '
|
||||
'roomId=${task.roomId} roomTask=${task.roomTask} '
|
||||
'gameTask=${task.gameTask}',
|
||||
);
|
||||
if (task.status == _TaskActionStatus.claimed) return;
|
||||
if (task.status == _TaskActionStatus.go) {
|
||||
final opened = await _openJumpPage(task);
|
||||
if (opened && mounted) {
|
||||
debugPrint('[TaskCenter][Page] refresh after jump return');
|
||||
unawaited(_loadTasks());
|
||||
_scheduleTaskStatusCacheRefresh('jump return');
|
||||
}
|
||||
@ -424,10 +395,6 @@ class _TaskPageState extends State<TaskPage>
|
||||
var path = uri?.path ?? '';
|
||||
var roomId = uri?.queryParameters['roomId']?.trim() ?? '';
|
||||
if ((path == '/room' || path == '/game-center') && roomId.isEmpty) {
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] room jump missing roomId, fallback first room '
|
||||
'target=$target taskId=${task.id}',
|
||||
);
|
||||
final fallbackTarget = await _firstRoomJumpUrl(target);
|
||||
if (!mounted) return false;
|
||||
if (fallbackTarget.isEmpty) {
|
||||
@ -441,10 +408,6 @@ class _TaskPageState extends State<TaskPage>
|
||||
}
|
||||
|
||||
final jumpType = _taskJumpType(task, target);
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] open jump type=$jumpType url=$target '
|
||||
'taskId=${task.id}',
|
||||
);
|
||||
await SCEntryPopupCoordinator.openConfiguredJump(
|
||||
context,
|
||||
jumpType: jumpType,
|
||||
@ -460,16 +423,9 @@ class _TaskPageState extends State<TaskPage>
|
||||
final roomId = room.id?.trim() ?? '';
|
||||
if (roomId.isEmpty) continue;
|
||||
final resolvedTarget = _withRoomId(target, roomId);
|
||||
debugPrint(
|
||||
'[TaskCenter][Page] fallback first room roomId=$roomId '
|
||||
'target=$resolvedTarget',
|
||||
);
|
||||
return resolvedTarget;
|
||||
}
|
||||
debugPrint('[TaskCenter][Page] fallback first room empty list');
|
||||
} catch (error) {
|
||||
debugPrint('[TaskCenter][Page] fallback first room failed error=$error');
|
||||
}
|
||||
} catch (error) {}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
final results = await Future.wait<dynamic>([
|
||||
_repository.vipHome(),
|
||||
_repository.vipStatus().catchError((error) {
|
||||
debugPrint('VIP status load failed: $error');
|
||||
return SCVipStatusRes();
|
||||
}),
|
||||
]);
|
||||
@ -155,11 +154,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
if (_home?.configured == false ||
|
||||
config?.enabled == false ||
|
||||
config?.canPurchase != true) {
|
||||
debugPrint(
|
||||
'[VIP][Page] skip preview level=$level '
|
||||
'configured=${_home?.configured} enabled=${config?.enabled} '
|
||||
'canPurchase=${config?.canPurchase}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -201,17 +195,12 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
|
||||
if (!mounted) return;
|
||||
if (purchase.success == true) {
|
||||
debugPrint(
|
||||
'[VIP][Page] purchase success targetLevel=$_selectedLevel '
|
||||
'orderId=${purchase.order?.id} paidGold=${purchase.order?.paidGold}',
|
||||
);
|
||||
SCTts.show(SCAppLocalizations.of(context)!.purchaseIsSuccessful);
|
||||
profileManager.fetchUserProfileData(loadGuardCount: false);
|
||||
profileManager.balance();
|
||||
await _loadVipData(showLoading: false);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint('VIP purchase failed: $error');
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
if (mounted) {
|
||||
@ -230,24 +219,8 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
SCVipStatusRes? status,
|
||||
int selectedLevel,
|
||||
) {
|
||||
debugPrint(
|
||||
'[VIP][Page] home loaded configured=${home.configured} '
|
||||
'levels=${home.levels.length} selectedLevel=$selectedLevel '
|
||||
'statusActive=${status?.active} statusLevel=${status?.level} '
|
||||
'statusExpireAt=${status?.expireAt}',
|
||||
);
|
||||
if (home.configured != true) {
|
||||
debugPrint(
|
||||
'[VIP][Page][Warn] vip home configured=${home.configured}; '
|
||||
'check backend VIP config for sysOrigin=${home.sysOrigin}',
|
||||
);
|
||||
}
|
||||
if (home.levels.isEmpty) {
|
||||
debugPrint(
|
||||
'[VIP][Page][Warn] vip home levels is empty; '
|
||||
'frontend has no level data to render.',
|
||||
);
|
||||
}
|
||||
if (home.configured != true) {}
|
||||
if (home.levels.isEmpty) {}
|
||||
_logSelectedLevelResources(
|
||||
selectedLevel,
|
||||
config: _levelConfigFromHome(home, selectedLevel),
|
||||
@ -262,9 +235,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
}) {
|
||||
final state = status?.levelInt == level ? status : null;
|
||||
if (config == null && state == null) {
|
||||
debugPrint(
|
||||
'[VIP][Page][Warn] selected level=$level has no config or state',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final badge = _preferResource(config?.badge, state?.badge);
|
||||
@ -281,14 +251,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
config?.floatPicture,
|
||||
state?.floatPicture,
|
||||
);
|
||||
debugPrint(
|
||||
'[VIP][Page] selected level resources level=$level '
|
||||
'badge=${_resourceLogValue(badge)} '
|
||||
'avatarFrame=${_resourceLogValue(avatarFrame)} '
|
||||
'entryEffect=${_resourceLogValue(entryEffect)} '
|
||||
'chatBubble=${_resourceLogValue(chatBubble)} '
|
||||
'floatPicture=${_resourceLogValue(floatPicture)}',
|
||||
);
|
||||
}
|
||||
|
||||
String _resourceLogValue(SCVipResourceRes? resource) {
|
||||
|
||||
@ -230,9 +230,7 @@ class _WebViewPageState extends State<WebViewPage> {
|
||||
_title = title.replaceAll("\"", "");
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print("获取标题失败: $e");
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -312,7 +310,6 @@ class _WebViewPageState extends State<WebViewPage> {
|
||||
}
|
||||
|
||||
void _onWebResourceError(WebResourceError error) {
|
||||
print('_onWebResourceError:${error.description}');
|
||||
// 可以在这里添加错误处理逻辑,比如显示错误页面
|
||||
}
|
||||
}
|
||||
|
||||
@ -1452,9 +1452,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_resetAgoraTracking();
|
||||
try {
|
||||
await engine?.leaveChannel();
|
||||
} catch (error) {
|
||||
debugPrint('[Agora] leave channel during cleanup failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
if (clearMicSeats) {
|
||||
roomWheatMap.clear();
|
||||
notifyListeners();
|
||||
@ -1470,16 +1468,13 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
}
|
||||
try {
|
||||
await rtcEngine.leaveChannel();
|
||||
} catch (error) {
|
||||
debugPrint('[RoomExit] leave Agora channel failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
Future<void> _handleAgoraJoinFailed(
|
||||
Object error, {
|
||||
required bool exitRoom,
|
||||
}) async {
|
||||
debugPrint('[Agora] join failed: $error');
|
||||
await _cleanupAgoraRoomState(clearMicSeats: true);
|
||||
if (!exitRoom || _isExitingCurrentVoiceRoomSession) {
|
||||
return;
|
||||
@ -1493,7 +1488,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
_isHandlingAgoraRoomFailure = true;
|
||||
debugPrint('[Agora] disconnected, leave room: $reason');
|
||||
SCTts.show("Voice connection failed");
|
||||
await _cleanupAgoraRoomState(clearMicSeats: true);
|
||||
await exitCurrentVoiceRoomSession(false);
|
||||
@ -1528,7 +1522,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
await _configureAgoraAudioEngine(rtcEngine);
|
||||
} catch (error, stackTrace) {
|
||||
_rtcEnginePrewarmTask = null;
|
||||
debugPrint('[Agora] prewarm failed: $error\n$stackTrace');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@ -1575,9 +1568,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
if (pendingRoomSwitchLeaveTask != null) {
|
||||
try {
|
||||
await pendingRoomSwitchLeaveTask;
|
||||
} catch (error) {
|
||||
debugPrint('[Agora] pending room switch leave failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
_cancelAgoraJoinWaiter(const _AgoraJoinCanceled('Agora join superseded'));
|
||||
@ -1623,7 +1614,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
rtcEngine.muteAllRemoteAudioStreams(roomIsMute);
|
||||
} catch (e) {
|
||||
if (e is _AgoraJoinCanceled) {
|
||||
debugPrint('[Agora] join canceled: $e');
|
||||
if (throwOnError) {
|
||||
rethrow;
|
||||
}
|
||||
@ -1633,7 +1623,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
if (throwOnError) {
|
||||
rethrow;
|
||||
}
|
||||
debugPrint('加入失败:${e.runtimeType},${e.toString()}');
|
||||
} finally {
|
||||
if (identical(_joinAgoraCompleter, joinCompleter)) {
|
||||
_cancelAgoraJoinWaiter();
|
||||
@ -1665,7 +1654,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_resyncHeartbeatFromAgoraState();
|
||||
return true;
|
||||
} catch (error) {
|
||||
debugPrint('[Agora] switch to broadcaster failed: $error');
|
||||
_agoraRoleIsBroadcaster = false;
|
||||
_resyncHeartbeatFromAgoraState();
|
||||
return false;
|
||||
@ -1687,7 +1675,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_resyncHeartbeatFromAgoraState();
|
||||
return true;
|
||||
} catch (error) {
|
||||
debugPrint('[Agora] switch to audience failed: $error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1785,7 +1772,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
engine = rtcEngine;
|
||||
_rtcEngineEventHandler = RtcEngineEventHandler(
|
||||
onError: (ErrorCodeType err, String msg) {
|
||||
debugPrint('rtc错误$err');
|
||||
final error = 'Agora error: $err $msg';
|
||||
if (!_agoraJoined) {
|
||||
final completer = _joinAgoraCompleter;
|
||||
@ -1801,7 +1787,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
}
|
||||
},
|
||||
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
|
||||
debugPrint('rtc 自己加入 ${connection.channelId} ${connection.localUid}');
|
||||
final joinedChannelId = connection.channelId ?? "";
|
||||
if (!_isCurrentAgoraChannel(joinedChannelId)) {
|
||||
return;
|
||||
@ -1919,13 +1904,9 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
}
|
||||
_roomMusicMixingStateListener?.call(state, reason);
|
||||
},
|
||||
onUserJoined: (connection, remoteUid, elapsed) {
|
||||
debugPrint('rtc用户 $remoteUid 加入了频道');
|
||||
},
|
||||
onUserJoined: (connection, remoteUid, elapsed) {},
|
||||
// 监听远端用户离开
|
||||
onUserOffline: (connection, remoteUid, reason) {
|
||||
debugPrint('rtc用户 $remoteUid 离开了频道 (原因: $reason)');
|
||||
},
|
||||
onUserOffline: (connection, remoteUid, reason) {},
|
||||
onTokenPrivilegeWillExpire: (
|
||||
RtcConnection connection,
|
||||
String token,
|
||||
@ -1980,16 +1961,12 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
rtcEngine.unregisterEventHandler(eventHandler);
|
||||
}
|
||||
await rtcEngine.leaveChannel();
|
||||
} catch (e) {
|
||||
debugPrint('rtc销毁前离开频道出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
_resetAgoraTracking();
|
||||
|
||||
try {
|
||||
await rtcEngine.release();
|
||||
} catch (e) {
|
||||
debugPrint('rtc释放引擎出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
await SCVoiceRoomForegroundService.stop();
|
||||
}
|
||||
|
||||
@ -2002,7 +1979,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
// if (user == null) {
|
||||
// throw "本地User尚未初始化";
|
||||
// }
|
||||
// print('初始化声音监听器:${user.toJson()}');
|
||||
|
||||
if (roomWheatMap.isEmpty || speakers.isEmpty) {
|
||||
return;
|
||||
@ -2235,7 +2211,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
if (!_isActiveRoomEntryRequest(entryRequestSerial)) {
|
||||
return;
|
||||
}
|
||||
debugPrint('[RoomStartup] entry room failed: $e\n$stackTrace');
|
||||
_stopVoiceRoomForegroundService();
|
||||
_setRoomStartupFailed(RoomStartupFailureType.entry);
|
||||
}
|
||||
@ -2616,9 +2591,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
if (_isCurrentRoomId(staleRoomId)) {
|
||||
debugPrint(
|
||||
'[RoomStartup] skip stale entry cleanup: room $staleRoomId is active again',
|
||||
);
|
||||
return;
|
||||
}
|
||||
await _retryExitNetworkRequest('quit stale entered room $staleRoomId', () {
|
||||
@ -2701,9 +2673,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
if (joinResult == null || joinResult.code != 0) {
|
||||
debugPrint(
|
||||
'[RoomStartup] join IM group failed code=${joinResult?.code} desc=${joinResult?.desc}',
|
||||
);
|
||||
_stopVoiceRoomForegroundService();
|
||||
_setRoomStartupFailed(RoomStartupFailureType.im);
|
||||
return;
|
||||
@ -2776,10 +2745,8 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_loadRoomSecondaryData();
|
||||
} catch (error, stackTrace) {
|
||||
if (!_isActiveRoomStartup(entryRequestSerial, roomId)) {
|
||||
debugPrint('[RoomStartup] ignore canceled bootstrap failure: $error');
|
||||
return;
|
||||
}
|
||||
debugPrint('[RoomStartup] bootstrap failed: $error\n$stackTrace');
|
||||
_stopVoiceRoomForegroundService();
|
||||
_setRoomStartupFailed(failureType);
|
||||
}
|
||||
@ -2938,14 +2905,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
} catch (error) {
|
||||
if (_isMissingPathError(error)) {
|
||||
_disableOnlineUsersRefreshForCurrentSession = true;
|
||||
debugPrint(
|
||||
'[Room][OnlineUsers] suspend auto refresh for current session: ${_errorMessageFrom(error)}',
|
||||
);
|
||||
} else {
|
||||
debugPrint(
|
||||
'[Room][OnlineUsers] refresh failed: ${_errorMessageFrom(error)}',
|
||||
);
|
||||
}
|
||||
} else {}
|
||||
} finally {
|
||||
_isRefreshingOnlineUsers = false;
|
||||
}
|
||||
@ -2979,17 +2939,10 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
_disableMicListRefreshForCurrentSession = true;
|
||||
_deferredMicListRefreshTimer?.cancel();
|
||||
_deferredMicListRefreshTimer = null;
|
||||
debugPrint(
|
||||
'[Room][MicList] suspend auto refresh for current session: ${_errorMessageFrom(error)}',
|
||||
);
|
||||
if (notifyIfUnchanged) {
|
||||
notifyListeners();
|
||||
}
|
||||
} else {
|
||||
debugPrint(
|
||||
'[Room][MicList] refresh failed: ${_errorMessageFrom(error)}',
|
||||
);
|
||||
}
|
||||
} else {}
|
||||
} finally {
|
||||
_isRefreshingMicList = false;
|
||||
if (_pendingMicListRefresh) {
|
||||
@ -3119,11 +3072,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
}
|
||||
try {
|
||||
await loadRoomRedPacketList(1);
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][List] refresh after entry failed roomId=$roomId error=$error',
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
void _startRoomRedPacketPresenceHeartbeat(String roomId) {
|
||||
@ -3132,25 +3081,14 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
if (normalizedRoomId.isEmpty) {
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Presence] start heartbeat roomId=$normalizedRoomId',
|
||||
);
|
||||
void sendHeartbeat() {
|
||||
if (!_isCurrentRoomId(normalizedRoomId)) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Presence] stop heartbeat because room changed '
|
||||
'roomId=$normalizedRoomId current=${currenRoom?.roomProfile?.roomProfile?.id}',
|
||||
);
|
||||
_stopRoomRedPacketPresenceHeartbeat();
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Presence] heartbeat roomId=$normalizedRoomId',
|
||||
);
|
||||
SCChatRoomRepository()
|
||||
.roomRedPacketPresenceHeartbeat(normalizedRoomId)
|
||||
.catchError((e) {
|
||||
debugPrint('[RoomRedPacket][Presence] heartbeat failed: $e');
|
||||
return SCRoomRedPacketPresenceRes();
|
||||
});
|
||||
}
|
||||
@ -3164,7 +3102,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
|
||||
void _stopRoomRedPacketPresenceHeartbeat() {
|
||||
if (_roomRedPacketPresenceTimer != null) {
|
||||
debugPrint('[RoomRedPacket][Presence] stop heartbeat');
|
||||
_roomRedPacketPresenceTimer?.cancel();
|
||||
}
|
||||
_roomRedPacketPresenceTimer = null;
|
||||
@ -3193,9 +3130,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
SCHeartbeatUtils.cancelTimer();
|
||||
_stopRoomRedPacketPresenceHeartbeat();
|
||||
exitRtmProvider?.cleanRoomData();
|
||||
} catch (e) {
|
||||
debugPrint('rtc退出房间本地清理出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
_clearData();
|
||||
if (!isLogout && navigationContext != null) {
|
||||
@ -3233,9 +3168,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
SCHeartbeatUtils.cancelTimer();
|
||||
_stopRoomRedPacketPresenceHeartbeat();
|
||||
exitRtmProvider?.cleanRoomData();
|
||||
} catch (e) {
|
||||
debugPrint('rtc切换房间本地清理出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
_clearData();
|
||||
final agoraLeaveTask = _leaveAgoraRoomForExit();
|
||||
@ -3268,7 +3201,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
tasks.add(
|
||||
_retryExitNetworkRequest('heartbeat ONLINE', () async {
|
||||
if (currenRoom != null) {
|
||||
debugPrint('[RoomExit] skip ONLINE heartbeat: already in a room');
|
||||
return;
|
||||
}
|
||||
await SCHeartbeatUtils.scheduleHeartbeat(
|
||||
@ -3283,7 +3215,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
tasks.add(
|
||||
_retryExitNetworkRequest('quit IM group $groupId', () async {
|
||||
if (_isCurrentRoomGroup(groupId)) {
|
||||
debugPrint('[RoomExit] skip quitGroup: re-entered group $groupId');
|
||||
return;
|
||||
}
|
||||
await exitRtmProvider.quitGroup(groupId);
|
||||
@ -3302,7 +3233,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
tasks.add(
|
||||
_retryExitNetworkRequest('quit room $roomId', () async {
|
||||
if (_isCurrentRoomId(roomId)) {
|
||||
debugPrint('[RoomExit] skip quitRoom: re-entered room $roomId');
|
||||
return;
|
||||
}
|
||||
final didQuit = await SCAccountRepository().quitRoom(roomId);
|
||||
@ -3328,19 +3258,11 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
} catch (error, stackTrace) {
|
||||
lastError = error;
|
||||
lastStackTrace = stackTrace;
|
||||
debugPrint(
|
||||
'[RoomExit] $name failed attempt '
|
||||
'$attempt/$_exitNetworkRetryLimit: $error',
|
||||
);
|
||||
if (attempt < _exitNetworkRetryLimit) {
|
||||
await Future.delayed(_exitNetworkRetryDelay * attempt);
|
||||
}
|
||||
}
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomExit] $name failed after $_exitNetworkRetryLimit attempts, '
|
||||
'treat as backend/remote issue: $lastError\n$lastStackTrace',
|
||||
);
|
||||
}
|
||||
|
||||
bool _isCurrentRoomId(String roomId) {
|
||||
@ -3366,7 +3288,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
await _cleanupAgoraRoomState();
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
} catch (e) {
|
||||
debugPrint('rtc清理本地房间状态出错: $e');
|
||||
} finally {
|
||||
rtmProvider?.cleanRoomData();
|
||||
_clearData();
|
||||
@ -3405,7 +3326,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
await SCAccountRepository().quitRoom(roomId);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('rtc进房失败清理本地房间状态出错: $e');
|
||||
} finally {
|
||||
_clearData();
|
||||
_isHandlingRoomStartupFailure = false;
|
||||
@ -3633,12 +3553,10 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
|
||||
addSoundVoiceChangeListener(OnSoundVoiceChange onSoundVoiceChange) {
|
||||
_onSoundVoiceChangeList.add(onSoundVoiceChange);
|
||||
debugPrint('添加监听:${_onSoundVoiceChangeList.length}');
|
||||
}
|
||||
|
||||
removeSoundVoiceChangeListener(OnSoundVoiceChange onSoundVoiceChange) {
|
||||
_onSoundVoiceChangeList.remove(onSoundVoiceChange);
|
||||
debugPrint('删除监听:${_onSoundVoiceChangeList.length}');
|
||||
}
|
||||
|
||||
void shangMai(num index, {String? eventType, String? inviterId}) async {
|
||||
@ -3695,11 +3613,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
currenRoom?.roomProfile?.roomProfile?.id ?? "",
|
||||
targetIndex,
|
||||
);
|
||||
} catch (downError) {
|
||||
debugPrint(
|
||||
'[Agora] release backend mic after broadcaster switch failed: $downError',
|
||||
);
|
||||
}
|
||||
} catch (downError) {}
|
||||
_clearSelfMicSwitchGuard(clearPreferredIndex: true);
|
||||
_clearUserFromSeats(myUser?.id);
|
||||
_syncSelfMicRuntimeState();
|
||||
@ -3845,7 +3759,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
});
|
||||
} catch (e) {
|
||||
SCTts.show("kill the user fail");
|
||||
debugPrint('踢人下麦失败');
|
||||
}
|
||||
}
|
||||
|
||||
@ -3943,12 +3856,8 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
|
||||
Future<bool> loadRoomInfo(String roomId) async {
|
||||
try {
|
||||
debugPrint("[Room Cover Sync] loadRoomInfo start roomId=$roomId");
|
||||
final value = await SCChatRoomRepository().specific(roomId);
|
||||
final currentRoomProfile = currenRoom?.roomProfile?.roomProfile;
|
||||
debugPrint(
|
||||
"[Room Cover Sync] loadRoomInfo fetched roomId=${value.id ?? roomId} roomCover=${value.roomCover ?? ""} roomBackground=${value.roomBackground ?? ""} roomName=${value.roomName ?? ""}",
|
||||
);
|
||||
currenRoom = currenRoom?.copyWith(
|
||||
roomProfile: currenRoom?.roomProfile?.copyWith(
|
||||
roomCounter: value.counter ?? currenRoom?.roomProfile?.roomCounter,
|
||||
@ -3973,9 +3882,6 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
),
|
||||
),
|
||||
);
|
||||
debugPrint(
|
||||
"[Room Cover Sync] loadRoomInfo applied roomId=$roomId roomCover=${currenRoom?.roomProfile?.roomProfile?.roomCover ?? ""} roomBackground=${currenRoom?.roomProfile?.roomProfile?.roomBackground ?? ""}",
|
||||
);
|
||||
|
||||
///如果是游客禁止上麦,已经在麦上的游客需要下麦
|
||||
bool touristMike =
|
||||
|
||||
@ -115,9 +115,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
|
||||
BuildContext? context;
|
||||
|
||||
void _giftFxLog(String message) {
|
||||
debugPrint('[GiftFX][RTM] $message');
|
||||
}
|
||||
void _giftFxLog(String message) {}
|
||||
|
||||
void _enqueueGiftFloatingMessage(
|
||||
SCFloatingMessage message, {
|
||||
@ -510,7 +508,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
.getConversationList(nextSeq: '0', count: 100);
|
||||
List<V2TimConversation?>? conversationList =
|
||||
convList.data?.conversationList;
|
||||
print('conversationList:${conversationList?.length}');
|
||||
conversationMap.clear();
|
||||
if (conversationList != null) {
|
||||
for (V2TimConversation? conversation in conversationList) {
|
||||
@ -540,7 +537,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
.getConversationManager()
|
||||
.getTotalUnreadMessageCount();
|
||||
if (res.code == 0) {
|
||||
print('初始未读总数: ${res.data}');
|
||||
messageUnReadCount = res.data ?? 0;
|
||||
allUnReadCount =
|
||||
messageUnReadCount + activityUnReadCount + notifcationUnReadCount;
|
||||
@ -562,28 +558,20 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
userID: userModel.userProfile?.id ?? "",
|
||||
userSig: userModel.userSig ?? "",
|
||||
);
|
||||
print(
|
||||
'tim voLogin:${res.code},${userModel.userProfile?.id},${userModel.userSig}',
|
||||
);
|
||||
if (res.code == 0) {
|
||||
isLogout = false;
|
||||
// 登录成功逻辑
|
||||
logined = true;
|
||||
print('tim 登录成功');
|
||||
await initConversation();
|
||||
unawaited(syncRoomRedPacketBroadcastGroup());
|
||||
} else {
|
||||
// 登录失败逻辑
|
||||
//print('timm 需要重新登录2');
|
||||
print('tim 登录失败${res.code}');
|
||||
SCTts.show('tim login fail');
|
||||
}
|
||||
} else {
|
||||
//print('timm 需要重新登录sign');
|
||||
SCTts.show('tim login fail');
|
||||
}
|
||||
} catch (e) {
|
||||
//print('timm 登录异常:${e.toString()}');
|
||||
SCTts.show('timm login fail:${e.toString()}');
|
||||
}
|
||||
userModel = AccountStorage().getCurrentUser();
|
||||
@ -601,10 +589,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
if (_shouldRouteUntrackedRoomRedPacketBroadcast(groupId, message)) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] route untracked group as region broadcast '
|
||||
'group=$groupId cachedRegionGroup=$roomRedPacketBroadcastGroupId',
|
||||
);
|
||||
_newBroadCastMsgRecv(groupId, message, forceRegionBroadcast: true);
|
||||
return;
|
||||
}
|
||||
@ -674,24 +658,13 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
Future<void> syncRoomRedPacketBroadcastGroup() async {
|
||||
for (var attempt = 0; attempt < 3 && !isLogout; attempt++) {
|
||||
try {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] sync region group attempt=${attempt + 1}',
|
||||
);
|
||||
final group = await SCChatRoomRepository().roomRedPacketImGroup();
|
||||
if (!group.canJoin) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] skip join configured=${group.configured} '
|
||||
'groupId=${group.groupId} region=${group.regionCode} status=${group.status}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final newGroupId = group.groupId.trim();
|
||||
if (newGroupId == roomRedPacketBroadcastGroupId) {
|
||||
roomRedPacketBroadcastRegionCode = group.regionCode.trim();
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] region group unchanged group=$newGroupId '
|
||||
'region=${group.regionCode}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final joinResult = await TencentImSDKPlugin.v2TIMManager.joinGroup(
|
||||
@ -707,17 +680,9 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
oldGroupId != newGroupId) {
|
||||
unawaited(quitGroup(oldGroupId));
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] joined region group=$newGroupId region=${group.regionCode}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] join group failed code=${joinResult.code} desc=${joinResult.desc}',
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('[RoomRedPacket][IM] sync group failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
await Future.delayed(Duration(milliseconds: 550));
|
||||
}
|
||||
}
|
||||
@ -771,7 +736,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
print('发送消息失败: $e');
|
||||
// 处理发送失败的情况
|
||||
}
|
||||
}
|
||||
@ -953,7 +917,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
message?.isSelf = true;
|
||||
// message.conversation = conversation;
|
||||
message?.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
|
||||
print('组装完成,准备发送:${message?.toJson()}');
|
||||
// String id = await FTIM.getMessageManager().sendMessage(message);
|
||||
// message.msgId = id;
|
||||
V2TimValueCallback<V2TimMessage> sendMessageRes =
|
||||
@ -992,11 +955,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
'giftPhoto=${msg.gift?.giftPhoto}',
|
||||
);
|
||||
}
|
||||
if (msg.type == SCRoomMsgType.roomSettingUpdate) {
|
||||
debugPrint(
|
||||
"[Room Cover Sync] send roomSettingUpdate groupId=${msg.groupId ?? ""} roomId=${msg.msg ?? ""}",
|
||||
);
|
||||
}
|
||||
if (msg.type == SCRoomMsgType.roomSettingUpdate) {}
|
||||
var user = msg.user?.copyWith();
|
||||
var toUser = msg.toUser?.copyWith();
|
||||
user?.cleanWearHonor();
|
||||
@ -1089,17 +1048,10 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
lastMsgID: null,
|
||||
);
|
||||
final messages = result.data ?? const <V2TimMessage>[];
|
||||
debugPrint(
|
||||
'[RoomHistory][IM] loaded group=$normalizedGroupId count=${messages.length}',
|
||||
);
|
||||
for (final message in messages.reversed) {
|
||||
_addRoomHistoryMessage(normalizedGroupId, message);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[RoomHistory][IM] load failed group=$normalizedGroupId error=$error',
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
void _addRoomHistoryMessage(String groupId, V2TimMessage message) {
|
||||
@ -1133,11 +1085,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
if (_shouldAddRoomHistoryMessage(msg)) {
|
||||
addMsg(msg);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[RoomHistory][IM] skip malformed msg=${message.msgID ?? ""} error=$error',
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
bool _shouldAddRoomHistoryMessage(Msg msg) {
|
||||
@ -1170,22 +1118,15 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
}
|
||||
if (msg.type == SCRoomMsgType.roomRedPacket &&
|
||||
_hasRoomRedPacketMessage(msg)) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Chat] skip duplicate packetId=${_roomRedPacketMessageKey(msg)}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (msg.type == SCRoomMsgType.roomRedPacketClaim &&
|
||||
_hasRoomRedPacketClaimMessage(msg)) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Claim] skip duplicate key=${_roomRedPacketClaimMessageKey(msg)}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
roomAllMsgList.insert(0, msg);
|
||||
if (roomAllMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomAllMsgList.removeAt(roomAllMsgList.length - 1);
|
||||
}
|
||||
msgAllListener?.call(msg);
|
||||
@ -1193,7 +1134,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
if (msg.type == SCRoomMsgType.text) {
|
||||
roomChatMsgList.insert(0, msg);
|
||||
if (roomChatMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
|
||||
}
|
||||
msgChatListener?.call(msg);
|
||||
@ -1201,21 +1141,18 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
(msg.type == SCRoomMsgType.emoticons && (msg.number ?? -1) < 0)) {
|
||||
roomChatMsgList.insert(0, msg);
|
||||
if (roomChatMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
|
||||
}
|
||||
msgChatListener?.call(msg);
|
||||
} else if (msg.type == SCRoomMsgType.roomRedPacket) {
|
||||
roomChatMsgList.insert(0, msg);
|
||||
if (roomChatMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
|
||||
}
|
||||
msgChatListener?.call(msg);
|
||||
} else if (msg.type == SCRoomMsgType.roomRedPacketClaim) {
|
||||
roomChatMsgList.insert(0, msg);
|
||||
if (roomChatMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
|
||||
}
|
||||
msgChatListener?.call(msg);
|
||||
@ -1223,7 +1160,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
roomGiftMsgList.insert(0, msg);
|
||||
if (roomGiftMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomGiftMsgList.removeAt(roomGiftMsgList.length - 1);
|
||||
}
|
||||
msgGiftListener?.call(msg);
|
||||
@ -1628,27 +1564,18 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
void _handleRegionGiftBroadcast(dynamic data) {
|
||||
final payload = _broadcastPayloadMap(data);
|
||||
if (payload.isEmpty) {
|
||||
debugPrint('[RoomRegionBroadcast][Gift] skip empty payload');
|
||||
return;
|
||||
}
|
||||
if (!_isSameRegionBroadcastPayload(payload)) {
|
||||
final payloadRegion = _payloadText(payload['regionCode']);
|
||||
debugPrint(
|
||||
'[RoomRegionBroadcast][Gift] skip region mismatch '
|
||||
'payloadRegion=$payloadRegion currentRegion=$roomRedPacketBroadcastRegionCode',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final roomId = _payloadText(payload['roomId']);
|
||||
if (roomId.isEmpty) {
|
||||
debugPrint('[RoomRegionBroadcast][Gift] skip empty roomId');
|
||||
return;
|
||||
}
|
||||
if (_isCurrentVoiceRoom(roomId)) {
|
||||
debugPrint(
|
||||
'[RoomRegionBroadcast][Gift] skip current room duplicate roomId=$roomId',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1707,10 +1634,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
priority: 900,
|
||||
);
|
||||
|
||||
debugPrint(
|
||||
'[RoomRegionBroadcast][Gift] enqueue roomId=$roomId giftId=$giftId '
|
||||
'sender=$senderId amount=$amount quantity=$quantity giftUrl=$giftUrl',
|
||||
);
|
||||
_enqueueGiftFloatingMessage(
|
||||
message,
|
||||
dedupKey: _giftFloatingDedupKey(
|
||||
@ -1744,10 +1667,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
);
|
||||
final localGift = appGeneralManager.getGiftByIdOrStandardId(giftId);
|
||||
final localGiftPhoto = (localGift?.giftPhoto ?? '').trim();
|
||||
debugPrint(
|
||||
'[RoomRegionBroadcast][Gift] resolve gift photo giftId=$giftId '
|
||||
'localPhoto=$localGiftPhoto fallbackUrl=$fallbackUrl',
|
||||
);
|
||||
if (localGiftPhoto.isNotEmpty) {
|
||||
return localGiftPhoto;
|
||||
}
|
||||
@ -2039,22 +1958,7 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
final payload = _broadcastPayloadMap(fData);
|
||||
final packetId = _payloadText(payload['packetId']);
|
||||
final packetRoomId = _payloadText(payload["roomId"]);
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] recv broadcast packetId=$packetId '
|
||||
'roomId=$packetRoomId group=$groupID '
|
||||
'regionGroup=$roomRedPacketBroadcastGroupId '
|
||||
'isRegion=$isRegionBroadcastGroup '
|
||||
'payloadRegion=${_payloadText(payload['regionCode'])} '
|
||||
'currentRegion=${roomRedPacketBroadcastRegionCode ?? ''} '
|
||||
'currentRoom=${_currentVoiceRoomId()}',
|
||||
);
|
||||
if (!_isSameRoomRedPacketRegion(fData)) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] skip broadcast region mismatch '
|
||||
'packetId=$packetId '
|
||||
'payloadRegion=${_payloadText(payload['regionCode'])} '
|
||||
'currentRegion=${roomRedPacketBroadcastRegionCode ?? ''}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
RoomRedPacketPendingCache.instance.upsertPayload(fData);
|
||||
@ -2132,7 +2036,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
if (customData != null && customData.isNotEmpty) {
|
||||
// 直接处理字符串格式的自定义数据
|
||||
final data = json.decode(customData);
|
||||
debugPrint(">>>>>>>>>>>>>>>>>>>消息类型${data["type"]}");
|
||||
|
||||
if (data["type"] == SCRoomMsgType.roomRedPacket) {
|
||||
///房间红包
|
||||
@ -2232,9 +2135,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
if (msg.type == SCRoomMsgType.roomSettingUpdate) {
|
||||
debugPrint(
|
||||
"[Room Cover Sync] recv roomSettingUpdate groupId=$groupID roomId=${msg.msg ?? ""}",
|
||||
);
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context!,
|
||||
listen: false,
|
||||
@ -2624,7 +2524,6 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
joined = true;
|
||||
}
|
||||
} catch (e) {
|
||||
//print('timm 登录异常:${e.toString()}');
|
||||
SCTts.show('broadcastGroup join fail:${e.toString()}');
|
||||
}
|
||||
}
|
||||
@ -2675,18 +2574,9 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
if (targetGroupIds.isEmpty) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] skip send broadcast because target groups are empty',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] send broadcast packetId=${payload['packetId']} '
|
||||
'roomId=${payload['roomId']} mode=${payload['packetMode']} '
|
||||
'targets=${targetGroupIds.join(',')} regionGroup=$regionGroupId '
|
||||
'region=${payload['regionCode'] ?? roomRedPacketBroadcastRegionCode ?? ''}',
|
||||
);
|
||||
final message = <String, dynamic>{
|
||||
'type': SCRoomMsgType.roomRedPacket,
|
||||
'data': payload,
|
||||
@ -2707,24 +2597,12 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
.getMessageManager()
|
||||
.createCustomMessage(data: data);
|
||||
if (textMsg.code != 0 || textMsg.data?.id == null) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] create message failed '
|
||||
'group=$groupId code=${textMsg.code} desc=${textMsg.desc}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final sendResult = await TencentImSDKPlugin.v2TIMManager
|
||||
.getMessageManager()
|
||||
.sendMessage(id: textMsg.data!.id!, groupID: groupId, receiver: '');
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] send message packetId=${payload['packetId']} '
|
||||
'group=$groupId code=${sendResult.code} desc=${sendResult.desc}',
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][IM] send message failed group=$groupId error=$error',
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
Future quitGroup(String groupID) async {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class SCVoiceRoomForegroundService {
|
||||
@ -17,10 +16,7 @@ class SCVoiceRoomForegroundService {
|
||||
'roomName': roomName?.trim(),
|
||||
});
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('[VoiceRoomForeground] start failed: ${e.message}');
|
||||
} catch (e) {
|
||||
debugPrint('[VoiceRoomForeground] start failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
static Future<void> stop() async {
|
||||
@ -30,9 +26,6 @@ class SCVoiceRoomForegroundService {
|
||||
try {
|
||||
await _channel.invokeMethod<void>('stop');
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('[VoiceRoomForeground] stop failed: ${e.message}');
|
||||
} catch (e) {
|
||||
debugPrint('[VoiceRoomForeground] stop failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,8 +148,6 @@ class SocialChatAuthenticationManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
void _showAuthError(Object error) {
|
||||
debugPrint("authenticateUser error: $error");
|
||||
|
||||
if (error is DioException) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -225,9 +225,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().inviteHost(id, status);
|
||||
getUserIdentity();
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('inviteHostOpt failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void inviteAgentOpt(BuildContext ct, String id, String status) async {
|
||||
@ -236,9 +234,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().inviteAgent(id, status);
|
||||
getUserIdentity();
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('inviteAgentOpt failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void inviteBDOpt(BuildContext ct, String id, String status) async {
|
||||
@ -247,9 +243,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().inviteBD(id, status);
|
||||
getUserIdentity();
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('inviteBDOpt failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void inviteBDLeader(BuildContext ct, String id, String status) async {
|
||||
@ -258,9 +252,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().inviteBDLeader(id, status);
|
||||
getUserIdentity();
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('inviteBDLeader failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void inviteRechargeAgent(BuildContext ct, String id, String status) async {
|
||||
@ -269,9 +261,7 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().inviteRechargeAgent(id, status);
|
||||
getUserIdentity();
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('inviteRechargeAgent failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void cpRlationshipProcessApply(
|
||||
@ -284,8 +274,6 @@ class SocialChatUserProfileManager extends ChangeNotifier {
|
||||
await SCAccountRepository().cpRelationshipProcessApply(id, status);
|
||||
fetchUserProfileData(loadGuardCount: false);
|
||||
SCTts.show(successMessage);
|
||||
} catch (e) {
|
||||
debugPrint('cpRlationshipProcessApply failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/room_res.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_room_repository_imp.dart';
|
||||
@ -23,7 +22,6 @@ class SCHomeRoomPreloadManager {
|
||||
}
|
||||
unawaited(
|
||||
loadPartyRooms().catchError((error, stackTrace) {
|
||||
debugPrint('[HomePreload] party rooms preload failed: $error');
|
||||
return <SocialChatRoomRes>[];
|
||||
}),
|
||||
);
|
||||
|
||||
@ -101,7 +101,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
if (response.notFoundIDs.isNotEmpty) {
|
||||
_errorMessage = '未找到商品: ${response.notFoundIDs.join(', ')}';
|
||||
debugPrint(_errorMessage);
|
||||
}
|
||||
|
||||
var details = response.productDetails;
|
||||
@ -117,7 +116,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
SCTts.show("Failed to retrieve iOS products: $e");
|
||||
_errorMessage = 'Failed to get iOS goods: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
@ -178,7 +176,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
SCTts.show("iOS Purchase failed: $e");
|
||||
_errorMessage = 'iOS purchase failed: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
@ -200,7 +197,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
break;
|
||||
|
||||
case PurchaseStatus.pending:
|
||||
debugPrint('iOS支付处理中: ${purchase.productID}');
|
||||
SCTts.show('Payment is being processed, please wait...');
|
||||
break;
|
||||
case PurchaseStatus.restored:
|
||||
@ -246,10 +242,15 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
// 🔥 iOS关键:必须完成交易
|
||||
await iap.completePurchase(purchase);
|
||||
// 更新用户信息
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false).fetchUserProfileData();
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false).balance();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).fetchUserProfileData();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).balance();
|
||||
SCTts.show('Purchase is successful!');
|
||||
debugPrint('iOS购买成功: ${purchase.productID}');
|
||||
} catch (e) {
|
||||
if (e.toString().endsWith("${SCErroCode.orderExistsCreated.code}")) {
|
||||
SCTts.show('The order already exists!');
|
||||
@ -259,7 +260,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
SCTts.show("ios verification fails $e");
|
||||
_errorMessage = 'iOS verification failed: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
// 即使验证失败,也要完成交易,否则会卡住
|
||||
if (purchase.pendingCompletePurchase) {
|
||||
await iap.completePurchase(purchase);
|
||||
@ -272,7 +272,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
// 交付商品(与安卓相同)
|
||||
Future<void> _deliverProduct(String productId) async {
|
||||
debugPrint('交付iOS商品: $productId');
|
||||
// 使用相同的业务逻辑
|
||||
}
|
||||
|
||||
@ -292,7 +291,6 @@ class IOSPaymentProcessor extends ChangeNotifier {
|
||||
break;
|
||||
}
|
||||
|
||||
debugPrint(_errorMessage);
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@ -109,7 +109,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
);
|
||||
if (response.notFoundIDs.isNotEmpty) {
|
||||
_errorMessage = '未找到商品: ${response.notFoundIDs.join(', ')}';
|
||||
debugPrint(_errorMessage);
|
||||
}
|
||||
var dtails = response.productDetails;
|
||||
if (dtails.isNotEmpty) {
|
||||
@ -146,15 +145,10 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// 打印商品信息用于调试
|
||||
for (var product in _products) {
|
||||
debugPrint(
|
||||
'商品: ${product.produc.id}, 类型: ${_productTypeMap[product.produc.id]}, 价格: ${product.produc.price}',
|
||||
);
|
||||
}
|
||||
for (var product in _products) {}
|
||||
} catch (e) {
|
||||
SCTts.show("Failed to retrieve the product: $e");
|
||||
_errorMessage = '获取商品失败: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
@ -217,7 +211,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
break;
|
||||
|
||||
case PurchaseStatus.pending:
|
||||
debugPrint('支付处理中: ${purchase.productID}');
|
||||
break;
|
||||
|
||||
case PurchaseStatus.restored:
|
||||
@ -235,18 +228,17 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
// 新增:处理已拥有商品的情况
|
||||
Future<void> _handleAlreadyOwnedItem(PurchaseDetails purchase) async {
|
||||
try {
|
||||
debugPrint('检测到已拥有商品: ${purchase.productID},尝试消耗');
|
||||
|
||||
// 如果是消耗型商品,尝试消耗
|
||||
if (_getProductType(purchase.productID) == 'consumable') {
|
||||
await consumePurchase(purchase);
|
||||
// 消耗后重新获取余额
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false).balance();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).balance();
|
||||
SCTts.show('outstanding purchases have been reinstated');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('处理已拥有商品失败: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 验证支付凭证
|
||||
@ -261,7 +253,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
// 2. 检查是否已经处理过这个购买
|
||||
if (!purchase.pendingCompletePurchase) {
|
||||
debugPrint('购买已处理过: ${purchase.productID}');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -292,15 +283,19 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// 8. 更新用户余额
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false).fetchUserProfileData();
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false).balance();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).fetchUserProfileData();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).balance();
|
||||
|
||||
SCTts.show('purchase successful');
|
||||
debugPrint('购买成功: ${purchase.productID}');
|
||||
} catch (e) {
|
||||
SCTts.show("verification failed: $e");
|
||||
_errorMessage = '验证失败: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
@ -309,7 +304,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
// 交付商品
|
||||
Future<void> _deliverProduct(String productId) async {
|
||||
debugPrint('交付商品: $productId');
|
||||
// 实现您的业务逻辑
|
||||
// 例如:增加用户余额、解锁功能等
|
||||
}
|
||||
@ -322,11 +316,7 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
// 尝试消耗购买
|
||||
await consumePurchase(purchase);
|
||||
|
||||
debugPrint('商品已成功消耗: ${purchase.productID}');
|
||||
} catch (e) {
|
||||
debugPrint('消耗商品失败,可能已自动消耗: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void _handleError(Object error, StackTrace stackTrace) {
|
||||
@ -348,22 +338,18 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
// 处理特定错误代码
|
||||
switch (error.code) {
|
||||
case 'payment-invalid':
|
||||
debugPrint('支付无效: 商品ID可能配置错误');
|
||||
SCTts.show(
|
||||
'Payment configuration error, please contact customer service',
|
||||
);
|
||||
break;
|
||||
case 'item-already-owned':
|
||||
debugPrint('商品已拥有,尝试消耗商品');
|
||||
SCTts.show('Unfinished purchase detected, processing...');
|
||||
break;
|
||||
case 'user-cancelled':
|
||||
debugPrint('用户取消购买');
|
||||
SCTts.show('Purchase cancelled');
|
||||
break;
|
||||
case 'service-timeout':
|
||||
case 'service-unavailable':
|
||||
debugPrint('Google Play服务不可用');
|
||||
SCTts.show(
|
||||
'Google Play services are temporarily unavailable, please try again later',
|
||||
);
|
||||
@ -373,7 +359,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
break;
|
||||
}
|
||||
|
||||
debugPrint(_errorMessage);
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
}
|
||||
@ -390,7 +375,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
await Future.delayed(Duration(milliseconds: 1000));
|
||||
} catch (e) {
|
||||
_errorMessage = '恢复购买失败: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
SCTts.show("Failed to restore purchase: ${e.toString()}");
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
@ -405,11 +389,9 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
final InAppPurchaseAndroidPlatformAddition androidAddition =
|
||||
iap.getPlatformAddition<InAppPurchaseAndroidPlatformAddition>();
|
||||
await androidAddition.consumePurchase(purchase);
|
||||
debugPrint('已消耗商品: ${purchase.productID}');
|
||||
}
|
||||
} catch (e) {
|
||||
_errorMessage = '消耗商品失败: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,7 +428,6 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
} catch (e) {
|
||||
SCTts.show("Purchase failed: $e");
|
||||
_errorMessage = '购买失败: ${e.toString()}';
|
||||
debugPrint(_errorMessage);
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
notifyListeners();
|
||||
@ -461,22 +442,12 @@ class AndroidPaymentProcessor extends ChangeNotifier {
|
||||
|
||||
// 给一点时间处理恢复的购买
|
||||
await Future.delayed(Duration(milliseconds: 550));
|
||||
} catch (e) {
|
||||
debugPrint('检查未完成购买时出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 添加调试方法
|
||||
void logCurrentPurchaseStatus() {
|
||||
debugPrint('=== 当前购买状态 ===');
|
||||
debugPrint('可用商品数量: ${_products.length}');
|
||||
debugPrint('未完成购买数量: ${_purchases.length}');
|
||||
|
||||
for (var purchase in _purchases) {
|
||||
debugPrint('商品: ${purchase.productID}, 状态: ${purchase.status}');
|
||||
debugPrint('待完成: ${purchase.pendingCompletePurchase}');
|
||||
}
|
||||
debugPrint('==================');
|
||||
for (var purchase in _purchases) {}
|
||||
}
|
||||
|
||||
// 释放资源
|
||||
|
||||
@ -61,7 +61,6 @@ class SocialChatRoomManager extends ChangeNotifier {
|
||||
// 差异化:添加自定义名称参数(暂未使用,为未来扩展预留)
|
||||
if (customName != null) {
|
||||
// TODO: 实现自定义房间名称
|
||||
debugPrint('创建房间使用自定义名称: $customName');
|
||||
}
|
||||
await SCAccountRepository().createRoom();
|
||||
myRoom = await SCAccountRepository().myProfile();
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
@ -33,11 +32,9 @@ class DataPersistence {
|
||||
_prefs = await SharedPreferences.getInstance();
|
||||
_isInitialized = true;
|
||||
_initializationCompleter!.complete();
|
||||
debugPrint('SharedPreferences initialized successfully');
|
||||
} catch (e) {
|
||||
_initializationCompleter!.completeError(e);
|
||||
_initializationCompleter = null;
|
||||
debugPrint('SharedPreferences initialization failed: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
typedef FileCacheManager = MediaCache;
|
||||
|
||||
class MediaCache {
|
||||
late CacheManager _cacheManager;
|
||||
static FileCacheManager? _instance;
|
||||
@ -55,10 +56,8 @@ class MediaCache {
|
||||
await Directory("$temporaryPath/$musicPath").create(recursive: true);
|
||||
|
||||
soundPath = "$temporaryPath/sound";
|
||||
print('语音文件夹路径: $soundPath');
|
||||
return temporaryPath;
|
||||
} catch (e) {
|
||||
print('目录创建失败: $e');
|
||||
rethrow; // 或者返回一个备用路径
|
||||
}
|
||||
}
|
||||
@ -66,10 +65,7 @@ class MediaCache {
|
||||
/// 下载或获取缓存文件
|
||||
/// [url] 文件网络地址
|
||||
/// [ignoreCache] 是否忽略缓存强制重新下载
|
||||
Future<File> getFile({
|
||||
required String url,
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
Future<File> getFile({required String url, bool ignoreCache = false}) async {
|
||||
if (ignoreCache) {
|
||||
// 强制重新下载
|
||||
final fileInfo = await _cacheManager.downloadFile(url);
|
||||
@ -126,12 +122,7 @@ class MediaCache {
|
||||
|
||||
// 2. 验证文件已缓存
|
||||
final cachedFile = await cacheManager.getFileFromCache(cacheKey);
|
||||
if (cachedFile != null) {
|
||||
print('文件已成功添加到缓存: ${cachedFile.file.path}');
|
||||
if (cachedFile != null) {}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (e) {
|
||||
print('添加文件到缓存失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -55,12 +55,7 @@ class OverlayManager {
|
||||
if (_isRecentFloatingDuplicate(message)) {
|
||||
return;
|
||||
}
|
||||
if (message.type == 4) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Floating] enqueue packetId=${message.toUserId} '
|
||||
'roomId=${message.roomId} region=${message.isRegionBroadcast}',
|
||||
);
|
||||
}
|
||||
if (message.type == 4) {}
|
||||
_rememberFloatingMessage(message);
|
||||
_enqueueMessage(
|
||||
message,
|
||||
@ -236,9 +231,7 @@ class OverlayManager {
|
||||
await SCSvgaAssetWidget.preloadAsset(
|
||||
FloatingLuckGiftScreenWidget.backgroundSvgaAssetPath,
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('预热幸运礼物横幅SVGA失败: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
void _safeScheduleNext() {
|
||||
@ -287,7 +280,6 @@ class OverlayManager {
|
||||
final messageToPlay = _messageQueue.removeFirst();
|
||||
_playMessage(messageToPlay);
|
||||
} catch (e) {
|
||||
debugPrint('播放悬浮消息出错: $e');
|
||||
_isPlaying = false;
|
||||
_safeScheduleNext();
|
||||
}
|
||||
@ -332,7 +324,6 @@ class OverlayManager {
|
||||
_currentMessage = null;
|
||||
_safeScheduleNext();
|
||||
} catch (e) {
|
||||
debugPrint('清理悬浮消息出错: $e');
|
||||
_isPlaying = false;
|
||||
_currentMessage = null;
|
||||
_safeScheduleNext();
|
||||
@ -427,9 +418,6 @@ class OverlayManager {
|
||||
|
||||
void beginSuppressFloatingScreens({String reason = 'unknown'}) {
|
||||
_suppressedCount += 1;
|
||||
debugPrint(
|
||||
'[FloatingScreen] suppress begin reason=$reason count=$_suppressedCount',
|
||||
);
|
||||
_removeActiveMessage(scheduleNext: false);
|
||||
_messageQueue.clear();
|
||||
_isPlaying = false;
|
||||
@ -440,9 +428,6 @@ class OverlayManager {
|
||||
if (_suppressedCount > 0) {
|
||||
_suppressedCount -= 1;
|
||||
}
|
||||
debugPrint(
|
||||
'[FloatingScreen] suppress end reason=$reason count=$_suppressedCount',
|
||||
);
|
||||
if (!_isSuppressed) {
|
||||
_safeScheduleNext();
|
||||
}
|
||||
@ -552,10 +537,6 @@ class OverlayManager {
|
||||
_deferredRegionRedPacketMessages.removeAt(0);
|
||||
}
|
||||
_deferredRegionRedPacketMessages.add(message);
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Floating] defer packetId=${message.toUserId} '
|
||||
'roomId=${message.roomId} ${_displayStateForLog(context)}',
|
||||
);
|
||||
}
|
||||
|
||||
void _restoreDeferredRegionRedPacketMessages() {
|
||||
@ -569,9 +550,6 @@ class OverlayManager {
|
||||
for (final message in messages) {
|
||||
_messageQueue.add(message);
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Floating] restore deferred count=${messages.length}',
|
||||
);
|
||||
}
|
||||
|
||||
void _logRegionRedPacketDrop(
|
||||
@ -581,11 +559,6 @@ class OverlayManager {
|
||||
if (message.type != 4) {
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][Floating] drop packetId=${message.toUserId} '
|
||||
'roomId=${message.roomId} region=${message.isRegionBroadcast} '
|
||||
'${_displayStateForLog(context)}',
|
||||
);
|
||||
}
|
||||
|
||||
String _displayStateForLog(BuildContext context) {
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/tools/sc_deviceId_utils.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/api.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/sc_logger.dart';
|
||||
|
||||
NetworkClient get http => _httpInstance;
|
||||
|
||||
@ -286,7 +284,6 @@ class NetworkClient extends BaseNetworkClient {
|
||||
// 添加拦截器
|
||||
dio.interceptors
|
||||
..add(ApiInterceptor())
|
||||
..add(SCDioLogger())
|
||||
..add(TimeOutInterceptor());
|
||||
|
||||
setupCacheInterceptor(dio); // 传入 dio 实例
|
||||
@ -529,10 +526,7 @@ class TimeOutInterceptor extends Interceptor {
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||
if (err.type == DioExceptionType.connectionTimeout ||
|
||||
err.type == DioExceptionType.receiveTimeout ||
|
||||
err.type == DioExceptionType.sendTimeout) {
|
||||
debugPrint('超时错误: URL => ${err.requestOptions.baseUrl}');
|
||||
debugPrint('当前使用的Host: ${SCGlobalConfig.apiHost}');
|
||||
}
|
||||
err.type == DioExceptionType.sendTimeout) {}
|
||||
|
||||
// 请求出错,取消计时器
|
||||
final String requestKey = err.requestOptions.uri.toString();
|
||||
|
||||
@ -1,267 +0,0 @@
|
||||
/*
|
||||
* @message: 日志拦截器
|
||||
* @Author: Jack
|
||||
* @Email: Jack@163.com
|
||||
* @Date: 2020-06-18 19:47:32
|
||||
*/
|
||||
import 'package:dio/dio.dart';
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/foundation.dart';
|
||||
// 必须引入此库处理 Emoji 截断问题
|
||||
import 'package:characters/characters.dart';
|
||||
|
||||
/// description: Dio 日志拦截器
|
||||
class SCDioLogger extends Interceptor {
|
||||
final bool request;
|
||||
final bool requestHeader;
|
||||
final bool requestBody;
|
||||
final bool responseBody;
|
||||
final bool responseHeader;
|
||||
final bool error;
|
||||
static const int initialTab = 1;
|
||||
static const String tabStep = ' ';
|
||||
final bool compact;
|
||||
final int maxWidth;
|
||||
|
||||
/// Log printer; defaults debugPrint to console.
|
||||
void Function(Object object) logPrint;
|
||||
final bool enableLog;
|
||||
|
||||
SCDioLogger({
|
||||
this.enableLog = kDebugMode,
|
||||
this.request = true,
|
||||
this.requestHeader = true,
|
||||
this.requestBody = true,
|
||||
this.responseHeader = false,
|
||||
this.responseBody = true,
|
||||
this.error = true,
|
||||
this.maxWidth = 90,
|
||||
this.compact = true,
|
||||
this.logPrint = print, // 修复:在 iOS 上 debugPrint 比 print 更稳健
|
||||
});
|
||||
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
if (!enableLog) return handler.next(options);
|
||||
|
||||
if (request) _pReqHdr(options);
|
||||
if (requestHeader) {
|
||||
_pTable(options.queryParameters, header: 'Query Parameters');
|
||||
final requestHeaders = <String, dynamic>{};
|
||||
requestHeaders.addAll(options.headers);
|
||||
requestHeaders['contentType'] = options.contentType?.toString();
|
||||
requestHeaders['responseType'] = options.responseType?.toString();
|
||||
requestHeaders['followRedirects'] = options.followRedirects;
|
||||
requestHeaders['connectTimeout'] = options.connectTimeout;
|
||||
requestHeaders['receiveTimeout'] = options.receiveTimeout;
|
||||
_pTable(requestHeaders, header: 'Headers');
|
||||
_pTable(options.extra, header: 'Extras');
|
||||
}
|
||||
if (requestBody && options.method != 'GET') {
|
||||
final data = options.data;
|
||||
if (data != null) {
|
||||
if (data is Map) {
|
||||
_pTable(data, header: 'Body');
|
||||
} else if (data is FormData) {
|
||||
final formDataMap = Map()
|
||||
..addEntries(data.fields)
|
||||
..addEntries(data.files);
|
||||
_pTable(formDataMap, header: 'Form data | ${data.boundary}');
|
||||
} else {
|
||||
_pBlock(data.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
handler.next(options);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||
if (!enableLog) return handler.next(err);
|
||||
|
||||
if (error) {
|
||||
if (err.type == DioExceptionType.badResponse) {
|
||||
final uri = err.response?.requestOptions.uri;
|
||||
_pBox(
|
||||
header: 'DioError ║ Status: ${err.response?.statusCode} ${err.response?.statusMessage}',
|
||||
text: uri.toString());
|
||||
if (err.response?.data != null) {
|
||||
logPrint('╔ ${err.type.toString()}');
|
||||
_pResp(err.response!);
|
||||
}
|
||||
_pLine('╚');
|
||||
} else {
|
||||
final uri = err.requestOptions.uri;
|
||||
_pBox(header: 'DioError ║ ${err.type} ║ ${uri.toString()}', text: err.message);
|
||||
}
|
||||
}
|
||||
handler.next(err);
|
||||
}
|
||||
|
||||
@override
|
||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||
if (!enableLog) return handler.next(response);
|
||||
|
||||
if (responseHeader) {
|
||||
final responseHeaders = <String, String>{};
|
||||
response.headers.forEach((k, list) => responseHeaders[k] = list.toString());
|
||||
_pTable(responseHeaders, header: 'Headers');
|
||||
}
|
||||
|
||||
if (responseBody) {
|
||||
_pRespHdr(response);
|
||||
logPrint('╔ Body');
|
||||
logPrint('║');
|
||||
_pResp(response);
|
||||
logPrint('║');
|
||||
_pLine('╚');
|
||||
}
|
||||
handler.next(response);
|
||||
}
|
||||
|
||||
void _pBox({String? header, String? text}) {
|
||||
logPrint('');
|
||||
logPrint('╔╣ $header');
|
||||
logPrint('║ $text');
|
||||
_pLine('╚');
|
||||
}
|
||||
|
||||
void _pResp(Response response) {
|
||||
if (response.data != null) {
|
||||
if (response.data is Map) {
|
||||
_pMap(response.data);
|
||||
} else if (response.data is List) {
|
||||
logPrint('║${_ind()}[');
|
||||
_pList(response.data);
|
||||
logPrint('║${_ind()}]');
|
||||
} else {
|
||||
_pBlock(response.data.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _pRespHdr(Response response) {
|
||||
final uri = response.requestOptions.uri;
|
||||
final method = response.requestOptions.method;
|
||||
String header = 'Response ║ $method ║ Status: ${response.statusCode} ${response.statusMessage}';
|
||||
logPrint('╔╣ $header ${'═' * 20}');
|
||||
logPrint('║ ${uri.toString()}');
|
||||
logPrint('║ ');
|
||||
}
|
||||
|
||||
void _pReqHdr(RequestOptions options) {
|
||||
final uri = options.uri;
|
||||
final method = options.method;
|
||||
_pBox(header: 'Request ║ $method ', text: uri.toString());
|
||||
}
|
||||
|
||||
void _pLine([String pre = '', String suf = '╝']) => logPrint('$pre${'═' * maxWidth}');
|
||||
|
||||
void _pKV(String key, Object v) {
|
||||
final pre = '╟ $key: ';
|
||||
final msg = v.toString();
|
||||
|
||||
if (pre.length + msg.length > maxWidth) {
|
||||
logPrint(pre);
|
||||
_pBlock(msg);
|
||||
} else {
|
||||
logPrint('$pre$msg');
|
||||
}
|
||||
}
|
||||
|
||||
// 修复:使用 characters 处理截断,防止 Emoji 损坏
|
||||
void _pBlock(String msg) {
|
||||
final charData = msg.characters;
|
||||
int lines = (charData.length / maxWidth).ceil();
|
||||
for (int i = 0; i < lines; ++i) {
|
||||
final start = i * maxWidth;
|
||||
final end = math.min<int>(start + maxWidth, charData.length);
|
||||
logPrint('║ ' + charData.getRange(start, end).toString());
|
||||
}
|
||||
}
|
||||
|
||||
String _ind([int tabCount = initialTab]) => tabStep * tabCount;
|
||||
|
||||
void _pMap(Map data, {int tabs = initialTab, bool isListItem = false, bool isLast = false}) {
|
||||
final bool isRoot = tabs == initialTab;
|
||||
final initialIndent = _ind(tabs);
|
||||
tabs++;
|
||||
|
||||
if (isRoot || isListItem) logPrint('║$initialIndent{');
|
||||
|
||||
data.keys.toList().asMap().forEach((index, key) {
|
||||
final isLast = index == data.length - 1;
|
||||
var value = data[key];
|
||||
if (value is String) value = '\"$value\"';
|
||||
|
||||
if (value is Map) {
|
||||
if (compact && _flatMap(value)) {
|
||||
logPrint('║${_ind(tabs)} $key: $value${!isLast ? ',' : ''}');
|
||||
} else {
|
||||
logPrint('║${_ind(tabs)} $key: {');
|
||||
_pMap(value, tabs: tabs);
|
||||
}
|
||||
} else if (value is List) {
|
||||
if (compact && _flatList(value)) {
|
||||
logPrint('║${_ind(tabs)} $key: ${value.toString()}');
|
||||
} else {
|
||||
logPrint('║${_ind(tabs)} $key: [');
|
||||
_pList(value, tabs: tabs);
|
||||
logPrint('║${_ind(tabs)} ]${isLast ? '' : ','}');
|
||||
}
|
||||
} else {
|
||||
final msg = value.toString().replaceAll('\n', '');
|
||||
final indent = _ind(tabs);
|
||||
final charMsg = msg.characters;
|
||||
final linWidth = maxWidth - indent.length;
|
||||
|
||||
// 修复:字符串分段时处理 Emoji
|
||||
if (charMsg.length + indent.length > maxWidth) {
|
||||
int lines = (charMsg.length / linWidth).ceil();
|
||||
for (int i = 0; i < lines; ++i) {
|
||||
final start = i * linWidth;
|
||||
final end = math.min<int>(start + linWidth, charMsg.length);
|
||||
logPrint('║${_ind(tabs)} ${charMsg.getRange(start, end).toString()}');
|
||||
}
|
||||
} else {
|
||||
logPrint('║${_ind(tabs)} $key: $msg${!isLast ? ',' : ''}');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
logPrint('║$initialIndent}${isListItem && !isLast ? ',' : ''}');
|
||||
}
|
||||
|
||||
void _pList(List list, {int tabs = initialTab}) {
|
||||
list.asMap().forEach((i, e) {
|
||||
final isLast = i == list.length - 1;
|
||||
if (e is Map) {
|
||||
if (compact && _flatMap(e)) {
|
||||
logPrint('║${_ind(tabs)} $e${!isLast ? ',' : ''}');
|
||||
} else {
|
||||
_pMap(e, tabs: tabs + 1, isListItem: true, isLast: isLast);
|
||||
}
|
||||
} else {
|
||||
logPrint('║${_ind(tabs + 2)} $e${isLast ? '' : ','}');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool _flatMap(Map map) {
|
||||
return map.values.where((val) => val is Map || val is List).isEmpty &&
|
||||
map.toString().length < maxWidth;
|
||||
}
|
||||
|
||||
bool _flatList(List list) {
|
||||
return (list.length < 10 && list.toString().length < maxWidth);
|
||||
}
|
||||
|
||||
void _pTable(Map? map, {String? header}) {
|
||||
if (map == null || map.isEmpty) return;
|
||||
logPrint('╔ $header ');
|
||||
map.forEach((key, value) {
|
||||
_pKV(key.toString(), (value ?? 'null').toString());
|
||||
});
|
||||
_pLine('╚');
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/shared/business_logic/repositories/general_repository.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/api.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/network_client.dart';
|
||||
@ -21,8 +20,6 @@ class SCGeneralRepositoryImp implements SocialChatGeneralRepository {
|
||||
filePath.lastIndexOf("/") + 1,
|
||||
filePath.length,
|
||||
);
|
||||
debugPrint("[上传头像图片地址] filePath: $filePath");
|
||||
debugPrint("[上传头像图片] fileName: $name");
|
||||
FormData formData = FormData.fromMap({
|
||||
"file": await MultipartFile.fromFile(filePath, filename: name),
|
||||
});
|
||||
@ -40,8 +37,6 @@ class SCGeneralRepositoryImp implements SocialChatGeneralRepository {
|
||||
response.data as Map<String, dynamic>,
|
||||
fromJsonT: (json) => json as String,
|
||||
);
|
||||
debugPrint("[返回值] response.data: ${response.data}");
|
||||
debugPrint("[返回图片地址] parsed file url: ${baseResponse.body ?? ""}");
|
||||
return baseResponse.body ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,9 +49,7 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
return _instance ??= SCChatRoomRepository._internal();
|
||||
}
|
||||
|
||||
void _giftRepoLog(String message) {
|
||||
debugPrint('[GiftFX][Repo] $message');
|
||||
}
|
||||
void _giftRepoLog(String message) {}
|
||||
|
||||
Future<T> _traceRoomRedPacketApi<T>(
|
||||
String method,
|
||||
@ -61,17 +59,8 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
dynamic query,
|
||||
}) async {
|
||||
final startedAt = DateTime.now();
|
||||
debugPrint(
|
||||
'[RoomRedPacket][API] -> $method $path '
|
||||
'query=${_debugJson(query)} data=${_debugJson(data)}',
|
||||
);
|
||||
try {
|
||||
final result = await request();
|
||||
debugPrint(
|
||||
'[RoomRedPacket][API] <- $method $path '
|
||||
'cost=${DateTime.now().difference(startedAt).inMilliseconds}ms '
|
||||
'result=${_debugResult(result)}',
|
||||
);
|
||||
return result;
|
||||
} catch (error, stackTrace) {
|
||||
_logRoomRedPacketApiError(method, path, error, stackTrace);
|
||||
@ -87,19 +76,7 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
) {
|
||||
if (error is DioException) {
|
||||
final request = error.requestOptions;
|
||||
debugPrint(
|
||||
'[RoomRedPacket][API] !! $method $path '
|
||||
'resolved=${request.method} ${request.uri} '
|
||||
'status=${error.response?.statusCode} '
|
||||
'type=${error.type} message=${error.message} '
|
||||
'error=${error.error} response=${_debugJson(error.response?.data)}',
|
||||
);
|
||||
} else {
|
||||
debugPrint('[RoomRedPacket][API] !! $method $path error=$error');
|
||||
}
|
||||
debugPrint(
|
||||
'[RoomRedPacket][API] stack=${stackTrace.toString().split('\n').take(8).join(' | ')}',
|
||||
);
|
||||
} else {}
|
||||
}
|
||||
|
||||
String _debugJson(dynamic value) {
|
||||
@ -147,13 +124,7 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
if (!_shouldHydrateRoomProfile(cachedRoom.id, cachedRoom.roomCover)) {
|
||||
return cachedRoom;
|
||||
}
|
||||
debugPrint(
|
||||
"[Room Cover][room-list] hydrate roomId=${cachedRoom.id} remoteCover=${cachedRoom.roomCover ?? ""}",
|
||||
);
|
||||
final specificRoom = await specific(cachedRoom.id ?? "");
|
||||
debugPrint(
|
||||
"[Room Cover][room-list] specific roomId=${cachedRoom.id} specificCover=${specificRoom.roomCover ?? ""}",
|
||||
);
|
||||
return SCRoomProfileCache.applyToSocialChatRoomRes(
|
||||
cachedRoom.copyWith(
|
||||
roomCover: SCRoomProfileCache.preferNonEmpty(
|
||||
@ -224,9 +195,6 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
queryParams: queryParams,
|
||||
fromJson: (json) => MyRoomRes.fromJson(json),
|
||||
);
|
||||
debugPrint(
|
||||
"[Room Cover][specific] roomId=${result.id ?? roomId} roomCover=${result.roomCover ?? ""} roomBackground=${result.roomBackground ?? ""} roomName=${result.roomName ?? ""}",
|
||||
);
|
||||
await SCRoomProfileCache.saveRoomProfile(
|
||||
roomId: result.id ?? roomId,
|
||||
roomCover: result.roomCover,
|
||||
|
||||
@ -266,13 +266,11 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
"roomDesc": roomDesc,
|
||||
"event": event,
|
||||
};
|
||||
debugPrint("[Room Cover Save] request payload=$payload");
|
||||
final result = await http.put(
|
||||
"1e41384e55cbd6c2374608b129e2ed27",
|
||||
data: payload,
|
||||
fromJson: (json) => SCEditRoomInfoRes.fromJson(json),
|
||||
);
|
||||
debugPrint("[Room Cover Save] response=${result.toJson()}");
|
||||
await SCRoomProfileCache.saveRoomProfile(
|
||||
roomId: roomId,
|
||||
roomCover: roomCover,
|
||||
@ -289,7 +287,6 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
String roomBackground,
|
||||
) async {
|
||||
final payload = {"roomId": roomId, "roomBackground": roomBackground};
|
||||
debugPrint("[Room Background Save] request payload=$payload");
|
||||
final result = await http.put(
|
||||
"/room/profile/background",
|
||||
data: payload,
|
||||
@ -299,7 +296,6 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
(result.roomBackground ?? "").trim().isNotEmpty
|
||||
? result.roomBackground
|
||||
: roomBackground;
|
||||
debugPrint("[Room Background Save] response=${result.toJson()}");
|
||||
await SCRoomProfileCache.saveRoomProfile(
|
||||
roomId: result.id ?? roomId,
|
||||
roomCover: result.roomCover,
|
||||
@ -662,22 +658,13 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
@override
|
||||
Future<SCSignInRewardStatusRes> signInRewardStatus() async {
|
||||
const path = "/go/app/sign-in-reward/status";
|
||||
debugPrint(
|
||||
'[SignInReward][Request] GET $path '
|
||||
'baseUrl=${http.dio.options.baseUrl} params={}',
|
||||
);
|
||||
try {
|
||||
final result = await http.get<SCSignInRewardStatusRes>(
|
||||
path,
|
||||
fromJson: (json) => SCSignInRewardStatusRes.fromJson(json),
|
||||
);
|
||||
debugPrint(
|
||||
'[SignInReward][Response] GET $path '
|
||||
'summary=${jsonEncode(_signInRewardStatusSummary(result))}',
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
debugPrint('[SignInReward][Error] GET $path error=$error');
|
||||
_debugSignInRewardError('GET', path, error);
|
||||
rethrow;
|
||||
}
|
||||
@ -687,23 +674,14 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
Future<SCSignInRewardCheckInRes> signInRewardCheckIn() async {
|
||||
const path = "/go/app/sign-in-reward/check-in";
|
||||
const body = <String, dynamic>{};
|
||||
debugPrint(
|
||||
'[SignInReward][Request] POST $path '
|
||||
'baseUrl=${http.dio.options.baseUrl} body=${jsonEncode(body)}',
|
||||
);
|
||||
try {
|
||||
final result = await http.post<SCSignInRewardCheckInRes>(
|
||||
path,
|
||||
data: body,
|
||||
fromJson: (json) => SCSignInRewardCheckInRes.fromJson(json),
|
||||
);
|
||||
debugPrint(
|
||||
'[SignInReward][Response] POST $path '
|
||||
'summary=${jsonEncode(_signInRewardCheckInSummary(result))}',
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
debugPrint('[SignInReward][Error] POST $path error=$error');
|
||||
_debugSignInRewardError('POST', path, error);
|
||||
rethrow;
|
||||
}
|
||||
@ -713,29 +691,8 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
if (error is DioException) {
|
||||
final requestOptions = error.requestOptions;
|
||||
final response = error.response;
|
||||
debugPrint(
|
||||
'[SignInReward][Dio] $method $path '
|
||||
'type=${error.type} '
|
||||
'message=${error.message} '
|
||||
'uri=${requestOptions.uri}',
|
||||
);
|
||||
debugPrint(
|
||||
'[SignInReward][Dio] $method $path '
|
||||
'headers=${jsonEncode(requestOptions.headers)} '
|
||||
'query=${jsonEncode(requestOptions.queryParameters)} '
|
||||
'data=${jsonEncode(requestOptions.data)}',
|
||||
);
|
||||
debugPrint(
|
||||
'[SignInReward][Dio] $method $path '
|
||||
'statusCode=${response?.statusCode} '
|
||||
'statusMessage=${response?.statusMessage} '
|
||||
'response=${jsonEncode(response?.data)} '
|
||||
'innerError=${error.error}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
debugPrint('[SignInReward][Dio] $method $path non-dio-error=$error');
|
||||
}
|
||||
|
||||
Map<String, dynamic> _signInRewardStatusSummary(
|
||||
@ -993,7 +950,6 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
String path, {
|
||||
required String source,
|
||||
}) async {
|
||||
debugPrint("[TaskCenter][Repo] list request source=$source path=$path");
|
||||
final result = await http.get<List<SCTaskListRes>>(
|
||||
path,
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
@ -1001,10 +957,6 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
(json) =>
|
||||
(json as List).map((e) => SCTaskListRes.fromJson(e)).toList(),
|
||||
);
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] list response source=$source "
|
||||
"count=${result.length} ${_taskListDebugSample(result)}",
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1039,33 +991,21 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
@override
|
||||
Future<bool> taskReward(String taskId) async {
|
||||
try {
|
||||
debugPrint("[TaskCenter][Repo] claim request source=new taskId=$taskId");
|
||||
final result = await http.post<bool>(
|
||||
"/go/app/task-center/claim",
|
||||
data: {"taskId": taskId},
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
fromJson: (json) => json as bool,
|
||||
);
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] claim response source=new taskId=$taskId "
|
||||
"success=$result",
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
_debugTaskError("new claim taskId=$taskId", error);
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] claim request source=legacy taskId=$taskId",
|
||||
);
|
||||
final result = await http.get<bool>(
|
||||
"0047abf8502867ed03180e3a6b505d411832ea9bebe4ec426a7036c865082475",
|
||||
queryParams: {"taskId": taskId},
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
fromJson: (json) => json as bool,
|
||||
);
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] claim response source=legacy taskId=$taskId "
|
||||
"success=$result",
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1082,15 +1022,11 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
}
|
||||
|
||||
Future<int> _taskClaimableCount(String path) async {
|
||||
debugPrint("[TaskCenter][Repo] claimable count request path=$path");
|
||||
final result = await http.get<num>(
|
||||
path,
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
fromJson: _parseTaskClaimableCount,
|
||||
);
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] claimable count response path=$path count=$result",
|
||||
);
|
||||
return result.toInt();
|
||||
}
|
||||
|
||||
@ -1103,16 +1039,8 @@ class SCAccountRepository implements SocialChatUserRepository {
|
||||
|
||||
void _debugTaskError(String stage, Object error) {
|
||||
if (error is DioException) {
|
||||
debugPrint(
|
||||
"[TaskCenter][Repo] $stage failed "
|
||||
"type=${error.type} status=${error.response?.statusCode} "
|
||||
"message=${error.message} error=${error.error} "
|
||||
"url=${error.requestOptions.uri} "
|
||||
"data=${_clipTaskDebug(_stringifyTaskDebug(error.response?.data))}",
|
||||
);
|
||||
return;
|
||||
}
|
||||
debugPrint("[TaskCenter][Repo] $stage failed error=$error");
|
||||
}
|
||||
|
||||
String _stringifyTaskDebug(dynamic data) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_vip_res.dart';
|
||||
import 'package:yumi/shared/business_logic/repositories/vip_repository.dart';
|
||||
@ -158,21 +157,13 @@ class SCVipRepositoryImp implements SocialChatVipRepository {
|
||||
String path, {
|
||||
Map<String, dynamic>? query,
|
||||
Map<String, dynamic>? body,
|
||||
}) {
|
||||
debugPrint(
|
||||
'[VIP][Request] $method $path '
|
||||
'baseUrl=$_activeBaseUrl query=${_json(query ?? const {})} '
|
||||
'body=${_json(body ?? const {})}',
|
||||
);
|
||||
}
|
||||
}) {}
|
||||
|
||||
static void _logResponse(
|
||||
String method,
|
||||
String path,
|
||||
Map<String, dynamic> summary,
|
||||
) {
|
||||
debugPrint('[VIP][Response] $method $path summary=${_json(summary)}');
|
||||
}
|
||||
) {}
|
||||
|
||||
static void _logError(
|
||||
String method,
|
||||
@ -181,19 +172,7 @@ class SCVipRepositoryImp implements SocialChatVipRepository {
|
||||
Map<String, dynamic>? query,
|
||||
Map<String, dynamic>? body,
|
||||
}) {
|
||||
debugPrint(
|
||||
'[VIP][Error] $method $path query=${_json(query ?? const {})} '
|
||||
'body=${_json(body ?? const {})} error=$error',
|
||||
);
|
||||
if (error is DioException) {
|
||||
debugPrint(
|
||||
'[VIP][DioError] $method $path '
|
||||
'uri=${error.requestOptions.uri} '
|
||||
'statusCode=${error.response?.statusCode} '
|
||||
'message=${error.message} '
|
||||
'response=${_json(error.response?.data)}',
|
||||
);
|
||||
}
|
||||
if (error is DioException) {}
|
||||
}
|
||||
|
||||
static Map<String, dynamic> _statusSummary(SCVipStatusRes result) {
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
import 'dart:io';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class SCAppUtils {
|
||||
|
||||
|
||||
// 递归计算文件夹大小
|
||||
static Future<double> _gs(Directory folder) async {
|
||||
try {
|
||||
@ -28,21 +25,17 @@ class SCAppUtils {
|
||||
|
||||
return size;
|
||||
} catch (e) {
|
||||
print('计算文件夹大小出错: ${folder.path} - $e');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 删除文件夹
|
||||
static Future<void> _dd(Directory folder) async {
|
||||
try {
|
||||
if (await folder.exists()) {
|
||||
await folder.delete(recursive: true);
|
||||
}
|
||||
} catch (e) {
|
||||
print('删除文件夹失败: ${folder.path} - $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 清理 Dio 缓存
|
||||
@ -54,9 +47,7 @@ class SCAppUtils {
|
||||
if (await dioCacheDir.exists()) {
|
||||
await dioCacheDir.delete(recursive: true);
|
||||
}
|
||||
} catch (e) {
|
||||
print('清理Dio缓存出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 清理图片缓存
|
||||
@ -69,9 +60,7 @@ class SCAppUtils {
|
||||
imageCache.clearLiveImages();
|
||||
}
|
||||
await clearDiskCachedImages();
|
||||
} catch (e) {
|
||||
print('清理图片缓存出错: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 格式化缓存大小显示
|
||||
|
||||
@ -25,30 +25,22 @@ class SCDeepLinkHandler {
|
||||
if (initialLink != null) {
|
||||
_ph(initialLink);
|
||||
}
|
||||
} catch (err) {
|
||||
print('获取初始链接失败: $err');
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
void _sl() {
|
||||
// 4. 使用 uriLinkStream 监听链接(流类型为 Uri)
|
||||
_lss = _ap.uriLinkStream.listen(
|
||||
(Uri? link) {
|
||||
_lss = _ap.uriLinkStream.listen((Uri? link) {
|
||||
// 注意:uriLinkStream 可能直接发出 Uri,而不是 String?
|
||||
// 根据实际版本,可能是 Uri 或 String?,以下处理两者兼容
|
||||
if (link != null) {
|
||||
_ph(link);
|
||||
}
|
||||
},
|
||||
onError: (err) {
|
||||
print('监听链接流出错: $err');
|
||||
},
|
||||
);
|
||||
}, onError: (err) {});
|
||||
}
|
||||
|
||||
// 5. 接收 Uri 类型参数(原来接收 String)
|
||||
void _ph(Uri uri) {
|
||||
print('SCDeepLinkHandler 处理链接: $uri');
|
||||
// 如果需要存储为字符串,可以使用 uri.toString()
|
||||
_lnc.add(uri.toString());
|
||||
_olrc?.call(uri);
|
||||
|
||||
@ -1,12 +1,3 @@
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_svga/flutter_svga.dart';
|
||||
import 'package:yumi/shared/tools/sc_path_utils.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/file_cache_manager.dart';
|
||||
import 'package:tancent_vap/widgets/vap_view.dart';
|
||||
|
||||
import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart';
|
||||
|
||||
// class EntranceVapSvgaManager {
|
||||
// static EntranceVapSvgaManager? _instance;
|
||||
//
|
||||
@ -86,7 +77,6 @@ import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart';
|
||||
// await _playNetwork(task);
|
||||
// }
|
||||
// } catch (e, s) {
|
||||
// print('VAP_SVGA播放失败: $e\n$s');
|
||||
// _isPlaying = false;
|
||||
// } finally {
|
||||
// // 确保状态正确重置
|
||||
@ -136,7 +126,6 @@ import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart';
|
||||
// SCGiftVapSvgaManager().videoItemCache[task.path] = entity;
|
||||
// } catch (e) {
|
||||
// _isPlaying = false;
|
||||
// print('svga解析出错:$e');
|
||||
// }
|
||||
// }
|
||||
// if (entity != null) {
|
||||
|
||||
@ -99,7 +99,6 @@ class SCEntryPopupCoordinator {
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[EntryPopup] show failed: $error');
|
||||
} finally {
|
||||
_isRunning = false;
|
||||
}
|
||||
@ -448,11 +447,7 @@ class SCEntryPopupCoordinator {
|
||||
final room = await SCChatRoomRepository().specific(roomId);
|
||||
resolvedPreviewData = RoomEntryPreviewData.fromMyRoom(room);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[EntryPopup] load room preview failed roomId=$roomId: $error',
|
||||
);
|
||||
}
|
||||
} catch (error) {}
|
||||
if (!context.mounted) {
|
||||
return false;
|
||||
}
|
||||
@ -526,9 +521,7 @@ class SCEntryPopupCoordinator {
|
||||
return '';
|
||||
}
|
||||
|
||||
static void _log(String message) {
|
||||
debugPrint('[EntryPopup] $message');
|
||||
}
|
||||
static void _log(String message) {}
|
||||
|
||||
static String _clip(String value, {int maxLength = 180}) {
|
||||
if (value.length <= maxLength) {
|
||||
|
||||
@ -3,18 +3,17 @@ import 'dart:io';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class SCFileHelper{
|
||||
class SCFileHelper {
|
||||
// 将资源文件拷贝到应用文档目录
|
||||
static Future<String> copyAssetToLocal(String assetPath) async {
|
||||
|
||||
try {
|
||||
// 获取应用文档目录
|
||||
final Directory appDocDir = await getApplicationDocumentsDirectory();
|
||||
final String localFilePath = '${appDocDir.path}/${assetPath.split('/').last}';
|
||||
final String localFilePath =
|
||||
'${appDocDir.path}/${assetPath.split('/').last}';
|
||||
|
||||
// 检查文件是否已存在
|
||||
if (await File(localFilePath).exists()) {
|
||||
print('文件已存在,直接使用: $localFilePath');
|
||||
return localFilePath;
|
||||
}
|
||||
|
||||
@ -26,13 +25,9 @@ class SCFileHelper{
|
||||
final File localFile = File(localFilePath);
|
||||
await localFile.writeAsBytes(bytes);
|
||||
|
||||
print('文件拷贝成功: $localFilePath');
|
||||
return localFilePath;
|
||||
} catch (e) {
|
||||
print('拷贝文件时发生错误: $e');
|
||||
rethrow; // 重新抛出异常以便上层处理
|
||||
} finally {
|
||||
|
||||
}
|
||||
} finally {}
|
||||
}
|
||||
}
|
||||
@ -73,9 +73,7 @@ class SCGiftVapSvgaManager {
|
||||
return _mute;
|
||||
}
|
||||
|
||||
void _log(String message) {
|
||||
debugPrint('[GiftFX][Player] $message');
|
||||
}
|
||||
void _log(String message) {}
|
||||
|
||||
bool _needsSvgaController(String path) {
|
||||
return SCPathUtils.getFileExtension(path).toLowerCase() == ".svga";
|
||||
@ -554,11 +552,9 @@ class SCGiftVapSvgaManager {
|
||||
} else if (pathType == PathType.network) {
|
||||
await _pnw(task);
|
||||
} else {
|
||||
debugPrint('VAP_SVGA不支持的路径类型: ${task.path}');
|
||||
_finishCurrentTask();
|
||||
}
|
||||
} catch (e, s) {
|
||||
debugPrint('VAP_SVGA播放失败: $e\n$s');
|
||||
_finishCurrentTask();
|
||||
}
|
||||
}
|
||||
@ -636,7 +632,6 @@ class SCGiftVapSvgaManager {
|
||||
try {
|
||||
entity = await _loadSvgaEntity(task.path);
|
||||
} catch (e) {
|
||||
debugPrint('svga解析出错:$e');
|
||||
_finishCurrentTask();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
|
||||
///谷歌授权登录
|
||||
@ -45,7 +44,6 @@ class SCGoogleAuthService {
|
||||
|
||||
return userCredential.user;
|
||||
} catch (e) {
|
||||
debugPrint('Google sign-in error: $e');
|
||||
rethrow; // 抛出异常让调用者处理
|
||||
}
|
||||
}
|
||||
@ -75,7 +73,6 @@ class SCGoogleAuthService {
|
||||
|
||||
return userCredential.user;
|
||||
} catch (e) {
|
||||
debugPrint('Silent sign-in error: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -87,7 +84,6 @@ class SCGoogleAuthService {
|
||||
await _g.signOut();
|
||||
await FirebaseAuth.instance.signOut();
|
||||
} catch (e) {
|
||||
debugPrint('Sign out error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||||
|
||||
@ -41,10 +40,8 @@ class SCInstallReferrerUtils {
|
||||
}
|
||||
return inviteCode;
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('get install referrer failed: ${e.code} ${e.message}');
|
||||
return '';
|
||||
} catch (e) {
|
||||
debugPrint('get install referrer failed: $e');
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/shared/tools/sc_room_utils.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/services/audio/rtc_manager.dart';
|
||||
@ -38,7 +37,10 @@ void showEnterRoomConfirm(
|
||||
: SCAppLocalizations.of(context)!.enterRoomConfirmTips,
|
||||
btnText: SCAppLocalizations.of(context)!.confirm,
|
||||
onEnsure: () {
|
||||
Provider.of<RealTimeCommunicationManager>(context, listen: false).joinVoiceRoomSession(
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).joinVoiceRoomSession(
|
||||
context,
|
||||
roomId,
|
||||
needOpenRedenvelope: needOpenRedenvelope,
|
||||
@ -86,9 +88,6 @@ showCenterAnimationDialog(BuildContext context, Widget child) {
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
print(
|
||||
'showCenterAnimationDialog:${animation.value},${secondaryAnimation.value}',
|
||||
);
|
||||
CurvedAnimation curvedAnimation = CurvedAnimation(
|
||||
curve: Curves.bounceOut,
|
||||
reverseCurve: Curves.easeInExpo,
|
||||
@ -403,7 +402,10 @@ class SCTsDialog extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
VerticalDivider(width: width(1), color: SocialChatTheme.dividerColor),
|
||||
VerticalDivider(
|
||||
width: width(1),
|
||||
color: SocialChatTheme.dividerColor,
|
||||
),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||||
|
||||
class SCLuckyGiftWinSoundPlayer {
|
||||
@ -45,9 +44,7 @@ class SCLuckyGiftWinSoundPlayer {
|
||||
try {
|
||||
await _player.stop();
|
||||
await _player.play(AssetSource(assetPath));
|
||||
} catch (error) {
|
||||
debugPrint('播放幸运礼物中奖音效失败: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
static String _formatNum(num? value) {
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
class SCMessageNotifier {
|
||||
|
||||
class SCMessageNotifier {
|
||||
static bool canPlay = true;
|
||||
static final AudioPlayer _a = AudioPlayer();
|
||||
// 播放提示音
|
||||
static Future<void> playNotificationSound() async {
|
||||
if(!canPlay){
|
||||
if (!canPlay) {
|
||||
return;
|
||||
}
|
||||
// _audioPlayer.setVolume(0.2);
|
||||
try {
|
||||
_a.play(AssetSource("sc_images/msg/im_noti_music.MP3"));
|
||||
} catch (e) {
|
||||
print('播放提示音失败: $e');
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,7 +3,6 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
|
||||
@ -22,32 +21,25 @@ class SCMessageUtils {
|
||||
// 2. 获取文件信息
|
||||
final originalSize = file.lengthSync();
|
||||
final fileExtension = _ge(file.path).toLowerCase();
|
||||
print('压缩前文件: ${file.path}');
|
||||
print('文件类型: $fileExtension');
|
||||
print('压缩前大小: ${_fs(originalSize)}');
|
||||
|
||||
// 3. 小文件不压缩(小于 100KB)
|
||||
if (originalSize < 100 * 1024) {
|
||||
print('文件较小,跳过压缩');
|
||||
return file;
|
||||
}
|
||||
|
||||
// 4. GIF 文件特殊处理
|
||||
if (fileExtension == 'gif') {
|
||||
print('GIF 文件,使用特殊处理');
|
||||
return await _gf(file);
|
||||
}
|
||||
|
||||
// 5. 创建临时目录和文件
|
||||
final directory = await getTemporaryDirectory();
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
final String fileName =
|
||||
'compressed_${timestamp}_${_fh(file)}.jpg';
|
||||
final String fileName = 'compressed_${timestamp}_${_fh(file)}.jpg';
|
||||
final File newFile = File("${directory.path}/$fileName");
|
||||
|
||||
// 6. 动态调整压缩质量(根据原文件大小)
|
||||
final int quality = _cq(originalSize);
|
||||
print('使用压缩质量: $quality%');
|
||||
|
||||
// 7. 执行压缩
|
||||
final XFile? compressedFile =
|
||||
@ -65,7 +57,6 @@ class SCMessageUtils {
|
||||
);
|
||||
|
||||
if (compressedFile == null) {
|
||||
print('压缩失败,返回原文件');
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -74,12 +65,8 @@ class SCMessageUtils {
|
||||
final compressionRatio =
|
||||
(originalSize - compressedSize) / originalSize * 100;
|
||||
|
||||
print('压缩后大小: ${_fs(compressedSize)}');
|
||||
print('压缩率: ${compressionRatio.toStringAsFixed(1)}%');
|
||||
|
||||
// 9. 如果压缩后文件反而更大,返回原文件
|
||||
if (compressedSize >= originalSize) {
|
||||
print('压缩后文件更大,返回原文件');
|
||||
await newFile.delete(); // 删除无用的压缩文件
|
||||
return file;
|
||||
}
|
||||
@ -89,10 +76,8 @@ class SCMessageUtils {
|
||||
final String cacheKey = _fh(localFile);
|
||||
await FileCacheManager.getInstance().putFileFromFile(cacheKey, localFile);
|
||||
|
||||
print('压缩成功,发送路径: ${compressedFile.path}');
|
||||
return localFile;
|
||||
} catch (e) {
|
||||
print('图片压缩异常: $e');
|
||||
return file; // 异常时返回原文件,保证功能可用
|
||||
}
|
||||
}
|
||||
@ -152,7 +137,6 @@ class SCMessageUtils {
|
||||
// 3. 或者直接返回原文件(保持动图效果)
|
||||
|
||||
// 这里简单返回原文件,避免破坏 GIF 动画
|
||||
print('GIF 文件保持原样发送');
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -172,7 +156,6 @@ class SCMessageUtils {
|
||||
);
|
||||
return thumbnailPath; // 返回文件路径,可用于 Image.file(File(thumbnailPath!))
|
||||
} catch (e) {
|
||||
print("生成缩略图文件时出错: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class SCMobileLoginContext {
|
||||
@ -36,10 +35,7 @@ class SCMobileLoginContext {
|
||||
return value;
|
||||
}
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('get mobile timezone failed: ${e.code} ${e.message}');
|
||||
} catch (e) {
|
||||
debugPrint('get mobile timezone failed: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
return _fallbackZone();
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@ import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||
class SCPickUtils {
|
||||
static final ImagePicker _pkr = ImagePicker();
|
||||
|
||||
static void pickImage(BuildContext context,
|
||||
static void pickImage(
|
||||
BuildContext context,
|
||||
OnUpLoadCallBack onUpLoadCallBack, {
|
||||
double? aspectRatio,
|
||||
bool? backOriginalFile = true,
|
||||
@ -65,12 +66,10 @@ class SCPickUtils {
|
||||
}
|
||||
} catch (e) {
|
||||
onUpLoadCallBack?.call(false, "");
|
||||
print("Image selection error: $e");
|
||||
SCTts.show("Failed to select image");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 检查图像是否为 GIF 格式
|
||||
static Future<bool> _igif(XFile file) async {
|
||||
try {
|
||||
@ -89,7 +88,6 @@ class SCPickUtils {
|
||||
|
||||
return false;
|
||||
} catch (e) {
|
||||
print("Error checking GIF: $e");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -119,33 +117,39 @@ class SCPickUtils {
|
||||
// 检查扩展的 WebP 格式(如果有更多字节可用)
|
||||
if (bytes.length >= 16) {
|
||||
// 检查 VP8 (有损) WebP
|
||||
if (bytes[12] == 0x56 && bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 && bytes[15] == 0x20) {
|
||||
if (bytes[12] == 0x56 &&
|
||||
bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 &&
|
||||
bytes[15] == 0x20) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查 VP8L (无损) WebP
|
||||
if (bytes[12] == 0x56 && bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 && bytes[15] == 0x4C) {
|
||||
if (bytes[12] == 0x56 &&
|
||||
bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 &&
|
||||
bytes[15] == 0x4C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查 VP8X (扩展) WebP
|
||||
if (bytes[12] == 0x56 && bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 && bytes[15] == 0x58) {
|
||||
if (bytes[12] == 0x56 &&
|
||||
bytes[13] == 0x50 &&
|
||||
bytes[14] == 0x38 &&
|
||||
bytes[15] == 0x58) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (e) {
|
||||
print("Error checking WebP: $e");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 拍照并过滤 GIF
|
||||
static void takePhoto(BuildContext context,
|
||||
static void takePhoto(
|
||||
BuildContext context,
|
||||
OnUpLoadCallBack onUpLoadCallBack, {
|
||||
double? aspectRatio,
|
||||
bool? backOriginalFile = true,
|
||||
@ -175,7 +179,6 @@ class SCPickUtils {
|
||||
onUpLoadCallBack,
|
||||
);
|
||||
} catch (e) {
|
||||
print("Camera error: $e");
|
||||
SCTts.show("Camera failed");
|
||||
}
|
||||
}
|
||||
@ -192,19 +195,18 @@ class SCPickUtils {
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
print("Video selection error: $e");
|
||||
SCTts.show("Failed to select video_pic");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 原有的 cropImage 方法保持不变
|
||||
static void cropImage(File originalImage,
|
||||
static void cropImage(
|
||||
File originalImage,
|
||||
BuildContext context,
|
||||
double? aspectRatio,
|
||||
bool? backOriginalFile,
|
||||
OnUpLoadCallBack onUpLoadCallBack,
|
||||
{
|
||||
OnUpLoadCallBack onUpLoadCallBack, {
|
||||
bool needUpload = true,
|
||||
}) async {
|
||||
if (originalImage == null) {
|
||||
@ -213,12 +215,12 @@ class SCPickUtils {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
CropImagePage(
|
||||
builder:
|
||||
(context) => CropImagePage(
|
||||
originalImage,
|
||||
aspectRatio: aspectRatio,
|
||||
backOriginalFile: backOriginalFile,
|
||||
needUpload:needUpload,
|
||||
needUpload: needUpload,
|
||||
onUpLoadCallBack: (success, url) {
|
||||
if (url.isNotEmpty) {
|
||||
onUpLoadCallBack(success, url);
|
||||
|
||||
@ -108,11 +108,7 @@ class SCRoomEffectScheduler {
|
||||
);
|
||||
try {
|
||||
task.action();
|
||||
} catch (error, stackTrace) {
|
||||
debugPrint(
|
||||
'[RoomEffectScheduler] deferred task failed: $error\n$stackTrace',
|
||||
);
|
||||
}
|
||||
} catch (error, stackTrace) {}
|
||||
|
||||
_scheduleDeferredDrainIfNeeded();
|
||||
}
|
||||
@ -122,9 +118,7 @@ class SCRoomEffectScheduler {
|
||||
_deferredDrainTimer = null;
|
||||
}
|
||||
|
||||
void _log(String message) {
|
||||
debugPrint('[RoomEffectScheduler] $message');
|
||||
}
|
||||
void _log(String message) {}
|
||||
}
|
||||
|
||||
class _DeferredRoomEffectTask {
|
||||
|
||||
@ -3,7 +3,12 @@ import 'dart:ui';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
richText({required String txt, required String key, Color highlight = Colors.red, Color defaultColor = Colors.black}) {
|
||||
richText({
|
||||
required String txt,
|
||||
required String key,
|
||||
Color highlight = Colors.red,
|
||||
Color defaultColor = Colors.black,
|
||||
}) {
|
||||
assert(txt != null);
|
||||
assert(key != null);
|
||||
if (txt.contains(key)) {
|
||||
@ -16,13 +21,17 @@ richText({required String txt, required String key, Color highlight = Colors.red
|
||||
if (sps.length > 0) {
|
||||
List<TextSpan> textSpanList = [];
|
||||
for (String sp in sps) {
|
||||
print(sp);
|
||||
textSpanList.add(TextSpan(text: sp, style: TextStyle(color: sp == key ? highlight : defaultColor)));
|
||||
textSpanList.add(
|
||||
TextSpan(
|
||||
text: sp,
|
||||
style: TextStyle(color: sp == key ? highlight : defaultColor),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Text.rich(TextSpan(children: textSpanList));
|
||||
}
|
||||
}
|
||||
return Text(txt, style: TextStyle(color: defaultColor),);
|
||||
return Text(txt, style: TextStyle(color: defaultColor));
|
||||
}
|
||||
|
||||
List<String> splitStr(String txt, String key) {
|
||||
@ -45,7 +54,6 @@ List<String> splitStr(String txt, String key) {
|
||||
index = localIndex;
|
||||
}
|
||||
}
|
||||
print('所有的索引:${indexes.toString()}');
|
||||
|
||||
List<String> results = [];
|
||||
|
||||
@ -58,10 +66,20 @@ List<String> splitStr(String txt, String key) {
|
||||
results.add(txt.substring(0, keyLength));
|
||||
} else {
|
||||
results.add(txt.substring(0, indexes[indexArrayIndex]));
|
||||
results.add(txt.substring(indexes[indexArrayIndex], indexes[indexArrayIndex] + keyLength));
|
||||
results.add(
|
||||
txt.substring(
|
||||
indexes[indexArrayIndex],
|
||||
indexes[indexArrayIndex] + keyLength,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
results.add(txt.substring(indexes[indexArrayIndex], indexes[indexArrayIndex] + keyLength));
|
||||
results.add(
|
||||
txt.substring(
|
||||
indexes[indexArrayIndex],
|
||||
indexes[indexArrayIndex] + keyLength,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
int endIndex = indexes[indexArrayIndex] + keyLength;
|
||||
@ -85,10 +103,8 @@ List<String> splitStr(String txt, String key) {
|
||||
indexArrayIndex += 1;
|
||||
}
|
||||
|
||||
print('迭代的结果:$results');
|
||||
return results;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@ -218,7 +218,6 @@ Widget netImage({
|
||||
Widget? loadingWidget,
|
||||
Widget? errorWidget,
|
||||
}) {
|
||||
// print('${SCGlobalConfig.imgHost}$image?imageslim');
|
||||
return ExtendedImage.network(
|
||||
url,
|
||||
width: width,
|
||||
@ -334,7 +333,6 @@ msgRoleTag(String role, {double? width, double? height}) {
|
||||
|
||||
///性别 0女 1男
|
||||
xb(num? sex, {double? height, Color? color = Colors.white}) {
|
||||
// print('sex:$sex');
|
||||
// if (sex == null) return Container();
|
||||
String image = "sc_images/login/sc_icon_sex_man.png";
|
||||
if (sex == 0) {
|
||||
@ -349,7 +347,6 @@ xb(num? sex, {double? height, Color? color = Colors.white}) {
|
||||
}
|
||||
|
||||
xb2(num? sex, {double? width, double? height}) {
|
||||
// print('sex:$sex');
|
||||
if (sex == null) return Container();
|
||||
String image = "sc_images/login/sc_icon_sex_man_bg.png";
|
||||
if (sex == 0) {
|
||||
|
||||
@ -47,9 +47,11 @@ class _IndexBannerPageState extends State<IndexBannerPage> {
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
),
|
||||
onTap: () {
|
||||
print('ads:${widget.res.toJson()}');
|
||||
SmartDialog.dismiss(tag: "showBannerDialog");
|
||||
SCBannerUtils.openBanner(widget.res, navigatorKey.currentState!.context);
|
||||
SCBannerUtils.openBanner(
|
||||
widget.res,
|
||||
navigatorKey.currentState!.context,
|
||||
);
|
||||
},
|
||||
),
|
||||
PositionedDirectional(
|
||||
|
||||
@ -273,12 +273,6 @@ class _DailySignInDialogState extends State<DailySignInDialog> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_data = widget.data;
|
||||
debugPrint(
|
||||
'[SignInReward][Dialog] init '
|
||||
'checkedToday=${_data.checkedToday} '
|
||||
'currentDay=${_data.currentItem?.day ?? 0} '
|
||||
'items=${_debugItemsSummary(_data.items)}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleCheckIn() async {
|
||||
@ -301,10 +295,6 @@ class _DailySignInDialogState extends State<DailySignInDialog> {
|
||||
_isSubmitting = true;
|
||||
});
|
||||
SCLoadingManager.show();
|
||||
debugPrint(
|
||||
'[SignInReward][Dialog] tap check-in '
|
||||
'currentDay=${currentItem.day}',
|
||||
);
|
||||
|
||||
try {
|
||||
final checkInResult = await SCAccountRepository().signInRewardCheckIn();
|
||||
@ -314,14 +304,9 @@ class _DailySignInDialogState extends State<DailySignInDialog> {
|
||||
|
||||
DailySignInDialogData latestData;
|
||||
try {
|
||||
debugPrint('[SignInReward][Dialog] reload status after check-in');
|
||||
final latestStatus = await SCAccountRepository().signInRewardStatus();
|
||||
latestData = DailySignInDialogData.fromStatus(statusRes: latestStatus);
|
||||
} catch (_) {
|
||||
debugPrint(
|
||||
'[SignInReward][Dialog] reload status failed, fallback to local update '
|
||||
'dayIndex=${checkInResult.dayIndex}',
|
||||
);
|
||||
latestData = _markDayAsClaimed(_data, checkInResult.dayIndex);
|
||||
}
|
||||
|
||||
@ -332,22 +317,14 @@ class _DailySignInDialogState extends State<DailySignInDialog> {
|
||||
setState(() {
|
||||
_data = latestData;
|
||||
});
|
||||
debugPrint(
|
||||
'[SignInReward][Dialog] check-in success '
|
||||
'alreadySigned=${checkInResult.alreadySigned} '
|
||||
'dayIndex=${checkInResult.dayIndex} '
|
||||
'checkedToday=${latestData.checkedToday}',
|
||||
);
|
||||
final toastMessage =
|
||||
checkInResult.alreadySigned
|
||||
? l10n.signedin
|
||||
: _rewardToastMessage(l10n, checkInResult.rewardItems);
|
||||
debugPrint('[SignInReward][Dialog] reward toast=$toastMessage');
|
||||
SCTts.show(toastMessage);
|
||||
SmartDialog.dismiss(tag: DailySignInDialog.dialogTag);
|
||||
} catch (error) {
|
||||
SCLoadingManager.hide();
|
||||
debugPrint('[SignInReward][Dialog] check-in failed error=$error');
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -380,7 +380,6 @@ class _ConversationItemState extends State<ConversationItem> {
|
||||
return Container();
|
||||
}
|
||||
}*/
|
||||
// print('time :${Platform.isAndroid ? (conversation.lastMsg?.timestamp ?? 0) * 1000 : conversation.lastMsg?.timestamp}');
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
if (_isC2CConversation && (conversation.userID?.isEmpty ?? true)) {
|
||||
|
||||
@ -91,11 +91,6 @@ class _RoomAnimationQueueScreenState extends State<RoomAnimationQueueScreen> {
|
||||
isLowPerformance && floatPictureFallbackUrl.isNotEmpty
|
||||
? floatPictureFallbackUrl
|
||||
: floatPictureUrl;
|
||||
debugPrint(
|
||||
'[VIP][RoomFloat] enqueue entry float '
|
||||
'userId=${msg.user?.id} roomId=$roomId resourceId=${floatPicture?.id} '
|
||||
'url=$displayUrl',
|
||||
);
|
||||
final floatingMessage = SCFloatingMessage(
|
||||
type: 5,
|
||||
userId: msg.user?.id,
|
||||
@ -220,7 +215,6 @@ class _RoomAnimationQueueScreenState extends State<RoomAnimationQueueScreen> {
|
||||
});
|
||||
} else {
|
||||
// 重试多次失败后,跳过当前动画
|
||||
debugPrint("动画启动失败,跳过当前任务");
|
||||
task.onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,9 +458,7 @@ class _RoomEntranceWidgetState extends State<RoomEntranceWidget>
|
||||
),
|
||||
key,
|
||||
);
|
||||
} catch (e) {
|
||||
print('设置文本占位符 $key 失败: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -479,9 +477,7 @@ class _RoomEntranceWidgetState extends State<RoomEntranceWidget>
|
||||
if (videoItem.images!.containsKey(key)) {
|
||||
videoItem.images![key] = imageData;
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置图片占位符 $key 失败: $e');
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -701,9 +697,7 @@ class RoomEntranceExample extends StatelessWidget {
|
||||
RoomEntranceHelper.addEntranceAnimation(
|
||||
resource: 'assets/animations/entrance.svga',
|
||||
textReplacements: {'username': '张三', 'level': 'VIP 10'},
|
||||
onCompleted: () {
|
||||
print('入场动画播放完成');
|
||||
},
|
||||
onCompleted: () {},
|
||||
);
|
||||
},
|
||||
child: Text('播放入场动画'),
|
||||
@ -724,7 +718,6 @@ class RoomEntranceExample extends StatelessWidget {
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
final status = RoomEntranceHelper.getQueueStatus();
|
||||
print('队列状态: $status');
|
||||
},
|
||||
child: Text('查看队列状态'),
|
||||
),
|
||||
|
||||
@ -527,9 +527,6 @@ class _RoomGiftSeatFlightOverlayState extends State<RoomGiftSeatFlightOverlay>
|
||||
if (!_isPlaying || _activeFlights.isEmpty) {
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
'[GiftSeatFlight] watchdog timeout active=${_activeFlights.length}',
|
||||
);
|
||||
_controller.stop();
|
||||
_finishCurrentAnimation();
|
||||
});
|
||||
|
||||
@ -59,9 +59,7 @@ class _LuckGiftNomorAnimWidgetState extends State<LuckGiftNomorAnimWidget> {
|
||||
if (avatarImage != null) {
|
||||
movieEntity.dynamicItem.setImage(avatarImage, _avatarDynamicKey);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint('[LuckGiftBurstSVGA] avatar sync failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
try {
|
||||
@ -77,9 +75,7 @@ class _LuckGiftNomorAnimWidgetState extends State<LuckGiftNomorAnimWidget> {
|
||||
awardAmountImage,
|
||||
_awardAmountDynamicKey,
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[LuckGiftBurstSVGA] award amount sync failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
final multiple = rewardData.multiple ?? 0;
|
||||
if (multiple > 0) {
|
||||
@ -93,9 +89,7 @@ class _LuckGiftNomorAnimWidgetState extends State<LuckGiftNomorAnimWidget> {
|
||||
shadowColor: const Color(0x990B2D72),
|
||||
);
|
||||
movieEntity.dynamicItem.setImage(multipleImage, _multipleDynamicKey);
|
||||
} catch (error) {
|
||||
debugPrint('[LuckGiftBurstSVGA] multiple sync failed: $error');
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,9 +17,7 @@ class _VapPlusSvgaPlayerState extends State<VapPlusSvgaPlayer>
|
||||
with TickerProviderStateMixin {
|
||||
late SVGAAnimationController _svgaController;
|
||||
|
||||
void _giftFxLog(String message) {
|
||||
debugPrint('[GiftFX][Widget] $message');
|
||||
}
|
||||
void _giftFxLog(String message) {}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
||||
@ -60,8 +60,7 @@ class _ExploreBannerViewState extends State<ExploreBannerView> {
|
||||
borderRadius: BorderRadius.circular(12.w),
|
||||
),
|
||||
onTap: () {
|
||||
print('ads:${item.toJson()}');
|
||||
SCBannerUtils.openBanner(item,context);
|
||||
SCBannerUtils.openBanner(item, context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
|
||||
@ -213,17 +213,13 @@ class _FloatingLuckGiftScreenWidgetState
|
||||
if (avatarImage != null) {
|
||||
movieEntity.dynamicItem.setImage(avatarImage, _avatarDynamicKey);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint("[LuckGiftSVGA] avatar sync failed: $error");
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
try {
|
||||
final textImage = await _buildBannerTextImage();
|
||||
movieEntity.dynamicItem.setImage(textImage, _textDynamicKey);
|
||||
} catch (error) {
|
||||
debugPrint("[LuckGiftSVGA] text sync failed: $error");
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
final multipleValue = widget.message.multiple ?? 0;
|
||||
if (multipleValue > 0) {
|
||||
|
||||
@ -229,9 +229,7 @@ class _FloatingVipEntryScreenWidgetState
|
||||
if (avatarImage != null) {
|
||||
movieEntity.dynamicItem.setImage(avatarImage, _avatarDynamicKey);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint("[VIP][RoomFloat][SVGA] avatar sync failed: $error");
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
final nickname = (widget.message.userName ?? "").trim();
|
||||
@ -266,9 +264,7 @@ class _FloatingVipEntryScreenWidgetState
|
||||
)..layout(maxWidth: 220),
|
||||
_nicknameDynamicKey,
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint("[VIP][RoomFloat][SVGA] nickname sync failed: $error");
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,10 +281,6 @@ class _FloatingVipEntryScreenWidgetState
|
||||
if (missing.isEmpty) {
|
||||
return;
|
||||
}
|
||||
debugPrint(
|
||||
"[VIP][RoomFloat][SVGA] dynamic keys missing=${missing.join(",")} "
|
||||
"available=${keys.take(30).join(",")}",
|
||||
);
|
||||
}
|
||||
|
||||
Future<ui.Image?> _loadCircularUiImage(
|
||||
|
||||
@ -5,9 +5,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/shared/tools/sc_banner_utils.dart';
|
||||
import 'package:yumi/shared/tools/sc_string_utils.dart';
|
||||
import 'package:yumi/services/general/sc_app_general_manager.dart';
|
||||
import 'package:yumi/ui_kit/widgets/pop/pop_route.dart';
|
||||
|
||||
class RecommendBannerView extends StatefulWidget {
|
||||
@override
|
||||
@ -67,8 +65,7 @@ class _RecommendBannerViewState extends State<RecommendBannerView> {
|
||||
borderRadius: BorderRadius.circular(12.w),
|
||||
),
|
||||
onTap: () {
|
||||
print('ads:${item.toJson()}');
|
||||
SCBannerUtils.openBanner(item,context);
|
||||
SCBannerUtils.openBanner(item, context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
|
||||
@ -46,10 +46,7 @@ class RoomRedPacketUiData {
|
||||
|
||||
factory RoomRedPacketUiData.fromListRes(SCRoomRedPacketListRes res) {
|
||||
final countdown = res.countdown ?? 0;
|
||||
final claimStartTimeMs = _claimStartTimeMsFromValues(
|
||||
claimStartTime: res.claimStartTime,
|
||||
countdown: countdown,
|
||||
);
|
||||
final claimStartTimeMs = _claimStartTimeMsFromValue(res.claimStartTime);
|
||||
return RoomRedPacketUiData(
|
||||
packetId: res.packetId ?? '',
|
||||
senderName: res.userName ?? '',
|
||||
@ -86,9 +83,8 @@ class RoomRedPacketUiData {
|
||||
final fallbackAvatar = fallbackUser?.userAvatar ?? '';
|
||||
final fallbackId = fallbackUser?.id ?? '';
|
||||
final countdown = _intValue(json, const ['countdown']);
|
||||
final claimStartTimeMs = _claimStartTimeMsFromValues(
|
||||
claimStartTime: _firstValue(json, const ['claimStartTime']),
|
||||
countdown: countdown,
|
||||
final claimStartTimeMs = _claimStartTimeMsFromValue(
|
||||
_firstValue(json, const ['claimStartTime']),
|
||||
);
|
||||
final totalCount = _numValue(json, const ['totalCount', 'count']);
|
||||
final remainCount =
|
||||
@ -202,7 +198,7 @@ class RoomRedPacketUiData {
|
||||
}
|
||||
return (diff / 1000).ceil();
|
||||
}
|
||||
return countdown > 0 ? countdown : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool get isWaiting => waitingSeconds > 0;
|
||||
@ -345,17 +341,11 @@ class RoomRedPacketUiData {
|
||||
return null;
|
||||
}
|
||||
|
||||
static int _claimStartTimeMsFromValues({
|
||||
required dynamic claimStartTime,
|
||||
required int countdown,
|
||||
}) {
|
||||
static int _claimStartTimeMsFromValue(dynamic claimStartTime) {
|
||||
final parsedClaimStartTime = _timestampValueFromDynamic(claimStartTime);
|
||||
if (parsedClaimStartTime > 0) {
|
||||
return parsedClaimStartTime;
|
||||
}
|
||||
if (countdown > 0) {
|
||||
return DateTime.now().millisecondsSinceEpoch + countdown * 1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -537,10 +537,14 @@ class _RoomRedPacketSendPanelState extends State<RoomRedPacketSendPanel> {
|
||||
listen: false,
|
||||
).updateBalance(balanceAfter.toDouble());
|
||||
}
|
||||
final redPacketResult = await _resolveServerTimedRedPacketResult(result);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
rtcProvider.loadRoomRedPacketList(1).catchError((_) {
|
||||
return rtcProvider.redPacketList;
|
||||
});
|
||||
_showSentRedPacketFallback(result, rtcProvider);
|
||||
_showSentRedPacketFallback(redPacketResult, rtcProvider);
|
||||
SmartDialog.dismiss(tag: RoomRedPacketSendPanel.dialogTag);
|
||||
SCTts.show(localizations.roomRedPacketSendSuccess);
|
||||
} catch (error) {
|
||||
@ -559,6 +563,86 @@ class _RoomRedPacketSendPanelState extends State<RoomRedPacketSendPanel> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<SCRoomRedPacketListRes> _resolveServerTimedRedPacketResult(
|
||||
SCRoomRedPacketListRes result,
|
||||
) async {
|
||||
if (!_isDelayedRedPacketResult(result) ||
|
||||
_hasServerClaimStartTime(result)) {
|
||||
return result;
|
||||
}
|
||||
final packetId = (result.packetId ?? '').trim();
|
||||
if (packetId.isEmpty) {
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
final detail = await SCChatRoomRepository().roomRedPacketDetail(packetId);
|
||||
final claimStartTime = (detail.claimStartTime ?? '').trim();
|
||||
if (claimStartTime.isEmpty) {
|
||||
return result;
|
||||
}
|
||||
return SCRoomRedPacketListRes(
|
||||
packetId: _preferNonEmptyText(result.packetId, detail.packetId),
|
||||
packetMode: result.packetMode ?? 'DELAYED',
|
||||
roomId: result.roomId,
|
||||
userId: result.userId ?? detail.userId,
|
||||
userName: _preferNonEmptyText(result.userName, detail.userName),
|
||||
userAvatar: _preferNonEmptyText(result.userAvatar, detail.userAvatar),
|
||||
packetType: result.packetType ?? detail.packetType,
|
||||
packetTypeDesc: _preferNonEmptyText(
|
||||
result.packetTypeDesc,
|
||||
detail.packetTypeDesc,
|
||||
),
|
||||
sourceType: result.sourceType,
|
||||
totalAmount: result.totalAmount ?? detail.totalAmount,
|
||||
totalCount: result.totalCount ?? detail.totalCount,
|
||||
remainAmount: result.remainAmount ?? detail.remainAmount,
|
||||
remainCount: result.remainCount ?? detail.remainCount,
|
||||
expireMinutes: result.expireMinutes,
|
||||
expireTime: _preferNonEmptyText(result.expireTime, detail.expireTime),
|
||||
claimStartTime: claimStartTime,
|
||||
balanceAfter: result.balanceAfter,
|
||||
countdown: result.countdown,
|
||||
status: detail.status ?? result.status,
|
||||
statusDesc: _preferNonEmptyText(detail.statusDesc, result.statusDesc),
|
||||
grabbed: detail.grabbed ?? result.grabbed,
|
||||
createTime: _preferNonEmptyText(result.createTime, detail.createTime),
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][SendFallback] load server claimStartTime failed '
|
||||
'packetId=$packetId error=$error',
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool _isDelayedRedPacketResult(SCRoomRedPacketListRes result) {
|
||||
final packetMode = (result.packetMode ?? '').trim().toUpperCase();
|
||||
if (packetMode == 'DELAYED') {
|
||||
return true;
|
||||
}
|
||||
if (packetMode == 'IMMEDIATE') {
|
||||
return false;
|
||||
}
|
||||
return _selectedPickupMinutes > 0;
|
||||
}
|
||||
|
||||
bool _hasServerClaimStartTime(SCRoomRedPacketListRes result) {
|
||||
return (result.claimStartTime ?? '').trim().isNotEmpty;
|
||||
}
|
||||
|
||||
String? _preferNonEmptyText(String? primary, String? fallback) {
|
||||
final primaryText = primary?.trim();
|
||||
if (primaryText != null && primaryText.isNotEmpty) {
|
||||
return primary;
|
||||
}
|
||||
final fallbackText = fallback?.trim();
|
||||
if (fallbackText != null && fallbackText.isNotEmpty) {
|
||||
return fallback;
|
||||
}
|
||||
return primary ?? fallback;
|
||||
}
|
||||
|
||||
void _showSentRedPacketFallback(
|
||||
SCRoomRedPacketListRes result,
|
||||
RtcProvider rtcProvider,
|
||||
@ -579,12 +663,14 @@ class _RoomRedPacketSendPanelState extends State<RoomRedPacketSendPanel> {
|
||||
final senderName =
|
||||
currentUser?.userNickname ?? result.userName ?? 'Lucky Pack';
|
||||
final senderAvatar = currentUser?.userAvatar ?? result.userAvatar ?? '';
|
||||
final nowMs = DateTime.now().millisecondsSinceEpoch;
|
||||
final claimStartTime =
|
||||
result.claimStartTime ??
|
||||
(_selectedPickupMinutes > 0
|
||||
? (nowMs + _selectedPickupMinutes * 60 * 1000).toString()
|
||||
: '');
|
||||
final claimStartTime = (result.claimStartTime ?? '').trim();
|
||||
if (_isDelayedRedPacketResult(result) && claimStartTime.isEmpty) {
|
||||
debugPrint(
|
||||
'[RoomRedPacket][SendFallback] skip delayed local UI because server '
|
||||
'claimStartTime is empty packetId=$packetId',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final payload =
|
||||
Map<String, dynamic>.from(result.toJson())
|
||||
..['packetId'] = packetId
|
||||
@ -602,11 +688,17 @@ class _RoomRedPacketSendPanelState extends State<RoomRedPacketSendPanel> {
|
||||
..['packetMode'] =
|
||||
result.packetMode ??
|
||||
(_selectedPickupMinutes <= 0 ? 'IMMEDIATE' : 'DELAYED')
|
||||
..['countdown'] =
|
||||
result.countdown ??
|
||||
(_selectedPickupMinutes > 0 ? _selectedPickupMinutes * 60 : 0)
|
||||
..['claimStartTime'] = claimStartTime
|
||||
..['grabbed'] = result.grabbed ?? false;
|
||||
if (result.countdown != null) {
|
||||
payload['countdown'] = result.countdown;
|
||||
} else {
|
||||
payload.remove('countdown');
|
||||
}
|
||||
if (claimStartTime.isNotEmpty) {
|
||||
payload['claimStartTime'] = claimStartTime;
|
||||
} else {
|
||||
payload.remove('claimStartTime');
|
||||
}
|
||||
final roomRegionCode = rtcProvider.currenRoom?.roomProfile?.regionCode;
|
||||
if ((payload['regionCode']?.toString().trim() ?? '').isEmpty &&
|
||||
(roomRegionCode?.trim().isNotEmpty ?? false)) {
|
||||
|
||||
@ -56,14 +56,13 @@ class _RoomBannerViewState extends State<RoomBannerView> {
|
||||
return GestureDetector(
|
||||
child: netImage(url: item.smallCover ?? ""),
|
||||
onTap: () {
|
||||
print('ads:${item.toJson()}');
|
||||
SCBannerUtils.openBanner(item, context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
scrollDirection:Axis.horizontal,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children:
|
||||
|
||||
@ -1700,9 +1700,6 @@ class _MsgItemState extends State<MsgItem> {
|
||||
} catch (error) {
|
||||
_userInfoFailedAt[userId] = DateTime.now();
|
||||
_userInfoFutures.remove(userId);
|
||||
debugPrint(
|
||||
'[RoomChat][UserInfo] load failed userId=$userId error=$error',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@ -88,7 +88,6 @@ class _SCNinePatchImageState extends State<SCNinePatchImage> {
|
||||
if (!mounted || serial != _resolveSerial) {
|
||||
return;
|
||||
}
|
||||
debugPrint("[SCNinePatchImage] load failed url=$url error=$error");
|
||||
setState(() {
|
||||
_image = null;
|
||||
_hasError = true;
|
||||
@ -113,7 +112,6 @@ class _SCNinePatchImageState extends State<SCNinePatchImage> {
|
||||
_hasError = false;
|
||||
});
|
||||
} catch (error) {
|
||||
debugPrint("[SCNinePatchImage] crop failed error=$error");
|
||||
if (!mounted || serial != _resolveSerial) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -113,7 +113,6 @@ class _SCNetworkSvgaWidgetState extends State<SCNetworkSvgaWidget>
|
||||
});
|
||||
_syncPlayback(restartIfActive: true);
|
||||
} catch (error) {
|
||||
debugPrint("[SCNetworkSVGA] load failed resource=$resource error=$error");
|
||||
if (!mounted || widget.resource.trim() != resource) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -146,7 +146,6 @@ class _SCSvgaAssetWidgetState extends State<SCSvgaAssetWidget>
|
||||
});
|
||||
_syncPlayback(restartIfActive: true);
|
||||
} catch (error) {
|
||||
debugPrint('[SCSVGA] load failed asset=$assetPath error=$error');
|
||||
if (!mounted || widget.assetPath != assetPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user