diff --git a/YuMi/Modules/YMMine/View/MineInfo/XPMineUserInfoEditViewController.m b/YuMi/Modules/YMMine/View/MineInfo/XPMineUserInfoEditViewController.m index b9b9166e..7d5dda8a 100644 --- a/YuMi/Modules/YMMine/View/MineInfo/XPMineUserInfoEditViewController.m +++ b/YuMi/Modules/YMMine/View/MineInfo/XPMineUserInfoEditViewController.m @@ -483,11 +483,11 @@ TZImagePickerControllerDelegate> // 检查视频时长(头像视频应该在5秒内) NSTimeInterval duration = asset.duration; - if (duration > 555.0) { + if (duration > 5.0) { dispatch_async(dispatch_get_main_queue(), ^{ @kStrongify(self); [self hideHUD]; - [self showErrorToast:@"视频时长不能超过555秒"]; + [self showErrorToast:YMLocalizedString(@"20.20.51_text_30")]; }); return; } diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m b/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m index d7f4ca4c..ab8c3fb0 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m @@ -1109,7 +1109,7 @@ NSString * const kRoomShowTopicKey = @"kRoomShowTopicKey"; NSDictionary *obj = [datas xpSafeObjectAtIndex:0]; if (obj) { NSArray *results = [obj objectForKey:@"resultIndexes"]; - if (results.count > 0) { + if ([results isKindOfClass:[NSArray class]] && results.count > 0) { delay = 2.5; } } diff --git a/YuMi/Modules/YMRoom/View/MoreView/Factory/XPRoomMoreMenuActionFactory.m b/YuMi/Modules/YMRoom/View/MoreView/Factory/XPRoomMoreMenuActionFactory.m index 8c6bdb5c..1426c485 100644 --- a/YuMi/Modules/YMRoom/View/MoreView/Factory/XPRoomMoreMenuActionFactory.m +++ b/YuMi/Modules/YMRoom/View/MoreView/Factory/XPRoomMoreMenuActionFactory.m @@ -28,7 +28,7 @@ + (NSArray *)createActionsWithContext:(XPRoomMoreMenuActionContext *)context { NSMutableArray *actions = [NSMutableArray array]; - [actions addObject:[XPSocialAction trumpetAction]]; +// [actions addObject:[XPSocialAction trumpetAction]]; [actions addObject:[XPTurboModeAction actionWithRoomInfo:context.roomInfo]]; [actions addObject:[XPRoomAppManagerAction action]]; [actions addObject:[XPSocialAction reportAction]]; @@ -78,13 +78,13 @@ // 4. 基础功能 - 根据权限 if (userNotNormal) { - [actions addObject:[XPSocialAction trumpetAction]]; +// [actions addObject:[XPSocialAction trumpetAction]]; [actions addObject:[XPRoomEffectAction action]]; [actions addObject:[XPRoomSettingAction action]]; [actions addObject:[XPRoomBackGroundSettingAction action]]; [actions addObject:[XPRoomCleanMessagesAction action]]; } else { - [actions addObject:[XPSocialAction trumpetAction]]; +// [actions addObject:[XPSocialAction trumpetAction]]; [actions addObject:[XPRoomEffectAction action]]; } @@ -138,7 +138,7 @@ + (NSArray *)createSuperAdminActionsWithContext:(XPRoomMoreMenuActionContext *)context { NSMutableArray *actions = [NSMutableArray array]; - [actions addObject:[XPSocialAction trumpetAction]]; +// [actions addObject:[XPSocialAction trumpetAction]]; [actions addObject:[XPTurboModeAction actionWithRoomInfo:context.roomInfo]]; [actions addObject:[XPRoomAppManagerAction action]]; [actions addObject:[XPSocialAction reportAction]]; diff --git a/YuMi/ar.lproj/Localizable.strings b/YuMi/ar.lproj/Localizable.strings index 34005150..5485b6c5 100644 --- a/YuMi/ar.lproj/Localizable.strings +++ b/YuMi/ar.lproj/Localizable.strings @@ -4146,6 +4146,7 @@ ineHeadView12" = "الحمل"; "20.20.51_text_27" = "١ في كل مرة تقوم فيها بتحميل صورة رمزية ديناميكية سيقوم النظام بخصم %@ عملة من حسابك. يرجى التأكد من أن رصيد حسابك كافٍ\n\n٢ عملية المراجعة: بعد اكتمال التحميل، سيدخل النظام تلقائيًا عملية المراجعة. خلال هذه الفترة، يرجى عدم تحميل صورة رمزية جديدة مرة أخرى لتجنب التأثير على تقدم المراجعة.\n\n٣ نتائج المراجعة \n\nتمت المراجعة بنجاح: ستدخل الصورة الرمزية الديناميكية الجديدة حيز التنفيذ على الفور وسيتم عرضها للمستخدمين الآخرين.\n\nفشل المراجعة: سيقوم النظام تلقائيًا برد %@ عملة أنفقتها بعد اكتمال المراجعة. في نفس الوقت، ستتلقى إشعارًا من النظام.\n\n٤ عملية لا رجعة فيها: يرجى ملاحظة أنه بمجرد مراجعة الصورة الرمزية الديناميكية ودخولها حيز التنفيذ، فلن تتمكن من استعادتها إلى الصورة الرمزية السابقة.\n"; "20.20.51_text_28" = "عرض الوقت:%@"; "20.20.51_text_29" = "يجب أن يكون عدد الماس مضاعفات %@"; +"20.20.51_text_30" = "يجب ألا تتجاوز مدة الفيديو 10 ثوانٍ."; "20.20.56_text_1" = "عدد المباريات الحالي غير كافٍ، فشلت المباراة. إعادة المباراة مرة أخرى؟"; "20.20.56_text_2" = "فشلت المطابقة، تم إرجاع العملات التي استهلكتها إلى محفظتك"; diff --git a/YuMi/en.lproj/Localizable.strings b/YuMi/en.lproj/Localizable.strings index 8beb2340..988eaca7 100644 --- a/YuMi/en.lproj/Localizable.strings +++ b/YuMi/en.lproj/Localizable.strings @@ -3933,6 +3933,7 @@ "20.20.51_text_27" = "1 Each time you upload a dynamic avatar, the system will deduct %@ coins from your account. Please make sure that your account balance is sufficient.\n2 Review process: After the upload is completed, the system will automatically enter the review process. During this period, please do not upload a new avatar again to avoid affecting the review progress.\n3 Review results: \nReview passed: Your new dynamic avatar will take effect immediately and be displayed to other users.\nReview failed: The system will automatically refund the %@ coins you spent after the review is completed. At the same time, you will receive a system notification.\n4 Irreversible operation: Please note that once the dynamic avatar is reviewed and takes effect, you will not be able to restore it to the previous avatar.\n"; "20.20.51_text_28" = "View Time: %@"; "20.20.51_text_29" = "Number of diamonds needs to be multiples of %@"; +"20.20.51_text_30" = "Video duration must not exceed 10 seconds."; "20.20.56_text_1" = "The current number of matches is not enough, the match failed. Re-match again?"; "20.20.56_text_2" = "Match failed, the coins you consumed has been returned to your wallet"; diff --git a/YuMi/es.lproj/Localizable.strings b/YuMi/es.lproj/Localizable.strings index 769aaf4a..c7525be5 100644 --- a/YuMi/es.lproj/Localizable.strings +++ b/YuMi/es.lproj/Localizable.strings @@ -3941,6 +3941,7 @@ Revisión fallida: El sistema reembolsará automáticamente las %@ monedas que g "; "20.20.51_text_28" = "Hora de Vista: %@"; "20.20.51_text_29" = "El número de diamantes debe ser múltiplo de 1000"; +"20.20.51_text_30" = "La duración del video no debe exceder los 10 segundos."; "20.20.56_text_1" = "La cantidad actual de coincidencias no es suficiente, la coincidencia falló. ¿Volver a intentar?"; "20.20.56_text_2" = "Coincidencia fallida, las monedas que consumiste han sido devueltas a tu billetera"; diff --git a/YuMi/pt-BR.lproj/Localizable.strings b/YuMi/pt-BR.lproj/Localizable.strings index 0a98eb76..8ded8096 100644 --- a/YuMi/pt-BR.lproj/Localizable.strings +++ b/YuMi/pt-BR.lproj/Localizable.strings @@ -3229,6 +3229,8 @@ "20.20.51_text_27" = "1 Cada envio de avatar dinâmico deduz %@ moedas. Verifique seu saldo.\n2 Revisão: Após o envio, o sistema entrará em revisão. Não envie novamente para não atrasar.\n3 Resultado: \nAprovado: Seu avatar será exibido.\nReprovado: As moedas serão reembolsadas e você será notificado.\n4 Operação irreversível: Após a aprovação, não é possível reverter."; "20.20.51_text_28" = "Horário da Visita: %@"; "20.20.51_text_29" = "O número de diamantes precisa ser múltiplo de %@"; +"20.20.51_text_30" = "A duração do vídeo não pode exceder 10 segundos."; + "20.20.56_text_1" = "Número atual de correspondências insuficiente, falha na correspondência. Tentar novamente?"; "20.20.56_text_2" = "Falha na correspondência, as moedas gastas foram devolvidas à sua carteira."; "20.20.56_text_3" = "Mudar Relacionamento"; diff --git a/YuMi/ru.lproj/Localizable.strings b/YuMi/ru.lproj/Localizable.strings index 39af0619..6611d610 100644 --- a/YuMi/ru.lproj/Localizable.strings +++ b/YuMi/ru.lproj/Localizable.strings @@ -3930,6 +3930,7 @@ "20.20.51_text_27" = "1 Каждый раз, когда вы загружаете динамический аватар, система списывает %@ монет с вашего аккаунта. Пожалуйста, убедитесь, что баланс вашего аккаунта достаточен.\n2 Процесс проверки: После завершения загрузки система автоматически переходит в процесс проверки. В это время не загружайте новый аватар, чтобы не повлиять на прогресс проверки.\n3 Результаты проверки:\nПроверка пройдена: Ваш новый динамический аватар вступит в силу немедленно и будет отображаться другим пользователям.\nПроверка не пройдена: После завершения проверки система автоматически вернет вам потраченные %@ монеты. В то же время вы получите системное уведомление.\n4 Нереверсивная операция: Пожалуйста, обратите внимание, что после проверки и вступления в силу динамический аватар вы не сможете восстановить предыдущий аватар.\n"; "20.20.51_text_28" = "Время просмотра: %@"; "20.20.51_text_29" = "Количество алмазов должно быть кратно 1000"; +"20.20.51_text_30" = "Продолжительность видео не должна превышать 10 секунд."; "20.20.56_text_1" = "Текущее количество матчей недостаточно, матч не удался. Сыграть снова?"; "20.20.56_text_2" = "Матч не удался, потраченные вами монеты возвращены в Кошелёк"; diff --git a/YuMi/tr.lproj/Localizable.strings b/YuMi/tr.lproj/Localizable.strings index 986ffda1..c5b9de1a 100644 --- a/YuMi/tr.lproj/Localizable.strings +++ b/YuMi/tr.lproj/Localizable.strings @@ -3727,6 +3727,7 @@ "20.20.51_text_27" = "1 Her dinamik avatar yüklediğinizde, sistem hesabınızdan %@ jeton düşecektir. Lütfen hesap bakiyenizin yeterli olduğundan emin olun.\n2 İnceleme süreci: Yükleme tamamlandıktan sonra, sistem otomatik olarak inceleme sürecine girecektir. Bu süre zarfında, inceleme ilerlemesini etkilememek için lütfen tekrar yeni bir avatar yüklemeyin.\n3 İnceleme sonuçları: \nİnceleme geçti: Yeni dinamik avatarınız hemen yürürlüğe girecek ve diğer kullanıcılara gösterilecektir.\nİnceleme başarısız oldu: Sistem, inceleme tamamlandıktan sonra harcadığınız %@ jetonu otomatik olarak iade edecektir. Aynı zamanda, bir sistem bildirimi alacaksınız.\n4 Geri alınamaz işlem: Lütfen dinamik avatar incelendikten ve yürürlüğe girdikten sonra, onu önceki avatarınıza geri yükleyemeyeceğinizi unutmayın.\n"; "20.20.51_text_28" = "Görüntüleme Süresi: %@"; "20.20.51_text_29" = "Elmas sayısının %@ katları olması gerekir"; +"20.20.51_text_30" = "Video süresi 10 saniyeyi geçemez."; "20.20.56_text_1" = "Mevcut eşleşme sayısı yeterli değil, eşleşme başarısız oldu. Tekrar eşleşelim mi?"; "20.20.56_text_2" = "Eşleşme başarısız oldu, harcadığınız jetonlar cüzdanınıza iade edildi"; diff --git a/YuMi/uz-UZ.lproj/Localizable.strings b/YuMi/uz-UZ.lproj/Localizable.strings index ccbeac3d..cc5b050a 100644 --- a/YuMi/uz-UZ.lproj/Localizable.strings +++ b/YuMi/uz-UZ.lproj/Localizable.strings @@ -3901,6 +3901,7 @@ Tasdiqlangandan so'ng, sekretar sizga uni chop etishda yordam beradi va sizni xa "20.20.51_text_27" = "1 Har safar dinamik avatar yuklanganda, tizim hisobingizdan %@ tanga ayirib oladi. Iltimos, hisobingizning balansi etarli ekanligiga ishonch hosil qiling.\n2 Tekshirish jarayoni: Yuklash tugagandan so'ng, tizim avtomatik ravishda tekshirish jarayoniga kiradi. Bu vaqt ichida, qayta tekshirish jarayoniga ta'sir qilmaslik uchun, yangi avatarni yana yuklamang.\n3 Tekshirish natijalari: \nTekshiruv muvaffaqiyatli: Yangi dinamik avatariz darhol kuchga kiradi va boshqa foydalanuvchilarga ko'rsatiladi.\nTekshiruv muvaffaqiyatsiz: Tekshiruv tugagandan so'ng, tizim sarflangan %@ tangalarni avtomatik ravishda qaytaradi. Shu bilan birga, siz tizim xabarnomasini olasiz.\n4 Qaytarilmaydigan operatsiya: E'tibor bering, dinamik avatar tekshirib olingan va kuchga kiritilganidan keyin, uni oldingi avatarga qaytarib bo'lmaydi.\n"; "20.20.51_text_28" = "Ko'rish vaqti: %@"; "20.20.51_text_29" = "Almazlar soni 1000 ning multiplei bo'lishi kerak"; +"20.20.51_text_30" = "Video davomiyligi 10 soniyadan oshmasligi kerak."; "20.20.56_text_1" = "Joriy mosliklar soni etarli emas, moslik muvaffaqiyatsiz tugadi. Qayta moslashasizmi?"; "20.20.56_text_2" = "Moslik muvaffaqiyatsiz tugadi, sarflangan tangalar hamyoningizga qaytarildi"; diff --git a/YuMi/zh-Hant.lproj/Localizable.strings b/YuMi/zh-Hant.lproj/Localizable.strings index 32e3f62d..99a65b67 100644 --- a/YuMi/zh-Hant.lproj/Localizable.strings +++ b/YuMi/zh-Hant.lproj/Localizable.strings @@ -3597,6 +3597,7 @@ "20.20.51_text_27" = "1 每次上傳動態頭像,系統都會從您的帳戶中扣除%@金幣。請確保您的帳戶餘額充足。\n2 審核流程:上傳完成後,系統自動進入審核流程。在此期間,請勿再次上傳新頭像,以免影響審核進度。\n3 審核結果: \n審核通過:您的新動態頭像將立即生效並顯示給其他使用者。\n審核失敗:審核完成後系統將自動退還您花費的%@金幣。同時,您也會收到系統通知。\n4 不可逆操作:請注意,動態頭像一旦審核並生效,將無法恢復為先前的頭像。\n"; "20.20.51_text_28" = "访客時間:%@"; "20.20.51_text_29" = "鑽石數量需要是 %@ 的倍數"; +"20.20.51_text_30" = "視頻時長不能超過 10 秒"; "20.20.56_text_1" = "目前的匹配次數不足,匹配失敗。再次匹配?"; "20.20.56_text_2" = "匹配失敗,您消耗的硬幣已返回您的錢包"; diff --git a/current_user_mic_switch_flow.md b/current_user_mic_switch_flow.md deleted file mode 100644 index 3b20eb7a..00000000 --- a/current_user_mic_switch_flow.md +++ /dev/null @@ -1,98 +0,0 @@ -# 当前用户切换 mic 时云信消息发送流程 - -## 修复后的完整流程 - -``` -1. 用户切换 mic (位置A → 位置B) - ↓ -2. 接收云信通知 NIMChatroomEventTypeQueueChange - - 下麦通知 (changeType == 2) - - 上麦通知 (changeType == 1) - ↓ -3. 调用 handleMicChangeForCP:queue - ↓ -4. 在 handleMicChangeForCP 中执行: - a) updateCurrentUserMicStatus:queue - - 检测到麦位变化 - - 设置 currentUserMicStatusChanged = YES - b) updateMicMidpointRectManagerSnapshot - c) handleDownMicEventIfNeeded:queue - d) handleMicSwitchScenarioIfNeeded:queue - - 检测到 currentUserMicStatusChanged = YES - - 清除所有CP关系 - - 重新构建CP关系 - - 🔧 不重置状态标志(关键修复) - e) callMicCpListByUidListOnMicChangeWithQueue:queue - - 调用 micCpListByUidList API - ↓ -5. API 成功回调 getMicCpListByUidListSuccess:cpList - ↓ -6. 在 getMicCpListByUidListSuccess 中: - a) 更新 CP 缓存 - b) 刷新绘制 - c) 检查 currentUserMicStatusChanged = YES - d) 🔧 发送云信消息 sendMicRelationshipNIMessage:cpList - e) 重置状态标志 currentUserMicStatusChanged = NO - ↓ -7. 其他用户收到云信消息,更新CP关系 -``` - -## 关键修复点 - -### 修复前的问题 -- `handleMicSwitchScenarioIfNeeded` 中提前重置 `currentUserMicStatusChanged = NO` -- API 成功回调时状态标志已经是 `NO` -- 无法发送云信消息 - -### 修复后的逻辑 -- `handleMicSwitchScenarioIfNeeded` 中不重置状态标志 -- 状态标志保持 `YES` 直到 API 成功回调 -- API 成功回调时正确发送云信消息 -- 发送消息后重置状态标志 - -## 代码修改 - -### 修改前 -```objc -// 在 handleMicSwitchScenarioIfNeeded 中 -if (hasMicPositionChanged) { - // 处理麦位变化场景 - [midpointRectManager removeAllMidpointRects]; - [midpointRectManager rebuildMicSnapshotWithStageView:self.stageView micCount:micCount]; - [self drawSocialStageMidpointRects]; - - // ❌ 提前重置状态标志 - self.currentUserMicStatusChanged = NO; -} -``` - -### 修改后 -```objc -// 在 handleMicSwitchScenarioIfNeeded 中 -if (hasMicPositionChanged) { - // 处理麦位变化场景 - [midpointRectManager removeAllMidpointRects]; - [midpointRectManager rebuildMicSnapshotWithStageView:self.stageView micCount:micCount]; - [self drawSocialStageMidpointRects]; - - // ✅ 不在这里重置状态标志,等待API成功回调后再重置 - // 状态标志将在 getMicCpListByUidListSuccess 中重置,确保能发送云信消息 -} -``` - -## 验证要点 - -1. **当前用户切换mic时**: - - ✅ 正确检测到麦位状态变化 - - ✅ 重新构建所有CP关系 - - ✅ 调用 micCpListByUidList API - - ✅ API成功回调时发送云信消息 - - ✅ 状态标志在发送消息后正确重置 - -2. **其他用户切换mic时**: - - ✅ 通过 handleOtherUserMicChange 处理 - - ✅ 不发送云信消息(由切换用户发送) - -3. **边界情况**: - - ✅ 当前用户不在麦上时清理CP数据 - - ✅ 只有当前用户一个人时清理CP数据