diff --git a/assets/l10n/intl_ar.json b/assets/l10n/intl_ar.json index 418a000..f272452 100644 --- a/assets/l10n/intl_ar.json +++ b/assets/l10n/intl_ar.json @@ -308,6 +308,7 @@ "ownerSendTheRedEnvelope": "أرسل مالك الغرفة عملات المكافأة.", "rewardCoins": "عملات المكافأة:{1} عملة", "signInRewardReceived": "تم تسجيل الدخول بنجاح. المكافأة: {1}", + "registerRewardReceived": "تم استلام مكافأة التسجيل: {1}", "lastWeekProgress": "تقدم الأسبوع الماضي", "currentProgress": "التقدم الحالي", "coins2": "{1} عملات", diff --git a/assets/l10n/intl_bn.json b/assets/l10n/intl_bn.json index 5e07503..fabdef6 100644 --- a/assets/l10n/intl_bn.json +++ b/assets/l10n/intl_bn.json @@ -162,6 +162,7 @@ "ownerSendTheRedEnvelope": "মালিক পুরস্কার কয়েন পাঠিয়েছেন।", "rewardCoins": "পুরস্কার কয়েন:{1} কয়েন", "signInRewardReceived": "সাইন ইন সফল হয়েছে। পুরস্কার: {1}", + "registerRewardReceived": "রেজিস্ট্রেশন পুরস্কার পাওয়া গেছে: {1}", "lastWeekProgress": "গত সপ্তাহের অগ্রগতি", "redEnvelopeTips2": "*লাল খাম সময়সীমার মধ্যে দাবি না করলে, বাকি কয়েন প্রেরক ব্যবহারকারীকে ফেরত দেওয়া হবে।", "goToRecharge": "রিচার্জ করতে যান", diff --git a/assets/l10n/intl_en.json b/assets/l10n/intl_en.json index 17d61e3..ff95a3f 100644 --- a/assets/l10n/intl_en.json +++ b/assets/l10n/intl_en.json @@ -134,6 +134,7 @@ "ownerSendTheRedEnvelope": "The owner sent reward coins.", "rewardCoins": "Reward coins:{1} coins", "signInRewardReceived": "Signed in successfully. Reward: {1}", + "registerRewardReceived": "Registration reward received: {1}", "lastWeekProgress": "Last week's progress", "redEnvelopeTips2": "*If the red envelope is not claimed within the time limit, the remaining coins will be returned to the user who sent the red envelope.", "goToRecharge": "Go to recharge", diff --git a/assets/l10n/intl_tr.json b/assets/l10n/intl_tr.json index cd27750..c456187 100644 --- a/assets/l10n/intl_tr.json +++ b/assets/l10n/intl_tr.json @@ -123,6 +123,7 @@ "ownerSendTheRedEnvelope": "Sahip ödül jettonlarını gönderdi.", "rewardCoins": "Ödül jettonları:{1} jetton", "signInRewardReceived": "Giriş başarılı. Ödül: {1}", + "registerRewardReceived": "Kayıt ödülü alındı: {1}", "lastWeekProgress": "Geçen Haftanın İlerlemesi", "redEnvelopeTips2": "*Kırmızı zarf zaman sınırı içinde talep edilmezse, kalan jettonlar gönderen kullanıcıya iade edilecektir.", "goToRecharge": "Yüklemeye Git", diff --git a/lib/app_localizations.dart b/lib/app_localizations.dart index 43c1ce5..cf569af 100644 --- a/lib/app_localizations.dart +++ b/lib/app_localizations.dart @@ -1612,6 +1612,9 @@ class SCAppLocalizations { String signInRewardReceived(String name) => translate('signInRewardReceived').replaceAll('{1}', name); + String registerRewardReceived(String name) => + translate('registerRewardReceived').replaceAll('{1}', name); + String deleteAccount2(String name) => translate('deleteAccount2').replaceAll('{1}', name); diff --git a/lib/modules/chat/system/message_system_page.dart b/lib/modules/chat/system/message_system_page.dart index eda3470..45f84f7 100644 --- a/lib/modules/chat/system/message_system_page.dart +++ b/lib/modules/chat/system/message_system_page.dart @@ -584,6 +584,13 @@ class _MessageItem extends StatelessWidget { ) { _showMsgItemMenu(ct, content); }, context); + } else if (_isRegisterRewardGrantedType(type)) { + return SCSystemMessageUtils.buildRegisterRewardGrantedMessage(data, ( + ct, + content, + ) { + _showMsgItemMenu(ct, content); + }, context); } else if (type == SCSysytemMessageType.USER_SPECIAL_AUDIT_RESULTS.name) { if (data["content"] != null) { return Builder( @@ -883,6 +890,11 @@ class _MessageItem extends StatelessWidget { ); } + bool _isRegisterRewardGrantedType(String type) { + return type.trim().toUpperCase().replaceAll(' ', '_') == + SCSysytemMessageType.REGISTER_REWARD_GRANTED.name; + } + void _showMsgItemMenu(BuildContext ct, String content) { SmartDialog.showAttach( tag: "showMsgItemMenu", diff --git a/lib/shared/data_sources/models/enum/sc_sysytem_message_type.dart b/lib/shared/data_sources/models/enum/sc_sysytem_message_type.dart index afc29fb..2d5a942 100644 --- a/lib/shared/data_sources/models/enum/sc_sysytem_message_type.dart +++ b/lib/shared/data_sources/models/enum/sc_sysytem_message_type.dart @@ -15,4 +15,5 @@ enum SCSysytemMessageType{ CP_LOVE_LETTER, USER_COINS_RECEIVED, COIN_SELLER_COINS_RECEIVED, -} \ No newline at end of file + REGISTER_REWARD_GRANTED, +} diff --git a/lib/shared/tools/sc_system_message_utils.dart b/lib/shared/tools/sc_system_message_utils.dart index ad066fe..74d24d5 100644 --- a/lib/shared/tools/sc_system_message_utils.dart +++ b/lib/shared/tools/sc_system_message_utils.dart @@ -1425,4 +1425,243 @@ class SCSystemMessageUtils { } return Container(); } + + static Widget buildRegisterRewardGrantedMessage( + data, + Function(BuildContext ct, String content) showMsgItemMenu, + BuildContext context, + ) { + final content = _registerRewardGrantedContent(data, context); + return Builder( + builder: (ct) { + return GestureDetector( + onLongPress: () { + showMsgItemMenu(ct, content); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [BoxShadow(blurRadius: 2.w, color: Colors.black26)], + borderRadius: BorderRadius.only( + topLeft: Radius.circular(0), + topRight: Radius.circular(8.w), + bottomLeft: Radius.circular(8.w), + bottomRight: Radius.circular(8), + ), + ), + padding: EdgeInsets.all(8.0.w), + child: ExtendedText( + content, + style: TextStyle(fontSize: 14.sp, color: Colors.black54), + ), + ), + ); + }, + ); + } + + static String _registerRewardGrantedContent( + dynamic data, + BuildContext context, + ) { + final l10n = SCAppLocalizations.of(context)!; + final rewards = + _extractRegisterRewardItems(data) + .map((item) => _registerRewardItemLabel(l10n, item)) + .where((item) => item.isNotEmpty) + .toList(); + if (rewards.isNotEmpty) { + return l10n.registerRewardReceived(rewards.join(', ')); + } + + final plainContent = _plainRegisterRewardContent(data); + if (plainContent.isNotEmpty) { + return l10n.registerRewardReceived(plainContent); + } + return l10n.receiveSucc; + } + + static List _extractRegisterRewardItems(dynamic value) { + final decoded = _decodeJsonValue(value); + if (decoded is List) { + return decoded; + } + if (decoded is Map) { + final nestedItems = _extractNestedRegisterRewardItems(decoded); + if (nestedItems.isNotEmpty) { + return nestedItems; + } + if (_looksLikeRewardItem(decoded)) { + return [decoded]; + } + } + return const []; + } + + static String _registerRewardItemLabel( + SCAppLocalizations l10n, + dynamic item, + ) { + final decoded = _decodeJsonValue(item); + if (decoded is! Map) { + return _readPlainText(decoded); + } + + if (!_looksLikeRewardItem(decoded)) { + final nestedItems = _extractNestedRegisterRewardItems(decoded); + if (nestedItems.isNotEmpty) { + return nestedItems + .map((item) => _registerRewardItemLabel(l10n, item)) + .where((item) => item.isNotEmpty) + .join(', '); + } + } + + final type = _readPlainText(decoded['type']).trim().toUpperCase(); + final detailType = + _readPlainText(decoded['detailType']).trim().toUpperCase(); + final quantity = _rewardQuantity(decoded); + + if (type == 'GOLD' || + type == 'COIN' || + type == 'COINS' || + detailType == 'GOLD' || + detailType == 'COIN' || + detailType == 'COINS') { + return l10n.coins2(quantity.isEmpty ? '0' : quantity); + } + + final name = _pickFirstNonEmpty([ + _readPlainText(decoded['name']), + _readPlainText(decoded['badgeName']), + _readPlainText(decoded['remark']), + _readPlainText(decoded['title']), + _readPlainText(decoded['content']), + detailType, + type, + ]); + if (name.isEmpty) { + return ''; + } + + final count = _asInt(decoded['quantity']); + if (count > 1) { + return '$name x$count'; + } + return name; + } + + static List _extractNestedRegisterRewardItems( + Map value, + ) { + const nestedKeys = [ + 'rewardItems', + 'rewards', + 'items', + 'activityRewardProps', + 'rewardConfig', + 'propsGroup', + 'propsGroups', + 'data', + 'content', + ]; + for (final key in nestedKeys) { + final items = _extractRegisterRewardItems(value[key]); + if (items.isNotEmpty) { + return items; + } + } + return const []; + } + + static String _rewardQuantity(Map item) { + final quantity = _asInt(item['quantity']); + if (quantity > 0) { + return quantity.toString(); + } + return _pickFirstNonEmpty([ + _readPlainText(item['amount']), + _readPlainText(item['content']), + ]); + } + + static String _plainRegisterRewardContent(dynamic data) { + final decoded = _decodeJsonValue(data); + if (decoded is Map) { + return _pickFirstNonEmpty([ + _readPlainText(decoded['message']), + _readPlainText(decoded['title']), + _readPlainText(decoded['content']), + ]); + } + return _readPlainText(decoded); + } + + static dynamic _decodeJsonValue(dynamic value) { + if (value is! String) { + return value; + } + final text = value.trim(); + if (!_looksLikeStructuredText(text)) { + return value; + } + try { + return jsonDecode(text); + } catch (_) { + return value; + } + } + + static bool _looksLikeRewardItem(Map value) { + const rewardKeys = [ + 'type', + 'detailType', + 'name', + 'quantity', + 'amount', + 'remark', + 'badgeName', + ]; + return rewardKeys.any(value.containsKey); + } + + static String _pickFirstNonEmpty(List values) { + for (final value in values) { + final text = value.trim(); + if (text.isNotEmpty) { + return text; + } + } + return ''; + } + + static String _readPlainText(dynamic value) { + final text = _asString(value).trim(); + if (text.isEmpty || _looksLikeStructuredText(text)) { + return ''; + } + return text; + } + + static bool _looksLikeStructuredText(String value) { + final text = value.trimLeft(); + return text.startsWith('{') || text.startsWith('['); + } + + static String _asString(dynamic value) { + if (value == null) { + return ''; + } + return value.toString(); + } + + static int _asInt(dynamic value) { + if (value is int) { + return value; + } + if (value is num) { + return value.toInt(); + } + return int.tryParse(_asString(value)) ?? 0; + } }