chore: sync local changes
This commit is contained in:
parent
526a498de6
commit
2eff091bf3
@ -2,9 +2,12 @@ import 'package:yumi/app/config/app_config.dart';
|
||||
import 'package:yumi/app/config/business_logic_strategy.dart';
|
||||
|
||||
class SCGlobalConfig {
|
||||
static const Set<String> _knownLowPerformanceModels = {"redmi 14c"};
|
||||
|
||||
static String get apiHost => AppConfig.current.apiHost;
|
||||
static String get imgHost => AppConfig.current.imgHost;
|
||||
static String get privacyAgreementUrl => AppConfig.current.privacyAgreementUrl;
|
||||
static String get privacyAgreementUrl =>
|
||||
AppConfig.current.privacyAgreementUrl;
|
||||
static String get userAgreementUrl => AppConfig.current.userAgreementUrl;
|
||||
|
||||
// 以下URL从AppConfig获取
|
||||
@ -18,8 +21,10 @@ class SCGlobalConfig {
|
||||
static String get gamesKingUrl => AppConfig.current.gamesKingUrl;
|
||||
|
||||
// 应用下载链接需要根据Flavor调整
|
||||
static String get appDownloadUrlGoogle => AppConfig.current.appDownloadUrlGoogle;
|
||||
static String get appDownloadUrlApple => AppConfig.current.appDownloadUrlApple;
|
||||
static String get appDownloadUrlGoogle =>
|
||||
AppConfig.current.appDownloadUrlGoogle;
|
||||
static String get appDownloadUrlApple =>
|
||||
AppConfig.current.appDownloadUrlApple;
|
||||
|
||||
///语言
|
||||
static String lang = "en";
|
||||
@ -33,6 +38,9 @@ class SCGlobalConfig {
|
||||
static String model = "SM-G9550";
|
||||
static String sysVersion = "9";
|
||||
static int sdkInt = 28;
|
||||
static int processorCount = 0;
|
||||
static bool isLowRamDevice = false;
|
||||
static bool _isLowPerformanceDevice = false;
|
||||
|
||||
///高于这个值才播放特效,避免低性能手机卡顿
|
||||
static int maxSdkNoAnim = 27;
|
||||
@ -77,7 +85,8 @@ class SCGlobalConfig {
|
||||
};
|
||||
}
|
||||
|
||||
static String get primarySystemUserId => _normalizeConversationUserId(imAdmin);
|
||||
static String get primarySystemUserId =>
|
||||
_normalizeConversationUserId(imAdmin);
|
||||
static String get primarySystemConversationId => "c2c_$primarySystemUserId";
|
||||
|
||||
static bool isSystemConversationId(String? conversationId) {
|
||||
@ -119,17 +128,60 @@ class SCGlobalConfig {
|
||||
///入场秀
|
||||
static bool _isEntryVehicleAnimation = true;
|
||||
static bool get isEntryVehicleAnimation => _isEntryVehicleAnimation;
|
||||
static set isEntryVehicleAnimation(bool value) => _isEntryVehicleAnimation = value;
|
||||
static set isEntryVehicleAnimation(bool value) =>
|
||||
_isEntryVehicleAnimation = value;
|
||||
|
||||
///全局飘屏
|
||||
static bool _isFloatingAnimationInGlobal = true;
|
||||
static bool get isFloatingAnimationInGlobal => _isFloatingAnimationInGlobal;
|
||||
static set isFloatingAnimationInGlobal(bool value) => _isFloatingAnimationInGlobal = value;
|
||||
static set isFloatingAnimationInGlobal(bool value) =>
|
||||
_isFloatingAnimationInGlobal = value;
|
||||
|
||||
///幸运礼物特效开关
|
||||
static bool _isLuckGiftSpecialEffects = true;
|
||||
static bool get isLuckGiftSpecialEffects => _isLuckGiftSpecialEffects;
|
||||
static set isLuckGiftSpecialEffects(bool value) => _isLuckGiftSpecialEffects = value;
|
||||
static set isLuckGiftSpecialEffects(bool value) =>
|
||||
_isLuckGiftSpecialEffects = value;
|
||||
|
||||
static bool get isLowPerformanceDevice => _isLowPerformanceDevice;
|
||||
|
||||
static bool get allowsHighCostAnimations =>
|
||||
!_isLowPerformanceDevice && sdkInt > maxSdkNoAnim;
|
||||
|
||||
static int get recommendedImageCacheBytes =>
|
||||
_isLowPerformanceDevice ? 40 * 1024 * 1024 : 100 * 1024 * 1024;
|
||||
|
||||
static int get recommendedImageCacheEntries =>
|
||||
_isLowPerformanceDevice ? 80 : 200;
|
||||
|
||||
static void applyDevicePerformanceProfile({
|
||||
required bool isLowRamDevice,
|
||||
required int processorCount,
|
||||
}) {
|
||||
final normalizedModel = model.toLowerCase().replaceAll('-', ' ');
|
||||
final matchesKnownLowPerformanceModel = _knownLowPerformanceModels.any(
|
||||
normalizedModel.contains,
|
||||
);
|
||||
SCGlobalConfig.isLowRamDevice = isLowRamDevice;
|
||||
SCGlobalConfig.processorCount = processorCount;
|
||||
_isLowPerformanceDevice =
|
||||
isLowRamDevice ||
|
||||
processorCount <= 6 ||
|
||||
matchesKnownLowPerformanceModel;
|
||||
resetVisualEffectSwitchesToRecommendedDefaults();
|
||||
}
|
||||
|
||||
static bool clampVisualEffectPreference(bool enabled) {
|
||||
return !_isLowPerformanceDevice && enabled;
|
||||
}
|
||||
|
||||
static void resetVisualEffectSwitchesToRecommendedDefaults() {
|
||||
final enabled = !_isLowPerformanceDevice;
|
||||
isEntryVehicleAnimation = enabled;
|
||||
isGiftSpecialEffects = enabled;
|
||||
isFloatingAnimationInGlobal = enabled;
|
||||
isLuckGiftSpecialEffects = enabled;
|
||||
}
|
||||
|
||||
/// 获取当前业务逻辑策略
|
||||
static BusinessLogicStrategy get businessLogicStrategy {
|
||||
|
||||
@ -92,6 +92,14 @@ Future<void> _prepareAppShell() async {
|
||||
SCKeybordUtil.init();
|
||||
// 使用重试机制初始化存储
|
||||
await _initStore();
|
||||
await SCDeviceIdUtils.initDeviceinfo();
|
||||
_configureImageCache();
|
||||
}
|
||||
|
||||
void _configureImageCache() {
|
||||
final imageCache = PaintingBinding.instance.imageCache;
|
||||
imageCache.maximumSizeBytes = SCGlobalConfig.recommendedImageCacheBytes;
|
||||
imageCache.maximumSize = SCGlobalConfig.recommendedImageCacheEntries;
|
||||
}
|
||||
|
||||
void _installErrorHandlers() {
|
||||
@ -286,7 +294,6 @@ class _YumiApplicationState extends State<YumiApplication> {
|
||||
// 将非首帧必需的初始化统一延后到首帧后
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_initRouter();
|
||||
SCDeviceIdUtils.initDeviceinfo();
|
||||
unawaited(_initLink());
|
||||
});
|
||||
}
|
||||
@ -344,9 +351,9 @@ class _YumiApplicationState extends State<YumiApplication> {
|
||||
style: TextStyle(fontSize: 12.sp, color: Color(0xff999999)),
|
||||
);
|
||||
}
|
||||
return Container(
|
||||
return SizedBox(
|
||||
height: kTextTabBarHeight + ScreenUtil().statusBarHeight,
|
||||
child: Center(child: body),
|
||||
child: SizedBox.expand(child: Center(child: body)),
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -399,6 +406,7 @@ class _YumiApplicationState extends State<YumiApplication> {
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
child ?? const SizedBox.shrink(),
|
||||
if (SCGlobalConfig.allowsHighCostAnimations)
|
||||
const Positioned.fill(
|
||||
child: VapPlusSvgaPlayer(tag: "room_gift"),
|
||||
),
|
||||
|
||||
@ -15,6 +15,7 @@ import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/app/config/business_logic_strategy.dart';
|
||||
import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/api.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_room_repository_imp.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
||||
import 'package:yumi/main.dart';
|
||||
@ -101,6 +102,74 @@ class _GiftPageState extends State<GiftPage>
|
||||
debugPrint('[GiftFX][Send] $message');
|
||||
}
|
||||
|
||||
String _describeGiftSendError(Object error) {
|
||||
if (error is DioException) {
|
||||
final requestPath = error.requestOptions.path;
|
||||
final statusCode = error.response?.statusCode;
|
||||
final responseData = error.response?.data;
|
||||
return 'dioType=${error.type} '
|
||||
'statusCode=$statusCode '
|
||||
'path=$requestPath '
|
||||
'message=${error.message} '
|
||||
'error=${error.error} '
|
||||
'response=$responseData';
|
||||
}
|
||||
|
||||
if (error is NotSuccessException) {
|
||||
return 'notSuccess message=${error.message}';
|
||||
}
|
||||
|
||||
return 'type=${error.runtimeType} error=$error';
|
||||
}
|
||||
|
||||
void _showLocalLuckyGiftFeedback(
|
||||
List<MicRes> acceptUsers, {
|
||||
required SocialChatGiftRes gift,
|
||||
required int quantity,
|
||||
}) {
|
||||
final rtmProvider = Provider.of<RtmProvider>(
|
||||
navigatorKey.currentState!.context,
|
||||
listen: false,
|
||||
);
|
||||
final currentUser = AccountStorage().getCurrentUser()?.userProfile;
|
||||
if (currentUser == null) {
|
||||
_giftFxLog(
|
||||
'local lucky feedback skipped reason=no_current_user giftId=${gift.id}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
for (final acceptUser in acceptUsers) {
|
||||
final targetUser = acceptUser.user;
|
||||
if (targetUser == null) {
|
||||
_giftFxLog(
|
||||
'local lucky feedback skipped reason=no_target_user giftId=${gift.id}',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
_giftFxLog(
|
||||
'local lucky feedback trigger '
|
||||
'giftId=${gift.id} '
|
||||
'giftName=${gift.giftName} '
|
||||
'toUserId=${targetUser.id} '
|
||||
'toUserName=${targetUser.userNickname} '
|
||||
'quantity=$quantity',
|
||||
);
|
||||
rtmProvider.msgFloatingGiftListener?.call(
|
||||
Msg(
|
||||
groupId:
|
||||
rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount,
|
||||
msg: rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "",
|
||||
type: SCRoomMsgType.luckGiftAnimOther,
|
||||
gift: gift,
|
||||
user: currentUser,
|
||||
toUser: targetUser,
|
||||
number: quantity,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _applyGiftSelection(SocialChatGiftRes? gift, {bool notify = true}) {
|
||||
checkedGift = gift;
|
||||
if (gift != null &&
|
||||
@ -331,6 +400,80 @@ class _GiftPageState extends State<GiftPage>
|
||||
}
|
||||
}
|
||||
|
||||
bool _usesLuckyGiftEndpoint(SocialChatGiftRes? gift) {
|
||||
final giftTab = (gift?.giftTab ?? '').trim();
|
||||
return giftTab == "LUCK" ||
|
||||
giftTab == SCGiftType.LUCKY_GIFT.name ||
|
||||
giftTab == SCGiftType.MAGIC.name;
|
||||
}
|
||||
|
||||
bool _hasValidLuckyGiftStandardId(SocialChatGiftRes gift) {
|
||||
final standardId = (gift.standardId ?? '').trim();
|
||||
return standardId.isNotEmpty && standardId != '0';
|
||||
}
|
||||
|
||||
String _resolveGiftSendErrorMessage(Object error) {
|
||||
String sanitize(String message) {
|
||||
var value = message.trim();
|
||||
const prefixes = <String>[
|
||||
'Exception: ',
|
||||
'DioException: ',
|
||||
'DioException [unknown]: ',
|
||||
];
|
||||
for (final prefix in prefixes) {
|
||||
if (value.startsWith(prefix)) {
|
||||
value = value.substring(prefix.length).trim();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
if (error is DioException) {
|
||||
final responseData = error.response?.data;
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
final responseMessage = sanitize(
|
||||
responseData['errorMsg']?.toString() ?? '',
|
||||
);
|
||||
if (responseMessage.isNotEmpty) {
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (error.error is NotSuccessException) {
|
||||
final responseMessage = sanitize(
|
||||
(error.error as NotSuccessException).message,
|
||||
);
|
||||
if (responseMessage.isNotEmpty) {
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
final dioMessage = sanitize(error.message ?? '');
|
||||
if (dioMessage.isNotEmpty) {
|
||||
return dioMessage;
|
||||
}
|
||||
|
||||
final nestedMessage = sanitize(error.error?.toString() ?? '');
|
||||
if (nestedMessage.isNotEmpty) {
|
||||
return nestedMessage;
|
||||
}
|
||||
}
|
||||
|
||||
if (error is NotSuccessException) {
|
||||
final responseMessage = sanitize(error.message);
|
||||
if (responseMessage.isNotEmpty) {
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
final fallbackMessage = sanitize(error.toString());
|
||||
if (fallbackMessage.isNotEmpty) {
|
||||
return fallbackMessage;
|
||||
}
|
||||
|
||||
return 'Gift sending failed, please try again.';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<SCAppGeneralManager>(
|
||||
@ -926,7 +1069,7 @@ class _GiftPageState extends State<GiftPage>
|
||||
}
|
||||
|
||||
///赠送礼物
|
||||
void giveGifts() {
|
||||
void giveGifts() async {
|
||||
List<String> acceptUserIds = [];
|
||||
List<MicRes> acceptUsers = [];
|
||||
|
||||
@ -951,60 +1094,164 @@ class _GiftPageState extends State<GiftPage>
|
||||
}
|
||||
}
|
||||
if (acceptUserIds.isEmpty) {
|
||||
_giftFxLog(
|
||||
'tap send aborted reason=no_accept_users '
|
||||
'giftId=${checkedGift?.id} '
|
||||
'giftName=${checkedGift?.giftName} '
|
||||
'giftTab=${checkedGift?.giftTab} '
|
||||
'giveType=$giveType',
|
||||
);
|
||||
SCTts.show(SCAppLocalizations.of(context)!.pleaseSelectTheRecipient);
|
||||
return;
|
||||
}
|
||||
if (checkedGift == null) {
|
||||
final selectedGift = checkedGift;
|
||||
if (selectedGift == null) {
|
||||
_giftFxLog(
|
||||
'tap send aborted reason=no_selected_gift '
|
||||
'acceptUserIds=${acceptUserIds.join(",")} '
|
||||
'giveType=$giveType',
|
||||
);
|
||||
return;
|
||||
}
|
||||
SCChatRoomRepository()
|
||||
.giveGift(
|
||||
acceptUserIds,
|
||||
checkedGift!.id ?? "",
|
||||
number,
|
||||
false,
|
||||
roomId: rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "",
|
||||
)
|
||||
.then((result) {
|
||||
final selectedNumber = number;
|
||||
final roomId = rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "";
|
||||
final roomAccount =
|
||||
rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "";
|
||||
final isLuckyGiftRequest = _usesLuckyGiftEndpoint(selectedGift);
|
||||
final requestName = isLuckyGiftRequest ? 'giveLuckyGift' : 'giveGift';
|
||||
final senderId = AccountStorage().getCurrentUser()?.userProfile?.id ?? "";
|
||||
final senderName =
|
||||
AccountStorage().getCurrentUser()?.userProfile?.userNickname ?? "";
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
_giftFxLog(
|
||||
'giveGift success giftId=${checkedGift?.id} '
|
||||
'giftName=${checkedGift?.giftName} '
|
||||
'giftSourceUrl=${checkedGift?.giftSourceUrl} '
|
||||
'special=${checkedGift?.special} '
|
||||
'giftTab=${checkedGift?.giftTab} '
|
||||
'number=$number '
|
||||
'tap send start request=$requestName '
|
||||
'senderId=$senderId '
|
||||
'senderName=$senderName '
|
||||
'giftId=${selectedGift.id} '
|
||||
'giftName=${selectedGift.giftName} '
|
||||
'giftTab=${selectedGift.giftTab} '
|
||||
'special=${selectedGift.special} '
|
||||
'standardId=${selectedGift.standardId} '
|
||||
'giftCandy=${selectedGift.giftCandy} '
|
||||
'number=$selectedNumber '
|
||||
'acceptCount=${acceptUserIds.length} '
|
||||
'acceptUserIds=${acceptUserIds.join(",")} '
|
||||
'roomId=${rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id}',
|
||||
'roomId=$roomId '
|
||||
'roomAccount=$roomAccount '
|
||||
'giveType=$giveType '
|
||||
'giftType=$giftType',
|
||||
);
|
||||
|
||||
if (isLuckyGiftRequest && !_hasValidLuckyGiftStandardId(selectedGift)) {
|
||||
const configError =
|
||||
'Gift configuration unavailable, please try another gift.';
|
||||
_giftFxLog(
|
||||
'$requestName skipped giftId=${selectedGift.id} '
|
||||
'giftName=${selectedGift.giftName} '
|
||||
'giftTab=${selectedGift.giftTab} '
|
||||
'standardId=${selectedGift.standardId} '
|
||||
'reason=invalid_standard_id',
|
||||
);
|
||||
SCTts.show(configError);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final repository = SCChatRoomRepository();
|
||||
_giftFxLog(
|
||||
'calling repository.$requestName '
|
||||
'giftId=${selectedGift.id} '
|
||||
'roomId=$roomId '
|
||||
'acceptUserIds=${acceptUserIds.join(",")} '
|
||||
'quantity=$selectedNumber',
|
||||
);
|
||||
final result =
|
||||
isLuckyGiftRequest
|
||||
? await repository.giveLuckyGift(
|
||||
acceptUserIds,
|
||||
selectedGift.id ?? "",
|
||||
selectedNumber,
|
||||
false,
|
||||
roomId: roomId,
|
||||
)
|
||||
: await repository.giveGift(
|
||||
acceptUserIds,
|
||||
selectedGift.id ?? "",
|
||||
selectedNumber,
|
||||
false,
|
||||
roomId: roomId,
|
||||
);
|
||||
_giftFxLog(
|
||||
'$requestName success giftId=${selectedGift.id} '
|
||||
'giftName=${selectedGift.giftName} '
|
||||
'giftSourceUrl=${selectedGift.giftSourceUrl} '
|
||||
'special=${selectedGift.special} '
|
||||
'giftTab=${selectedGift.giftTab} '
|
||||
'standardId=${selectedGift.standardId} '
|
||||
'number=$selectedNumber '
|
||||
'acceptUserIds=${acceptUserIds.join(",")} '
|
||||
'roomId=$roomId '
|
||||
'balance=$result '
|
||||
'elapsedMs=${stopwatch.elapsedMilliseconds}',
|
||||
);
|
||||
// SCTts.show(SCAppLocalizations.of(context)!.giftGivingSuccessful);
|
||||
sendGiftMsg(acceptUsers);
|
||||
if (isLuckyGiftRequest) {
|
||||
_showLocalLuckyGiftFeedback(
|
||||
acceptUsers,
|
||||
gift: selectedGift,
|
||||
quantity: selectedNumber,
|
||||
);
|
||||
await sendLuckGiftAnimOtherMsg(
|
||||
acceptUsers,
|
||||
gift: selectedGift,
|
||||
quantity: selectedNumber,
|
||||
);
|
||||
} else {
|
||||
sendGiftMsg(acceptUsers, gift: selectedGift, quantity: selectedNumber);
|
||||
}
|
||||
if (mounted) {
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).updateBalance(result);
|
||||
})
|
||||
.catchError((e) {
|
||||
}
|
||||
} catch (e) {
|
||||
final errorMessage = _resolveGiftSendErrorMessage(e);
|
||||
final errorDetails = _describeGiftSendError(e);
|
||||
_giftFxLog(
|
||||
'giveGift failed giftId=${checkedGift?.id} '
|
||||
'giftName=${checkedGift?.giftName} '
|
||||
'error=$e',
|
||||
'$requestName failed giftId=${selectedGift.id} '
|
||||
'giftName=${selectedGift.giftName} '
|
||||
'giftTab=${selectedGift.giftTab} '
|
||||
'standardId=${selectedGift.standardId} '
|
||||
'error=$e '
|
||||
'resolvedError=$errorMessage '
|
||||
'details={$errorDetails} '
|
||||
'elapsedMs=${stopwatch.elapsedMilliseconds}',
|
||||
);
|
||||
});
|
||||
if (mounted) {
|
||||
SCTts.show(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendGiftMsg(List<MicRes> acceptUsers) {
|
||||
void sendGiftMsg(
|
||||
List<MicRes> acceptUsers, {
|
||||
required SocialChatGiftRes gift,
|
||||
required int quantity,
|
||||
}) {
|
||||
///发送一条IM消息
|
||||
for (var u in acceptUsers) {
|
||||
final special = checkedGift?.special ?? "";
|
||||
final giftSourceUrl = checkedGift?.giftSourceUrl ?? "";
|
||||
final special = gift.special ?? "";
|
||||
final giftSourceUrl = gift.giftSourceUrl ?? "";
|
||||
final hasSource = giftSourceUrl.isNotEmpty;
|
||||
final hasAnimation = scGiftHasAnimationSpecial(special);
|
||||
final hasGlobalGift = special.contains(SCGiftType.GLOBAL_GIFT.name);
|
||||
final hasFullScreenEffect = scGiftHasFullScreenEffect(special);
|
||||
_giftFxLog(
|
||||
'dispatch gift msg '
|
||||
'giftId=${checkedGift?.id} '
|
||||
'giftName=${checkedGift?.giftName} '
|
||||
'giftId=${gift.id} '
|
||||
'giftName=${gift.giftName} '
|
||||
'toUserId=${u.user?.id} '
|
||||
'toUserName=${u.user?.userNickname} '
|
||||
'giftSourceUrl=$giftSourceUrl '
|
||||
@ -1022,10 +1269,10 @@ class _GiftPageState extends State<GiftPage>
|
||||
Msg(
|
||||
groupId:
|
||||
rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount,
|
||||
gift: checkedGift,
|
||||
gift: gift,
|
||||
user: AccountStorage().getCurrentUser()?.userProfile,
|
||||
toUser: u.user,
|
||||
number: number,
|
||||
number: quantity,
|
||||
type: SCRoomMsgType.gift,
|
||||
role:
|
||||
Provider.of<RtcProvider>(
|
||||
@ -1049,7 +1296,7 @@ class _GiftPageState extends State<GiftPage>
|
||||
},
|
||||
);
|
||||
}
|
||||
num coins = checkedGift!.giftCandy! * number;
|
||||
num coins = (gift.giftCandy ?? 0) * quantity;
|
||||
if (coins > 9999) {
|
||||
var fMsg = SCFloatingMessage(
|
||||
type: 1,
|
||||
@ -1059,42 +1306,42 @@ class _GiftPageState extends State<GiftPage>
|
||||
AccountStorage().getCurrentUser()?.userProfile?.userNickname ??
|
||||
"",
|
||||
toUserName: u.user?.userNickname ?? "",
|
||||
giftUrl: checkedGift?.giftPhoto ?? "",
|
||||
giftUrl: gift.giftPhoto ?? "",
|
||||
roomId: rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "",
|
||||
coins: coins,
|
||||
number: number,
|
||||
number: quantity,
|
||||
);
|
||||
OverlayManager().addMessage(fMsg);
|
||||
}
|
||||
if (checkedGift!.giftSourceUrl != null && checkedGift!.special != null) {
|
||||
if (scGiftHasFullScreenEffect(checkedGift!.special)) {
|
||||
if (gift.giftSourceUrl != null && gift.special != null) {
|
||||
if (scGiftHasFullScreenEffect(gift.special)) {
|
||||
if (SCGlobalConfig.isGiftSpecialEffects) {
|
||||
_giftFxLog(
|
||||
'local trigger player play '
|
||||
'path=${checkedGift!.giftSourceUrl} '
|
||||
'giftId=${checkedGift?.id} '
|
||||
'giftName=${checkedGift?.giftName}',
|
||||
'path=${gift.giftSourceUrl} '
|
||||
'giftId=${gift.id} '
|
||||
'giftName=${gift.giftName}',
|
||||
);
|
||||
SCGiftVapSvgaManager().play(checkedGift!.giftSourceUrl!);
|
||||
SCGiftVapSvgaManager().play(gift.giftSourceUrl!);
|
||||
} else {
|
||||
_giftFxLog(
|
||||
'skip local play because isGiftSpecialEffects=false '
|
||||
'giftId=${checkedGift?.id}',
|
||||
'giftId=${gift.id}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_giftFxLog(
|
||||
'skip local play because special does not include '
|
||||
'${SCGiftType.ANIMSCION.name}/$kSCGiftAnimationSpecialAlias/${SCGiftType.GLOBAL_GIFT.name} '
|
||||
'giftId=${checkedGift?.id} special=${checkedGift?.special}',
|
||||
'giftId=${gift.id} special=${gift.special}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_giftFxLog(
|
||||
'skip local play because giftSourceUrl or special is null '
|
||||
'giftId=${checkedGift?.id} '
|
||||
'giftSourceUrl=${checkedGift?.giftSourceUrl} '
|
||||
'special=${checkedGift?.special}',
|
||||
'giftId=${gift.id} '
|
||||
'giftSourceUrl=${gift.giftSourceUrl} '
|
||||
'special=${gift.special}',
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1152,18 +1399,48 @@ class _GiftPageState extends State<GiftPage>
|
||||
}
|
||||
|
||||
///发送一条消息,幸运礼物,房间里所有人都能看到礼物飘向麦位的动画
|
||||
void sendLuckGiftAnimOtherMsg(List<MicRes> acceptUsers) {
|
||||
Provider.of<RtmProvider>(
|
||||
Future<void> sendLuckGiftAnimOtherMsg(
|
||||
List<MicRes> acceptUsers, {
|
||||
required SocialChatGiftRes gift,
|
||||
required int quantity,
|
||||
}) async {
|
||||
final targetUserIds =
|
||||
acceptUsers
|
||||
.map((u) => u.user?.id ?? "")
|
||||
.where((id) => id.isNotEmpty)
|
||||
.toList();
|
||||
final firstTargetUser =
|
||||
acceptUsers.isNotEmpty ? acceptUsers.first.user : null;
|
||||
_giftFxLog(
|
||||
'dispatch lucky anim msg '
|
||||
'giftId=${gift.id} '
|
||||
'giftName=${gift.giftName} '
|
||||
'giftPhoto=${gift.giftPhoto} '
|
||||
'quantity=$quantity '
|
||||
'firstTargetUserId=${firstTargetUser?.id} '
|
||||
'groupId=${rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount} '
|
||||
'roomId=${rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id} '
|
||||
'targetUserIds=${targetUserIds.join(",")}',
|
||||
);
|
||||
await Provider.of<RtmProvider>(
|
||||
navigatorKey.currentState!.context,
|
||||
listen: false,
|
||||
).dispatchMessage(
|
||||
Msg(
|
||||
groupId: rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount,
|
||||
gift: checkedGift,
|
||||
gift: gift,
|
||||
user: AccountStorage().getCurrentUser()?.userProfile,
|
||||
toUser: firstTargetUser,
|
||||
number: quantity,
|
||||
type: SCRoomMsgType.luckGiftAnimOther,
|
||||
msg: jsonEncode(acceptUsers.map((u) => u.user?.id).toList()),
|
||||
),
|
||||
addLocal: false,
|
||||
addLocal: true,
|
||||
);
|
||||
_giftFxLog(
|
||||
'dispatch lucky anim msg finished '
|
||||
'giftId=${gift.id} '
|
||||
'targetUserIds=${targetUserIds.join(",")}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import 'package:yumi/ui_kit/widgets/room/room_head_widget.dart';
|
||||
import 'package:yumi/ui_kit/widgets/room/room_msg_item.dart';
|
||||
import 'package:yumi/ui_kit/widgets/room/room_online_user_widget.dart';
|
||||
import 'package:yumi/ui_kit/widgets/room/room_play_widget.dart';
|
||||
import 'package:yumi/shared/data_sources/models/enum/sc_gift_type.dart';
|
||||
|
||||
import '../../ui_kit/components/sc_float_ichart.dart';
|
||||
import '../../ui_kit/widgets/room/seat/room_seat_widget.dart';
|
||||
@ -32,7 +33,7 @@ class VoiceRoomPage extends StatefulWidget {
|
||||
const VoiceRoomPage({super.key});
|
||||
|
||||
@override
|
||||
_VoiceRoomPageState createState() => _VoiceRoomPageState();
|
||||
State<VoiceRoomPage> createState() => _VoiceRoomPageState();
|
||||
}
|
||||
|
||||
class _VoiceRoomPageState extends State<VoiceRoomPage>
|
||||
@ -258,12 +259,15 @@ class _VoiceRoomPageState extends State<VoiceRoomPage>
|
||||
return;
|
||||
}
|
||||
var giftModel = LGiftModel();
|
||||
final giftTab = (msg.gift?.giftTab ?? '').trim();
|
||||
giftModel.labelId = "${msg.gift?.id}${msg.user?.id}${msg.toUser?.id}";
|
||||
giftModel.sendUserName = msg.user?.userNickname ?? "";
|
||||
giftModel.sendToUserName = msg.toUser?.userNickname ?? "";
|
||||
giftModel.sendUserPic = msg.user?.userAvatar ?? "";
|
||||
giftModel.giftPic = msg.gift?.giftPhoto ?? "";
|
||||
giftModel.giftCount = msg.number ?? 0;
|
||||
giftModel.isLuckyGift =
|
||||
giftTab == "LUCK" || giftTab == SCGiftType.LUCKY_GIFT.name;
|
||||
Provider.of<GiftAnimationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
|
||||
@ -430,7 +430,7 @@ class _BaishunGamePageState extends State<BaishunGamePage> {
|
||||
),
|
||||
child: Container(
|
||||
width: ScreenUtil().screenWidth,
|
||||
height: ScreenUtil().screenHeight * 0.56,
|
||||
height: ScreenUtil().screenHeight * 0.75,
|
||||
color: const Color(0xFF081915),
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
@ -635,10 +635,7 @@ class RealTimeCommunicationManager extends ChangeNotifier {
|
||||
DataPersistence.setLastTimeRoomId("");
|
||||
SCGiftVapSvgaManager().stopPlayback();
|
||||
SCRoomUtils.closeAllDialogs();
|
||||
SCGlobalConfig.isEntryVehicleAnimation = true;
|
||||
SCGlobalConfig.isGiftSpecialEffects = true;
|
||||
SCGlobalConfig.isFloatingAnimationInGlobal = true;
|
||||
SCGlobalConfig.isLuckGiftSpecialEffects = true;
|
||||
SCGlobalConfig.resetVisualEffectSwitchesToRecommendedDefaults();
|
||||
}
|
||||
|
||||
void toggleRemoteAudioMuteForAllUsers() {
|
||||
|
||||
@ -784,6 +784,16 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
// 发送消息(房间)
|
||||
Future<void> _sendRoomMessage(Msg msg) async {
|
||||
try {
|
||||
if (msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
_giftFxLog(
|
||||
'send room msg start '
|
||||
'type=${msg.type} '
|
||||
'groupId=${msg.groupId} '
|
||||
'msg=${msg.msg} '
|
||||
'giftId=${msg.gift?.id} '
|
||||
'giftPhoto=${msg.gift?.giftPhoto}',
|
||||
);
|
||||
}
|
||||
if (msg.type == SCRoomMsgType.roomSettingUpdate) {
|
||||
debugPrint(
|
||||
"[Room Cover Sync] send roomSettingUpdate groupId=${msg.groupId ?? ""} roomId=${msg.msg ?? ""}",
|
||||
@ -809,6 +819,16 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
.getMessageManager()
|
||||
.createCustomMessage(data: jsonEncode(msg.toJson()));
|
||||
|
||||
if (msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
_giftFxLog(
|
||||
'send room msg createCustomMessage '
|
||||
'type=${msg.type} '
|
||||
'code=${textMsg.code} '
|
||||
'id=${textMsg.data?.id} '
|
||||
'desc=${textMsg.desc}',
|
||||
);
|
||||
}
|
||||
|
||||
if (textMsg.code != 0) return;
|
||||
|
||||
final sendResult = await TencentImSDKPlugin.v2TIMManager
|
||||
@ -818,6 +838,16 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
groupID: msg.groupId!,
|
||||
receiver: '',
|
||||
);
|
||||
if (msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
_giftFxLog(
|
||||
'send room msg result '
|
||||
'type=${msg.type} '
|
||||
'code=${sendResult.code} '
|
||||
'msgId=${sendResult.data?.msgID} '
|
||||
'groupId=${sendResult.data?.groupID} '
|
||||
'desc=${sendResult.desc}',
|
||||
);
|
||||
}
|
||||
if (sendResult.code == 0) {}
|
||||
} catch (e) {
|
||||
throw Exception("create fail: $e");
|
||||
@ -847,16 +877,19 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
roomChatMsgList.removeAt(roomChatMsgList.length - 1);
|
||||
}
|
||||
msgChatListener?.call(msg);
|
||||
} else if (msg.type == SCRoomMsgType.gift) {
|
||||
} else if (msg.type == SCRoomMsgType.gift ||
|
||||
msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
roomGiftMsgList.insert(0, msg);
|
||||
if (roomGiftMsgList.length > 250) {
|
||||
print('大于200条消息');
|
||||
roomGiftMsgList.removeAt(roomGiftMsgList.length - 1);
|
||||
}
|
||||
msgGiftListener?.call(msg);
|
||||
if (msg.type == SCRoomMsgType.gift) {
|
||||
msgFloatingGiftListener?.call(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isLogout = false;
|
||||
|
||||
@ -1119,6 +1152,17 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
).fetchOnlineUsersList();
|
||||
} else if (msg.type == SCRoomMsgType.gameLuckyGift) {
|
||||
var broadCastRes = SCBroadCastLuckGiftPush.fromJson(data);
|
||||
_giftFxLog(
|
||||
'recv GAME_LUCKY_GIFT '
|
||||
'giftId=${broadCastRes.data?.giftId} '
|
||||
'roomId=${broadCastRes.data?.roomId} '
|
||||
'sendUserId=${broadCastRes.data?.sendUserId} '
|
||||
'acceptUserId=${broadCastRes.data?.acceptUserId} '
|
||||
'giftQuantity=${broadCastRes.data?.giftQuantity} '
|
||||
'awardAmount=${broadCastRes.data?.awardAmount} '
|
||||
'multiple=${broadCastRes.data?.multiple} '
|
||||
'multipleType=${broadCastRes.data?.multipleType}',
|
||||
);
|
||||
msg.gift = SocialChatGiftRes(giftPhoto: broadCastRes.data?.giftCover);
|
||||
msg.awardAmount = broadCastRes.data?.awardAmount;
|
||||
msg.user = SocialChatUserProfile(
|
||||
@ -1279,21 +1323,56 @@ class RealTimeMessagingManager extends ChangeNotifier {
|
||||
);
|
||||
}
|
||||
} else if (msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
if (Provider.of<GiftProvider>(
|
||||
final hideLGiftAnimal =
|
||||
Provider.of<GiftProvider>(
|
||||
context!,
|
||||
listen: false,
|
||||
).hideLGiftAnimal) {
|
||||
return;
|
||||
}
|
||||
).hideLGiftAnimal;
|
||||
if (hideLGiftAnimal) {
|
||||
_giftFxLog(
|
||||
'recv LUCK_GIFT_ANIM_OTHER skipped '
|
||||
'reason=hideLGiftAnimal '
|
||||
'giftPhoto=${msg.gift?.giftPhoto}',
|
||||
);
|
||||
} else {
|
||||
final targetUserIds =
|
||||
(jsonDecode(msg.msg ?? "") as List)
|
||||
.map((e) => e as String)
|
||||
.toList();
|
||||
_giftFxLog(
|
||||
'recv LUCK_GIFT_ANIM_OTHER '
|
||||
'giftPhoto=${msg.gift?.giftPhoto} '
|
||||
'sendUserId=${msg.user?.id} '
|
||||
'toUserId=${msg.toUser?.id} '
|
||||
'quantity=${msg.number} '
|
||||
'targetUserIds=${targetUserIds.join(",")}',
|
||||
);
|
||||
eventBus.fire(
|
||||
GiveRoomLuckWithOtherEvent(
|
||||
msg.gift?.giftPhoto ?? "",
|
||||
(jsonDecode(msg.msg ?? "") as List)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
targetUserIds,
|
||||
),
|
||||
);
|
||||
return;
|
||||
if (msg.user != null && msg.toUser != null && msg.gift != null) {
|
||||
_giftFxLog(
|
||||
'trigger floating gift listener from LUCK_GIFT_ANIM_OTHER '
|
||||
'sendUserId=${msg.user?.id} '
|
||||
'toUserId=${msg.toUser?.id} '
|
||||
'quantity=${msg.number} '
|
||||
'giftId=${msg.gift?.id}',
|
||||
);
|
||||
msgFloatingGiftListener?.call(msg);
|
||||
} else {
|
||||
_giftFxLog(
|
||||
'skip floating gift listener from LUCK_GIFT_ANIM_OTHER '
|
||||
'reason=incomplete_msg '
|
||||
'sendUserId=${msg.user?.id} '
|
||||
'toUserId=${msg.toUser?.id} '
|
||||
'giftId=${msg.gift?.id} '
|
||||
'quantity=${msg.number}',
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (msg.type == SCRoomMsgType.roomRoleChange) {
|
||||
///房间身份变动
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/tools/sc_message_utils.dart';
|
||||
import 'package:yumi/shared/tools/sc_room_utils.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
|
||||
import 'package:yumi/main.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
||||
@ -61,9 +59,7 @@ class AccountStorage {
|
||||
if (value.propsResources?.type == SCPropsType.AVATAR_FRAME.name) {
|
||||
///判断有没有过期
|
||||
if (int.parse(value.expireTime ?? "0") >
|
||||
DateTime
|
||||
.now()
|
||||
.millisecondsSinceEpoch) {
|
||||
DateTime.now().millisecondsSinceEpoch) {
|
||||
pr = value.propsResources;
|
||||
}
|
||||
}
|
||||
@ -78,9 +74,7 @@ class AccountStorage {
|
||||
if (value.propsResources?.type == SCPropsType.CHAT_BUBBLE.name) {
|
||||
///判断有没有过期
|
||||
if (int.parse(value.expireTime ?? "0") >
|
||||
DateTime
|
||||
.now()
|
||||
.millisecondsSinceEpoch) {
|
||||
DateTime.now().millisecondsSinceEpoch) {
|
||||
pr = value.propsResources;
|
||||
}
|
||||
}
|
||||
@ -95,9 +89,7 @@ class AccountStorage {
|
||||
if (value.propsResources?.type == SCPropsType.RIDE.name) {
|
||||
///判断有没有过期
|
||||
if (int.parse(value.expireTime ?? "0") >
|
||||
DateTime
|
||||
.now()
|
||||
.millisecondsSinceEpoch) {
|
||||
DateTime.now().millisecondsSinceEpoch) {
|
||||
pr = value.propsResources;
|
||||
}
|
||||
}
|
||||
@ -144,15 +136,15 @@ class AccountStorage {
|
||||
void logout(BuildContext context) {
|
||||
_cleanUser();
|
||||
SCHeartbeatUtils.cancelTimer();
|
||||
Provider.of<RtcProvider>(context, listen: false).exitCurrentVoiceRoomSession(true);
|
||||
Provider.of<RtcProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).exitCurrentVoiceRoomSession(true);
|
||||
Provider.of<RtmProvider>(context, listen: false).logout();
|
||||
SCNavigatorUtils.push(context, LoginRouter.login, clearStack: true);
|
||||
SCRoomUtils.closeAllDialogs();
|
||||
SCMessageUtils.redPacketFutureCache.clear();
|
||||
SCGlobalConfig.isEntryVehicleAnimation = true;
|
||||
SCGlobalConfig.isGiftSpecialEffects = true;
|
||||
SCGlobalConfig.isFloatingAnimationInGlobal = true;
|
||||
SCGlobalConfig.isLuckGiftSpecialEffects = true;
|
||||
SCGlobalConfig.resetVisualEffectSwitchesToRecommendedDefaults();
|
||||
OverlayManager().dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import 'package:yumi/shared/business_logic/models/res/room_user_card_res.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/sc_violation_handle_res.dart';
|
||||
import 'package:yumi/shared/business_logic/repositories/room_repository.dart';
|
||||
import 'package:yumi/services/audio/rtm_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/api.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/remote/net/network_client.dart';
|
||||
import 'package:yumi/shared/tools/sc_room_profile_cache.dart';
|
||||
|
||||
@ -44,6 +45,10 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
return _instance ??= SCChatRoomRepository._internal();
|
||||
}
|
||||
|
||||
void _giftRepoLog(String message) {
|
||||
debugPrint('[GiftFX][Repo] $message');
|
||||
}
|
||||
|
||||
bool _isBrokenLocalMediaUrl(String? url) {
|
||||
return (url ?? "").contains("/external/oss/local/");
|
||||
}
|
||||
@ -314,6 +319,7 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
final result = await http.post(
|
||||
"daa4f379ff3e429e55c318b6af7291e8",
|
||||
data: params,
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
fromJson: (json) => json as double,
|
||||
);
|
||||
return result;
|
||||
@ -617,11 +623,27 @@ class SCChatRoomRepository implements SocialChatRoomRepository {
|
||||
params["accepts"] = accepts.toJson();
|
||||
}
|
||||
|
||||
_giftRepoLog(
|
||||
'request giveLuckyGift endpoint=/gift/give/lucky-gift '
|
||||
'giftId=$giftId '
|
||||
'roomId=$roomId '
|
||||
'quantity=$quantity '
|
||||
'checkCombo=$checkCombo '
|
||||
'acceptUserIds=${acceptUserIds.join(",")} '
|
||||
'payload=$params',
|
||||
);
|
||||
final result = await http.post(
|
||||
"6ddf7ebecfa97adf23c6303877c7763ce591ff710a7abc4fe1e335d16efee21b",
|
||||
data: params,
|
||||
extra: const {BaseNetworkClient.silentErrorToastKey: true},
|
||||
fromJson: (json) => json as double,
|
||||
);
|
||||
_giftRepoLog(
|
||||
'response giveLuckyGift endpoint=/gift/give/lucky-gift '
|
||||
'giftId=$giftId '
|
||||
'roomId=$roomId '
|
||||
'balance=$result',
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -7,25 +7,33 @@ import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class SCDeviceIdUtils {
|
||||
static void initDeviceinfo() {
|
||||
PackageInfo.fromPlatform().then((info) {
|
||||
static Future<void> initDeviceinfo() async {
|
||||
final info = await PackageInfo.fromPlatform();
|
||||
SCGlobalConfig.version = info.version;
|
||||
SCGlobalConfig.build = info.buildNumber;
|
||||
|
||||
final processorCount = Platform.numberOfProcessors;
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
SCGlobalConfig.channel = "Google";
|
||||
DeviceInfoPlugin().androidInfo.then((dev) {
|
||||
final dev = await DeviceInfoPlugin().androidInfo;
|
||||
SCGlobalConfig.model = dev.model;
|
||||
SCGlobalConfig.sysVersion = dev.version.release;
|
||||
SCGlobalConfig.sdkInt = dev.version.sdkInt;
|
||||
});
|
||||
SCGlobalConfig.applyDevicePerformanceProfile(
|
||||
isLowRamDevice: dev.isLowRamDevice,
|
||||
processorCount: processorCount,
|
||||
);
|
||||
} else if (Platform.isIOS) {
|
||||
SCGlobalConfig.channel = "AppStore";
|
||||
DeviceInfoPlugin().iosInfo.then((dev) {
|
||||
final dev = await DeviceInfoPlugin().iosInfo;
|
||||
SCGlobalConfig.model = dev.model;
|
||||
SCGlobalConfig.sysVersion = dev.systemVersion;
|
||||
});
|
||||
SCGlobalConfig.applyDevicePerformanceProfile(
|
||||
isLowRamDevice: false,
|
||||
processorCount: processorCount,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取持久化的唯一设备ID
|
||||
|
||||
@ -286,10 +286,11 @@ class SCGiftVapSvgaManager {
|
||||
'play request path=$path ext=${SCPathUtils.getFileExtension(path)} '
|
||||
'priority=$priority type=$type '
|
||||
'sdkInt=${SCGlobalConfig.sdkInt} maxSdkNoAnim=${SCGlobalConfig.maxSdkNoAnim} '
|
||||
'lowPerformance=${SCGlobalConfig.isLowPerformanceDevice} '
|
||||
'disposed=$_dis playing=$_play queueBefore=${_tq.length} '
|
||||
'hasSvgaCtrl=${_rsc != null} hasVapCtrl=${_rgc != null}',
|
||||
);
|
||||
if (SCGlobalConfig.sdkInt > SCGlobalConfig.maxSdkNoAnim) {
|
||||
if (SCGlobalConfig.allowsHighCostAnimations) {
|
||||
if (_dis) {
|
||||
_log('play ignored because manager is disposed path=$path');
|
||||
return;
|
||||
@ -307,8 +308,9 @@ class SCGiftVapSvgaManager {
|
||||
}
|
||||
} else {
|
||||
_log(
|
||||
'play ignored because sdkInt <= maxSdkNoAnim '
|
||||
'sdkInt=${SCGlobalConfig.sdkInt} maxSdkNoAnim=${SCGlobalConfig.maxSdkNoAnim}',
|
||||
'play ignored because performance profile disabled heavy animations '
|
||||
'sdkInt=${SCGlobalConfig.sdkInt} maxSdkNoAnim=${SCGlobalConfig.maxSdkNoAnim} '
|
||||
'lowPerformance=${SCGlobalConfig.isLowPerformanceDevice}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import 'dart:math';
|
||||
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';
|
||||
@ -19,32 +18,29 @@ import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
|
||||
import 'package:yumi/shared/tools/sc_lk_dialog_util.dart';
|
||||
|
||||
|
||||
typedef SCRoomUtils = SCChatRoomHelper;
|
||||
|
||||
class SCChatRoomHelper {
|
||||
static Map<String, SocialChatUserProfile> roomUsersMap = {};
|
||||
|
||||
static void goRoom(String roomId,
|
||||
static void goRoom(
|
||||
String roomId,
|
||||
BuildContext context, {
|
||||
bool needOpenRedenvelope = false,
|
||||
bool fromFloting = false,
|
||||
String redPackId = "",
|
||||
}) {
|
||||
if (Provider
|
||||
.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.currenRoom != null) {
|
||||
if (SCFloatIchart().isShow()) {
|
||||
///房间最小化了
|
||||
if (Provider
|
||||
.of<RealTimeCommunicationManager>(
|
||||
if (Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
)
|
||||
.currenRoom
|
||||
?.roomProfile
|
||||
?.roomProfile
|
||||
?.id ==
|
||||
).currenRoom !=
|
||||
null) {
|
||||
if (SCFloatIchart().isShow()) {
|
||||
///房间最小化了
|
||||
if (Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).currenRoom?.roomProfile?.roomProfile?.id ==
|
||||
roomId) {
|
||||
SCRoomUtils.openCurrentRoom(
|
||||
context,
|
||||
@ -61,17 +57,11 @@ class SCChatRoomHelper {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (Provider
|
||||
.of<RealTimeCommunicationManager>(
|
||||
if (Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
)
|
||||
.currenRoom
|
||||
?.roomProfile
|
||||
?.roomProfile
|
||||
?.id ==
|
||||
).currenRoom?.roomProfile?.roomProfile?.id ==
|
||||
roomId) {
|
||||
|
||||
} else {
|
||||
showEnterRoomConfirm(
|
||||
roomId,
|
||||
@ -93,46 +83,43 @@ class SCChatRoomHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static void openCurrentRoom(BuildContext context, {
|
||||
static void openCurrentRoom(
|
||||
BuildContext context, {
|
||||
bool needOpenRedenvelope = false,
|
||||
String? redPackId,
|
||||
}) {
|
||||
SCFloatIchart().remove();
|
||||
Provider.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.loadRoomInfo(
|
||||
Provider
|
||||
.of<RealTimeCommunicationManager>(
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
)
|
||||
.currenRoom
|
||||
?.roomProfile
|
||||
?.roomProfile
|
||||
?.id ??
|
||||
).loadRoomInfo(
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).currenRoom?.roomProfile?.roomProfile?.id ??
|
||||
"",
|
||||
);
|
||||
Provider.of<SocialChatUserProfileManager>(context, listen: false)
|
||||
.fetchUserProfileData();
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).fetchUserProfileData();
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).retrieveMicrophoneList();
|
||||
Provider.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.retrieveMicrophoneList();
|
||||
Provider
|
||||
.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.closeFullGame = true;
|
||||
SCNavigatorUtils.push(
|
||||
context,
|
||||
'${VoiceRoomRoute.voiceRoom}?id=${Provider
|
||||
.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.currenRoom
|
||||
?.roomProfile
|
||||
?.roomProfile
|
||||
?.id}',
|
||||
'${VoiceRoomRoute.voiceRoom}?id=${Provider.of<RealTimeCommunicationManager>(context, listen: false).currenRoom?.roomProfile?.roomProfile?.id}',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
static double getCurrenProgress(int currentEnergy,
|
||||
static double getCurrenProgress(
|
||||
int currentEnergy,
|
||||
int maxEnergy,
|
||||
double maxWidth,) {
|
||||
double maxWidth,
|
||||
) {
|
||||
var progress = (currentEnergy / maxEnergy);
|
||||
var curren = progress * maxWidth;
|
||||
if (curren > maxWidth) {
|
||||
@ -164,11 +151,7 @@ class SCChatRoomHelper {
|
||||
children: [
|
||||
Spacer(),
|
||||
GestureDetector(
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.black,
|
||||
size: 20.w,
|
||||
),
|
||||
child: Icon(Icons.close, color: Colors.black, size: 20.w),
|
||||
onTap: () {
|
||||
SmartDialog.dismiss(tag: "showGoToRecharge");
|
||||
},
|
||||
@ -199,10 +182,7 @@ class SCChatRoomHelper {
|
||||
width: 125.w,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Color(0xFFFEB219),
|
||||
Color(0xFFFF9326),
|
||||
],
|
||||
colors: [Color(0xFFFEB219), Color(0xFFFF9326)],
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
@ -237,18 +217,16 @@ class SCChatRoomHelper {
|
||||
///房间游客是否可以发消息
|
||||
static bool touristCanMsg(BuildContext context) {
|
||||
///游客可以发送文字
|
||||
if (Provider
|
||||
.of<RealTimeCommunicationManager>(
|
||||
if (Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
)
|
||||
.currenRoom
|
||||
?.roomProfile
|
||||
?.roomSetting
|
||||
?.touristMsg ??
|
||||
false) {} else {
|
||||
if (Provider.of<RealTimeCommunicationManager>(context, listen: false)
|
||||
.isTourists()) {
|
||||
).currenRoom?.roomProfile?.roomSetting?.touristMsg ??
|
||||
false) {
|
||||
} else {
|
||||
if (Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).isTourists()) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.touristsCannotSendMessages);
|
||||
return false;
|
||||
}
|
||||
@ -257,33 +235,34 @@ class SCChatRoomHelper {
|
||||
}
|
||||
|
||||
static void roomSCGlobalConfig(String roomId) {
|
||||
SCGlobalConfig.isGiftSpecialEffects = DataPersistence.getBool(
|
||||
"${AccountStorage()
|
||||
.getCurrentUser()
|
||||
?.userProfile
|
||||
?.account}-GiftSpecialEffects",
|
||||
defaultValue: true,
|
||||
final defaultEffectsEnabled = !SCGlobalConfig.isLowPerformanceDevice;
|
||||
SCGlobalConfig
|
||||
.isGiftSpecialEffects = SCGlobalConfig.clampVisualEffectPreference(
|
||||
DataPersistence.getBool(
|
||||
"${AccountStorage().getCurrentUser()?.userProfile?.account}-GiftSpecialEffects",
|
||||
defaultValue: defaultEffectsEnabled,
|
||||
),
|
||||
);
|
||||
SCGlobalConfig.isEntryVehicleAnimation = DataPersistence.getBool(
|
||||
"${AccountStorage()
|
||||
.getCurrentUser()
|
||||
?.userProfile
|
||||
?.account}-EntryVehicleAnimation",
|
||||
defaultValue: true,
|
||||
SCGlobalConfig
|
||||
.isEntryVehicleAnimation = SCGlobalConfig.clampVisualEffectPreference(
|
||||
DataPersistence.getBool(
|
||||
"${AccountStorage().getCurrentUser()?.userProfile?.account}-EntryVehicleAnimation",
|
||||
defaultValue: defaultEffectsEnabled,
|
||||
),
|
||||
);
|
||||
SCGlobalConfig.isFloatingAnimationInGlobal = DataPersistence.getBool(
|
||||
"${AccountStorage()
|
||||
.getCurrentUser()
|
||||
?.userProfile
|
||||
?.account}-FloatingAnimationInGlobal",
|
||||
defaultValue: true,
|
||||
SCGlobalConfig
|
||||
.isFloatingAnimationInGlobal = SCGlobalConfig.clampVisualEffectPreference(
|
||||
DataPersistence.getBool(
|
||||
"${AccountStorage().getCurrentUser()?.userProfile?.account}-FloatingAnimationInGlobal",
|
||||
defaultValue: defaultEffectsEnabled,
|
||||
),
|
||||
);
|
||||
SCGlobalConfig.isLuckGiftSpecialEffects = DataPersistence.getBool(
|
||||
"${AccountStorage()
|
||||
.getCurrentUser()
|
||||
?.userProfile
|
||||
?.account}-LuckGiftSpecialEffects",
|
||||
defaultValue: true,
|
||||
SCGlobalConfig
|
||||
.isLuckGiftSpecialEffects = SCGlobalConfig.clampVisualEffectPreference(
|
||||
DataPersistence.getBool(
|
||||
"${AccountStorage().getCurrentUser()?.userProfile?.account}-LuckGiftSpecialEffects",
|
||||
defaultValue: defaultEffectsEnabled,
|
||||
),
|
||||
);
|
||||
DataPersistence.setLastTimeRoomId(roomId);
|
||||
}
|
||||
@ -297,6 +276,4 @@ class SCChatRoomHelper {
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,21 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_rotating_dots_loading.dart';
|
||||
|
||||
int? _resolveMemCacheDimension(double? logicalSize) {
|
||||
if (logicalSize == null || !logicalSize.isFinite || logicalSize <= 0) {
|
||||
return null;
|
||||
}
|
||||
final devicePixelRatio =
|
||||
WidgetsBinding
|
||||
.instance
|
||||
.platformDispatcher
|
||||
.implicitView
|
||||
?.devicePixelRatio ??
|
||||
2.0;
|
||||
final pixelSize = (logicalSize * devicePixelRatio).round();
|
||||
return pixelSize.clamp(1, 1920).toInt();
|
||||
}
|
||||
|
||||
class CustomCachedImage extends StatelessWidget {
|
||||
final String imageUrl;
|
||||
final double? width;
|
||||
@ -30,6 +45,8 @@ class CustomCachedImage extends StatelessWidget {
|
||||
imageUrl: imageUrl,
|
||||
width: width,
|
||||
height: height,
|
||||
memCacheWidth: _resolveMemCacheDimension(width),
|
||||
memCacheHeight: _resolveMemCacheDimension(height),
|
||||
fit: fit,
|
||||
placeholder: (context, url) => placeholder ?? _defaultPlaceholder(),
|
||||
errorWidget:
|
||||
|
||||
@ -18,6 +18,22 @@ import '../../shared/data_sources/models/enum/sc_room_roles_type.dart';
|
||||
|
||||
const String kRoomCoverDefaultImg = "sc_images/general/sc_no_data.png";
|
||||
|
||||
int? _resolveImageCacheDimension(double? logicalSize) {
|
||||
if (logicalSize == null || !logicalSize.isFinite || logicalSize <= 0) {
|
||||
return null;
|
||||
}
|
||||
final devicePixelRatio =
|
||||
WidgetsBinding
|
||||
.instance
|
||||
.platformDispatcher
|
||||
.implicitView
|
||||
?.devicePixelRatio ??
|
||||
2.0;
|
||||
final maxDimension = SCGlobalConfig.isLowPerformanceDevice ? 1280 : 1920;
|
||||
final pixelSize = (logicalSize * devicePixelRatio).round();
|
||||
return pixelSize.clamp(1, maxDimension).toInt();
|
||||
}
|
||||
|
||||
String resolveRoomCoverUrl(String? roomId, String? roomCover) {
|
||||
final cache = SCRoomProfileCache.getRoomProfile(roomId ?? "");
|
||||
return SCRoomProfileCache.preferCachedValue(cache["roomCover"], roomCover) ??
|
||||
@ -133,7 +149,7 @@ Widget head({
|
||||
headdress != null &&
|
||||
SCPathUtils.getFileExtension(headdress).toLowerCase() ==
|
||||
".svga" &&
|
||||
SCGlobalConfig.sdkInt > SCGlobalConfig.maxSdkNoAnim
|
||||
SCGlobalConfig.allowsHighCostAnimations
|
||||
? IgnorePointer(
|
||||
child: SVGAHeadwearWidget(
|
||||
width: width,
|
||||
@ -145,7 +161,7 @@ Widget head({
|
||||
headdress != null &&
|
||||
SCPathUtils.getFileExtension(headdress).toLowerCase() ==
|
||||
".mp4" &&
|
||||
SCGlobalConfig.sdkInt > SCGlobalConfig.maxSdkNoAnim
|
||||
SCGlobalConfig.allowsHighCostAnimations
|
||||
? SizedBox(
|
||||
width: width,
|
||||
height: width,
|
||||
@ -187,6 +203,8 @@ Widget netImage({
|
||||
url,
|
||||
width: width,
|
||||
height: height ?? width,
|
||||
cacheWidth: _resolveImageCacheDimension(width),
|
||||
cacheHeight: _resolveImageCacheDimension(height ?? width),
|
||||
headers: buildNetworkImageHeaders(url),
|
||||
fit: fit ?? BoxFit.cover,
|
||||
cache: true,
|
||||
@ -195,6 +213,7 @@ Widget netImage({
|
||||
clearMemoryCacheWhenDispose: false,
|
||||
clearMemoryCacheIfFailed: true,
|
||||
border: border,
|
||||
filterQuality: FilterQuality.low,
|
||||
gaplessPlayback: true,
|
||||
loadStateChanged: (ExtendedImageState state) {
|
||||
if (state.extendedImageLoadState == LoadState.completed) {
|
||||
|
||||
@ -7,9 +7,10 @@ import 'package:provider/provider.dart';
|
||||
import 'package:yumi/ui_kit/components/text/sc_text.dart';
|
||||
import 'package:yumi/services/gift/gift_animation_manager.dart';
|
||||
|
||||
|
||||
///房间礼物滚屏动画
|
||||
class LGiftAnimalPage extends StatefulWidget {
|
||||
const LGiftAnimalPage({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _GiftAnimalPageState();
|
||||
@ -18,71 +19,98 @@ class LGiftAnimalPage extends StatefulWidget {
|
||||
|
||||
class _GiftAnimalPageState extends State<LGiftAnimalPage>
|
||||
with TickerProviderStateMixin {
|
||||
static const Set<int> _luckyGiftMilestones = <int>{10, 20, 50, 100, 200, 300};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 305.w,
|
||||
child: Stack(
|
||||
children: [
|
||||
Consumer<GiftAnimationManager>(
|
||||
return SizedBox(
|
||||
height: 332.w,
|
||||
child: Consumer<GiftAnimationManager>(
|
||||
builder: (context, ref, child) {
|
||||
return ref.giftMap[0] != null
|
||||
? AnimatedBuilder(
|
||||
animation: ref.animationControllerList[0].controller,
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: List.generate(
|
||||
4,
|
||||
(index) => _buildGiftTickerItem(context, ref, index),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGiftTickerItem(
|
||||
BuildContext context,
|
||||
GiftAnimationManager ref,
|
||||
int index,
|
||||
) {
|
||||
final gift = ref.giftMap[index];
|
||||
if (gift == null || ref.animationControllerList.length <= index) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final bean = ref.animationControllerList[index];
|
||||
return AnimatedBuilder(
|
||||
animation: bean.controller,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
margin: ref.animationControllerList[0].verticalAnimation.value,
|
||||
width: ScreenUtil().screenWidth * 0.75,
|
||||
margin: bean.verticalAnimation.value,
|
||||
width: ScreenUtil().screenWidth * 0.78,
|
||||
child: _buildGiftTickerCard(context, gift, bean.sizeAnimation.value),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildGiftTickerCard(
|
||||
BuildContext context,
|
||||
LGiftModel gift,
|
||||
double animatedSize,
|
||||
) {
|
||||
return SizedBox(
|
||||
height: 52.w,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
width: ScreenUtil().screenWidth * 0.67,
|
||||
height: 42.w,
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
top: 5.w,
|
||||
start: 3.w,
|
||||
end: 76.w,
|
||||
top: 3.w,
|
||||
bottom: 3.w,
|
||||
),
|
||||
width: ScreenUtil().screenWidth * 0.65,
|
||||
height:
|
||||
35.w,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
getBg(""),
|
||||
),
|
||||
image: AssetImage(getBg("")),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(width: 3.w),
|
||||
netImage(
|
||||
url: ref.giftMap[0]!.sendUserPic,
|
||||
url: gift.sendUserPic,
|
||||
shape: BoxShape.circle,
|
||||
width: 25.w,
|
||||
height: 25.w,
|
||||
width: 26.w,
|
||||
height: 26.w,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Column(
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
socialchatNickNameText(
|
||||
maxWidth: 82.w,
|
||||
ref.giftMap[0]!.sendUserName ?? "",
|
||||
maxWidth: 88.w,
|
||||
gift.sendUserName,
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
type: "",
|
||||
needScroll:
|
||||
(ref
|
||||
.giftMap[0]!
|
||||
.sendUserName
|
||||
.characters
|
||||
.length ??
|
||||
0) >
|
||||
8,
|
||||
needScroll: gift.sendUserName.characters.length > 8,
|
||||
),
|
||||
//SizedBox(width: 2.w,),
|
||||
SizedBox(height: 1.w),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
@ -90,19 +118,18 @@ class _GiftAnimalPageState extends State<LGiftAnimalPage>
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: Colors.white,
|
||||
height: 1.0,
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 62.w,
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
"${ref.giftMap[0]?.sendToUserName}",
|
||||
gift.sendToUserName,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color:Color(0xFFFFD400),
|
||||
color: const Color(0xFFFFD400),
|
||||
height: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -110,540 +137,168 @@ class _GiftAnimalPageState extends State<LGiftAnimalPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 155.w,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
netImage(
|
||||
url: ref.giftMap[0]!.giftPic,
|
||||
fit: BoxFit.cover,
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
width: 32.w,
|
||||
height: 32.w,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "x",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[0]
|
||||
.sizeAnimation
|
||||
.value
|
||||
.w,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
"${ref.giftMap[0]!.giftCount}",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[0]
|
||||
.sizeAnimation
|
||||
.value,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Container();
|
||||
},
|
||||
),
|
||||
Consumer<GiftAnimationManager>(
|
||||
builder: (context, ref, child) {
|
||||
return ref.giftMap[1] != null
|
||||
? AnimatedBuilder(
|
||||
animation: ref.animationControllerList[1].controller,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
margin: ref.animationControllerList[1].verticalAnimation.value,
|
||||
width: ScreenUtil().screenWidth * 0.75,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
top:
|
||||
6.w,
|
||||
),
|
||||
width: ScreenUtil().screenWidth * 0.65,
|
||||
height:
|
||||
35.w,
|
||||
decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(52),
|
||||
// gradient: LinearGradient(
|
||||
// colors: [
|
||||
// Color(0xffFFE400),
|
||||
// Color(0xffFFE400).withOpacity(0.7),
|
||||
// Color(0xffFFE400).withOpacity(0),
|
||||
// ]
|
||||
// ),
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
getBg(""),
|
||||
),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
PositionedDirectional(
|
||||
end: 0,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: ScreenUtil().screenWidth * 0.30,
|
||||
minHeight: 40.w,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(width: 3.w),
|
||||
netImage(
|
||||
url: ref.giftMap[1]!.sendUserPic,
|
||||
shape: BoxShape.circle,
|
||||
width: 25.w,
|
||||
height: 25.w,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
socialchatNickNameText(
|
||||
maxWidth: 82.w,
|
||||
ref.giftMap[1]!.sendUserName ?? "",
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
type: "",
|
||||
needScroll:
|
||||
(ref
|
||||
.giftMap[1]!
|
||||
.sendUserName
|
||||
.characters
|
||||
.length ??
|
||||
0) >
|
||||
8,
|
||||
),
|
||||
//SizedBox(width: 2.w,),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"${SCAppLocalizations.of(context)!.sendTo} ",
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 62.w,
|
||||
),
|
||||
child: Text(
|
||||
"${ref.giftMap[1]?.sendToUserName}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color:Color(0xFFFFD400),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 155.w,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
netImage(
|
||||
url: ref.giftMap[1]!.giftPic,
|
||||
url: gift.giftPic,
|
||||
fit: BoxFit.cover,
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
width: 32.w,
|
||||
height: 32.w,
|
||||
width: 34.w,
|
||||
height: 34.w,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "x",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[1]
|
||||
.sizeAnimation
|
||||
.value
|
||||
.w,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
"${ref.giftMap[1]!.giftCount}",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[1]
|
||||
.sizeAnimation
|
||||
.value,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
SizedBox(width: 8.w),
|
||||
Flexible(
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _buildGiftCountLabel(gift, animatedSize),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Container();
|
||||
},
|
||||
),
|
||||
Consumer<GiftAnimationManager>(
|
||||
builder: (context, ref, child) {
|
||||
return ref.giftMap[2] != null
|
||||
? AnimatedBuilder(
|
||||
animation: ref.animationControllerList[2].controller,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
margin: ref.animationControllerList[2].verticalAnimation.value,
|
||||
width: ScreenUtil().screenWidth * 0.75,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
top:
|
||||
6.w,
|
||||
),
|
||||
width: ScreenUtil().screenWidth * 0.65,
|
||||
height:
|
||||
35.w,
|
||||
decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(52),
|
||||
// gradient: LinearGradient(
|
||||
// colors: [
|
||||
// Color(0xffFFE400),
|
||||
// Color(0xffFFE400).withOpacity(0.7),
|
||||
// Color(0xffFFE400).withOpacity(0),
|
||||
// ]
|
||||
// ),
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
getBg(""),
|
||||
),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
Widget _buildGiftCountLabel(LGiftModel gift, double animatedSize) {
|
||||
final isMilestone = _isLuckyGiftMilestone(gift);
|
||||
final xFontSize = animatedSize * (isMilestone ? 1.1 : 1.0);
|
||||
final countFontSize = animatedSize * (isMilestone ? 1.45 : 1.0);
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(width: 3.w),
|
||||
netImage(
|
||||
url: ref.giftMap[2]!.sendUserPic,
|
||||
shape: BoxShape.circle,
|
||||
width: 25.w,
|
||||
height: 25.w,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
socialchatNickNameText(
|
||||
maxWidth: 82.w,
|
||||
ref.giftMap[2]!.sendUserName ?? "",
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
type: "",
|
||||
needScroll:
|
||||
(ref
|
||||
.giftMap[2]!
|
||||
.sendUserName
|
||||
.characters
|
||||
.length ??
|
||||
0) >
|
||||
8,
|
||||
),
|
||||
//SizedBox(width: 2.w,),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"${SCAppLocalizations.of(context)!.sendTo} ",
|
||||
"x",
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 62.w,
|
||||
),
|
||||
child: Text(
|
||||
"${ref.giftMap[2]?.sendToUserName}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color:Color(0xFFFFD400),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 155.w,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
netImage(
|
||||
url: ref.giftMap[2]!.giftPic,
|
||||
fit: BoxFit.cover,
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
width: 32.w,
|
||||
height: 32.w,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "x",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[2]
|
||||
.sizeAnimation
|
||||
.value
|
||||
.w,
|
||||
fontSize: xFontSize,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
color:
|
||||
isMilestone
|
||||
? const Color(0xFFFFE08A)
|
||||
: const Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1,
|
||||
shadows:
|
||||
isMilestone
|
||||
? const [
|
||||
Shadow(
|
||||
color: Color(0xCC7A3E00),
|
||||
blurRadius: 8,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
"${ref.giftMap[2]!.giftCount}",
|
||||
SizedBox(width: 2.w),
|
||||
isMilestone
|
||||
? _buildMilestoneGiftCountText(
|
||||
_giftCountText(gift.giftCount),
|
||||
fontSize: countFontSize,
|
||||
)
|
||||
: Text(
|
||||
_giftCountText(gift.giftCount),
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[2]
|
||||
.sizeAnimation
|
||||
.value,
|
||||
fontSize: countFontSize,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
color: const Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Container();
|
||||
},
|
||||
),
|
||||
Consumer<GiftAnimationManager>(
|
||||
builder: (context, ref, child) {
|
||||
return ref.giftMap[3] != null
|
||||
? AnimatedBuilder(
|
||||
animation: ref.animationControllerList[3].controller,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
margin: ref.animationControllerList[3].verticalAnimation.value,
|
||||
width: ScreenUtil().screenWidth * 0.75,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
top:
|
||||
6.w,
|
||||
),
|
||||
width: ScreenUtil().screenWidth * 0.65,
|
||||
height:
|
||||
35.w,
|
||||
decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(52),
|
||||
// gradient: LinearGradient(
|
||||
// colors: [
|
||||
// Color(0xffFFE400),
|
||||
// Color(0xffFFE400).withOpacity(0.7),
|
||||
// Color(0xffFFE400).withOpacity(0),
|
||||
// ]
|
||||
// ),
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
getBg(""),
|
||||
),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(width: 3.w),
|
||||
netImage(
|
||||
url: ref.giftMap[3]!.sendUserPic,
|
||||
shape: BoxShape.circle,
|
||||
width: 25.w,
|
||||
height: 25.w,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
socialchatNickNameText(
|
||||
maxWidth: 82.w,
|
||||
ref.giftMap[3]!.sendUserName ?? "",
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
type: "",
|
||||
needScroll:
|
||||
(ref
|
||||
.giftMap[3]!
|
||||
.sendUserName
|
||||
.characters
|
||||
.length ??
|
||||
0) >
|
||||
8,
|
||||
),
|
||||
//SizedBox(width: 2.w,),
|
||||
Row(
|
||||
}
|
||||
|
||||
Widget _buildMilestoneGiftCountText(
|
||||
String countText, {
|
||||
required double fontSize,
|
||||
}) {
|
||||
return Stack(
|
||||
children: [
|
||||
Text(
|
||||
"${SCAppLocalizations.of(context)!.sendTo} ",
|
||||
countText,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: Colors.white,
|
||||
fontSize: fontSize,
|
||||
fontStyle: FontStyle.italic,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1,
|
||||
foreground:
|
||||
Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.8
|
||||
..color = const Color(0xFF7A3E00),
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: 62.w,
|
||||
),
|
||||
ShaderMask(
|
||||
blendMode: BlendMode.srcIn,
|
||||
shaderCallback:
|
||||
(bounds) => const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Color(0xFFFFF6C7),
|
||||
Color(0xFFFFE07A),
|
||||
Color(0xFFFFB800),
|
||||
],
|
||||
).createShader(bounds),
|
||||
child: Text(
|
||||
"${ref.giftMap[3]?.sendToUserName}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
countText,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color:Color(0xFFFFD400),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 155.w,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
netImage(
|
||||
url: ref.giftMap[3]!.giftPic,
|
||||
fit: BoxFit.cover,
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
width: 32.w,
|
||||
height: 32.w,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "x",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[3]
|
||||
.sizeAnimation
|
||||
.value
|
||||
.w,
|
||||
fontSize: fontSize,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
"${ref.giftMap[3]!.giftCount}",
|
||||
style: TextStyle(
|
||||
fontSize:
|
||||
ref
|
||||
.animationControllerList[3]
|
||||
.sizeAnimation
|
||||
.value,
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Color(0xFFFFD400),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Colors.white,
|
||||
height: 1,
|
||||
shadows: const [
|
||||
Shadow(
|
||||
color: Color(0xCC6A3700),
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Container();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool _isLuckyGiftMilestone(LGiftModel gift) {
|
||||
if (!gift.isLuckyGift) {
|
||||
return false;
|
||||
}
|
||||
final count = gift.giftCount;
|
||||
if (count % 1 != 0) {
|
||||
return false;
|
||||
}
|
||||
return _luckyGiftMilestones.contains(count.toInt());
|
||||
}
|
||||
|
||||
String _giftCountText(num count) {
|
||||
return count % 1 == 0 ? count.toInt().toString() : count.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
Provider.of<GiftAnimationManager>(
|
||||
@ -770,7 +425,9 @@ class LGiftModel {
|
||||
//一次发送礼物的数量
|
||||
num giftCount = 0;
|
||||
|
||||
//是否幸运礼物,用于特殊档位样式
|
||||
bool isLuckyGift = false;
|
||||
|
||||
//id
|
||||
String labelId = "";
|
||||
|
||||
}
|
||||
|
||||
@ -58,7 +58,8 @@ class _MsgItemState extends State<MsgItem> {
|
||||
}
|
||||
|
||||
///礼物
|
||||
if (widget.msg.type == SCRoomMsgType.gift) {
|
||||
if (widget.msg.type == SCRoomMsgType.gift ||
|
||||
widget.msg.type == SCRoomMsgType.luckGiftAnimOther) {
|
||||
return _buildGiftMsg(context);
|
||||
}
|
||||
|
||||
|
||||
5
需求进度.md
5
需求进度.md
@ -13,6 +13,10 @@
|
||||
- 本轮按需求暂未处理网络链路上的启动等待,例如审核态检查或远端启动页配置请求。
|
||||
|
||||
## 已完成模块
|
||||
- 已修复礼物页幸运礼物发送链路:当前 `gift_page` 会按礼物类型分流,普通礼物继续走 `/gift/batch`,`LUCKY_GIFT/LUCK/MAGIC` 改走已存在的 `/gift/give/lucky-gift`;幸运/魔法礼物成功后不再本地伪造普通 `GIFT` 消息,而是改发房间内 `LUCK_GIFT_ANIM_OTHER` 动画消息,避免和后端幸运礼物开奖/补发逻辑打架;同时送礼失败已补用户提示,且对 `standardId` 缺失的幸运礼物增加了前置拦截,避免继续点发送却只有日志没有反馈。
|
||||
- 已继续补齐幸运礼物前端可见反馈:根据真机日志确认 `giveLuckyGift` 和腾讯 IM 房间消息发送都已成功,当前问题收敛为发送端没有本地回显、且 `LUCK_GIFT_ANIM_OTHER` 收到后未真正接入房间礼物动画;现已在发送成功后先本地触发一轮房间礼物上飘反馈,并把收到的 `LUCK_GIFT_ANIM_OTHER` 直接接入现有房间礼物动画 listener,确保发送端和房间内其它端都能看到即时反应。排障期间临时加过的发送并发锁已在后续需求确认后撤回,不再限制幸运礼物连点。
|
||||
- 已按最新确认调整幸运礼物点击策略:撤回前一轮为排障临时加上的发送并发锁,恢复幸运礼物可连续点击;当前连点时每次请求仍走 `/gift/give/lucky-gift`,并继续通过本地回显 + `LUCK_GIFT_ANIM_OTHER` 接入现有房间礼物动画 listener 的方式提供与普通礼物一致的即时播报体验。
|
||||
- 已继续优化房间礼物播报 UI:礼物上飘条目高度与内部约束已重新收紧,修复底部 `bottom overflow`;同时为幸运礼物新增 10/20/50/100/200/300 连击特殊样式,这些档位的连击数字会以更大的“霸气金”渐变字显示,普通礼物与非里程碑连击保持原样式。
|
||||
- 已修复 `Me -> Friends/Fans 列表 -> 他人主页 -> 返回 Me` 后个人资料串号的问题:`MePage2` 现只读取当前登录用户资料,`SocialChatUserProfileManager.userProfile` 继续只承载“当前查看中的详情页用户”,同时移除了 `syncCurrentUserProfile()` 对详情态的覆盖,避免查看他人资料后把 `Me` 页错误渲染成对方信息。
|
||||
- 已按本轮动效替换需求完成首页底部 tab 动效接入,并同步将本轮新增本地 `.svga` 资源统一改成项目命名风格:当前 `Home / Explore / Message / Me` 已分别使用 `sc_icon_home_anim.svga / sc_icon_explore_anim.svga / sc_icon_message_anim.svga / sc_icon_me_anim.svga`,并继续保留原有 png 作为失败兜底;后续新增本地动效资源默认也按 `sc_icon_*_anim` 规则命名。
|
||||
- 已将语言房右侧 `game` 悬浮入口从 emoji 占位替换为本地动效资源,并按最新反馈移除外层圆形 `container`:当前直接使用 `sc_icon_room_game_entry_anim.svga` 本体作为入口展示,尺寸与原入口占位一致;若 SVGA 加载失败,会自动回退到项目原有 `sc_icon_botton_game.png`。
|
||||
@ -47,6 +51,7 @@
|
||||
- 已继续定位“游戏画面可见但触摸无响应”的 Flutter 侧原因:当前实现此前一直把 BAISHUN H5 页面放在 `showGeneralDialog` 底部弹层里承载,同时 App 启动时又全局锁定了 `portraitUp`;对于 `FishingStar` 这类横版游戏,这会叠加出“平台视图在弹层容器中的命中不稳定 + iPhone 端实际不支持横屏”的问题。现已改为用独立路由承载 BAISHUN 游戏页,并按启动数据里的 `orientation` 动态切换横竖屏;同时 iOS `Info.plist` 已补充手机横屏支持,便于继续验证横版游戏触摸是否恢复。上述调整仍属于本轮 BAISHUN 联调修正,不是新的正式产品交互。
|
||||
- 已按最新联调反馈回撤 BAISHUN 页面的横屏适配:当前后续不会接横屏游戏,因此已去掉游戏页按 `orientation` 切换系统方向的逻辑,并撤回 iPhone 端新增的横屏声明,只保留独立路由承载 BAISHUN 页面这一项 Flutter 容器修正。同时已继续增强临时调试,在 H5 侧补充 `pointerdown / touchstart / mousedown / click` 事件回传,用于下一轮真机直接确认“点击是否真的进到了 H5 DOM”;这些输入事件日志依旧只用于本轮排障,后续需要删除。
|
||||
- 已按当前收尾需求移除 BAISHUN 临时调试面板:`BS DEBUG` 组件和相关调试入口现已从游戏页删除,不再作为正式功能保留;同时游戏页展示高度已恢复为接近半屏的底部弹出样式,回到最初设定的房内游戏视觉形态。
|
||||
- 已继续微调 BAISHUN 游戏页高度:由于真实 H5 内容本身就是接近半屏,且顶部还需要预留拖拽条和标题栏空间,当前底部游戏页容器高度已从上一版的 `0.56` 屏高上调到 `0.62`,避免视觉上看起来比预期半屏更矮。
|
||||
- 创建并持续维护进度跟踪文件。
|
||||
- 已继续排查语言房 gift 动画链路:确认送礼后会同时走本地房间消息、滚屏礼物条和大额礼物全局飘屏三条路径,并修复动画管理器在控制器尚未绑定完成时提前消费队列导致后续动画不再播放的问题。
|
||||
- 已定位并修复语言房礼物飘屏资源引用错误:代码里误写 `sc_icon_gift_flosc_bg` / `sc_icon_luck_gift_flosc_*`,实际资源文件名为 `float`,导致点击送礼后飘屏背景图加载失败,相关动画无法正常显示。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user