修复多弹窗返回原任务失败bug 2505/1 2505/head 2506/target/1
authorxue <2144439972@qq.com>
Tue, 14 Oct 2025 08:59:02 +0000 (16:59 +0800)
committerxue <2144439972@qq.com>
Tue, 14 Oct 2025 08:59:02 +0000 (16:59 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdMainView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdReminderView.cpp

index ec2c620..2872f59 100644 (file)
@@ -594,9 +594,12 @@ namespace OHOS
            ThunderBirdModel::GetInstance()->HighFrequence();
         }
         // OTA界面已独立为slice,不再需要此检查
-        // 保存上一级视图信息
-        prevView_ = currentView_;
-        prevSubView_ = currentSubView_;
+        // 保存上一级视图信息(如果是GoBackToPreviousView调用,则不更新prevView_和prevSubView_)
+        if (!isGoingBack_)
+        {
+            prevView_ = currentView_;
+            prevSubView_ = currentSubView_;
+        }
         ClickFunc(showView);
         group[showView]->SetVisible(true);
         group[showView]->SetStyle(STYLE_BACKGROUND_OPA, 0x00);
@@ -676,10 +679,15 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ThunderBirdMainView::GoBackToPreviousView: prevView_=%d, prevSubView_=%d, currentView_=%d, currentSubView_=%d", 
                      prevView_, prevSubView_, currentView_, currentSubView_);
         
+        // 设置标志位,防止在ChangeView中更新prevView_和prevSubView_
+        isGoingBack_ = true;
         
         // 跳转到上一个界面
         ChangeView(currentView_, prevView_, prevSubView_);
         
+        // 重置标志位
+        isGoingBack_ = false;
+        
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ThunderBirdMainView::GoBackToPreviousView: Successfully returned to previous view");
         return true;
     }
index d812f60..f805823 100644 (file)
@@ -36,6 +36,8 @@
 #include "cJSON.h"
 #include "font/ui_font.h"
 #include "ln_api.h"
+#include <unistd.h>
+#include "vibrator_service.h"
  #define JUHEPINGTAI 0
  #if JUHEPINGTAI
  #include "websocket_server_manager.h"
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置对话文本: textId is null");
             return;
         }
-         // 添加文本内容
-         m_currentTimeStr = textId;
-         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置对话文本: %s", m_currentTimeStr.c_str());
-         int16_t currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
-         int16_t currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
-        if(ThunderBirdDialogueView::GetInstance() && currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)
-            ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(m_currentTimeStr.c_str());
-        if(ThunderBirdLullabyView::GetInstance() && currentSubView == ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4)
-            ThunderBirdLullabyView::GetInstance()->UpdateLullabyText(m_currentTimeStr.c_str());
-            //清除录音内容
-        ClearTextStr();
+        
+        // 检查是否有文本正在处理中
+        if (!m_hasTextProcessing) {
+            // 第一个文本:直接显示,设置处理标志
+            m_hasTextProcessing = true;
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "第一个文本直接显示: %s", textId);
+            
+            // 获取当前视图状态
+            int16_t currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
+            int16_t currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+            
+            // 直接推送到对话界面
+            if(ThunderBirdDialogueView::GetInstance() && currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)
+            {
+                ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(textId);
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "第一个文本直接显示在对话界面: %s", textId);
+            }
+            
+            // 不入队,避免重复显示
+        } else {
+            // 非第一个文本,加入队列等待音频开始播放时同步出队
+            EnqueueAudioText(textId);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "文本入队,等待音频开始播放: %s", textId);
+        }
      }
        
      
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleScheduleReminder");
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Title: %s", title ? title : "NULL");
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Content: %s", content ? content : "NULL");
-        
+        // 震动提醒
+        custom_VibratorFunc_int(0);
         // 示例:通过图形服务显示提醒
         if (title && content) {
             // 可以在这里调用UI相关的显示逻辑
             if (ThunderBirdMainView::GetInstance()) {
                 int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
-                ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_REMINDERVIEW, ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER);
+                int currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+                //如果当前界面是事项提醒界面,则不进行切换,防止返回原任务进入循环
+                if(currentView != THUNDERBIRD_REMINDERVIEW && currentSubView != ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER)
+                {
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_REMINDERVIEW, ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER);
+                }
+                
                 
                 // 更新任务提醒的文本内容
                 if (ThunderBirdReminderView::GetInstance()) {
         uapi_set_screen_on_api(); // 亮屏
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleTaskReminder");
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ScheduleName: %s", scheduleName ? scheduleName : "NULL");
-        
+        // 震动提醒
+        custom_VibratorFunc_int(0);
         // 这里可以添加具体的任务提醒处理逻辑
         // 例如:显示任务提醒界面、播放提醒音、更新任务列表等
         
             // 可以在这里调用UI相关的显示逻辑
             if (ThunderBirdMainView::GetInstance()) {
                 int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
-                ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_REMINDERVIEW, ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER);
-                
+                int currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+               //如果当前界面是事项提醒界面,则不进行切换,防止返回原任务进入循环
+               if(currentView != THUNDERBIRD_REMINDERVIEW && currentSubView != ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER)
+               {
+                   ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_REMINDERVIEW, ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_TASK_REMINDER);
+               }
                 // 更新任务提醒的文本内容
                 if (ThunderBirdReminderView::GetInstance()) {
                     ThunderBirdReminderView::GetInstance()->UpdateTaskReminderText(scheduleName,nullptr);
         NativeAbility::GetInstance().ChangeSlice(VIEW_OTA);
     }
 
+    void ThunderBirdModel::HandleAudioPlaybackStart()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackStart");
+        // 音频开始播放时,从队列中取出对应的文本并推送
+        DequeueAndPushAudioText();
+    }
+
     void ThunderBirdModel::HandleAudioPlaybackEnd()
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackEnd");
         {
             ThunderBirdDialogueView::GetInstance()->AudioPlaybackEnd();
         }
+        
+        // 重置文本处理标志,允许下一轮对话的第一个文本直接显示
+        m_hasTextProcessing = false;
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "音频播放结束,重置文本处理标志");
+    }
+    
+    // NPC表情变化处理函数
+    void ThunderBirdModel::HandleNpcEmotionChange(const char* emotion)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleNpcEmotionChange: %s", emotion ? emotion : "NULL");
+        
+        if (emotion == nullptr || strlen(emotion) == 0) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleNpcEmotionChange: emotion is null or empty");
+            return;
+        }
+        
+        //判断对话界面当前表情
+        
+        // 获取当前视图状态
+        int16_t currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
+        int16_t currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+        
+        // 如果当前在对话界面,更新表情显示
+        if(ThunderBirdDialogueView::GetInstance() && currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)
+        {
+            // 这里可以调用对话界面的表情更新函数
+             // 更新当前表情状态
+             //ThunderBirdMainView::SwitchVideo(emotion);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "NPC表情已更新: %s", emotion);
+        }
     }
     
     // 设置当前表情状态
         if(screenImageAsEmoji_ == false)
         {
             //获取当前角色配置
+            //为默认表情
+            if(eyesColor_.empty() == true || eyesShape_.empty() == true)
+            {
+                std::string expressionPath = "/user/res/video/Default/"+ m_currentExpression + ".mp4";
+                SwitchExpressionVideo(expressionPath.c_str());
+            }
+            else
+            {
+                std::string expressionPath = "/user/userdata/leiniao/emoji/" + eyesShape_ + "/" + eyesColor_ + "/" + m_currentExpression + ".mp4";
+                //判断表情文件是否存在
+                if(access(expressionPath.c_str(), F_OK) != -1)
+                {
+                    SwitchExpressionVideo(expressionPath.c_str());
+                }
+                else
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::not find expression file %s", m_currentExpression.c_str());
+                }
+            }
             
-            std::string expressionPath = "/user/res/video/Default/" + eyesShape_ + "/" + eyesColor_ + "/" + m_currentExpression + ".mp4";
-            //std::string expressionPath = "/user/res/video/Default/" + m_currentExpression + ".mp4";
-            SwitchExpressionVideo(expressionPath.c_str());
         }
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::SetCurrentExpressionAndStatus: expression=%s, statusText=%s", 
             m_currentExpression.c_str(), m_currentStatusText.c_str());
        return m_currentFps;
    }
 
+   // 将文本加入队列
+   void ThunderBirdModel::EnqueueAudioText(const std::string& text)
+   {
+       std::lock_guard<std::mutex> lock(m_textQueueMutex);
+       m_audioTextQueue.push(text);
+       WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::EnqueueAudioText: 文本入队: %s, 队列大小: %zu", 
+                     text.c_str(), m_audioTextQueue.size());
+   }
+
+   // 从队列中取出文本并推送
+   void ThunderBirdModel::DequeueAndPushAudioText()
+   {
+       std::lock_guard<std::mutex> lock(m_textQueueMutex);
+       
+       if (m_audioTextQueue.empty()) {
+           WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::DequeueAndPushAudioText: 队列为空,没有文本可推送");
+           return;
+       }
+       
+       std::string text = m_audioTextQueue.front();
+       m_audioTextQueue.pop();
+       
+       WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::DequeueAndPushAudioText: 推送文本: %s, 剩余队列大小: %zu", 
+                     text.c_str(), m_audioTextQueue.size());
+       
+       // 获取当前视图状态
+       int16_t currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
+       int16_t currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
+       
+       // 推送到对话界面
+       if(ThunderBirdDialogueView::GetInstance() && currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING)
+       {
+           ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(text.c_str());
+           WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "音频开始播放,显示对话文本: %s", text.c_str());
+       }
+       
+       // 推送到哄睡界面
+       if(ThunderBirdLullabyView::GetInstance() && currentSubView == ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4)
+       {
+           ThunderBirdLullabyView::GetInstance()->UpdateLullabyText(text.c_str());
+           WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "音频开始播放,显示哄睡文本: %s", text.c_str());
+       }
+   }
+
+   // 检查队列中是否有文本
+   bool ThunderBirdModel::HasAudioTextInQueue()
+   {
+       std::lock_guard<std::mutex> lock(m_textQueueMutex);
+       return !m_audioTextQueue.empty();
+   }
+
+   // 清空音频文本队列
+   void ThunderBirdModel::ClearAudioTextQueue()
+   {
+       std::lock_guard<std::mutex> lock(m_textQueueMutex);
+       while (!m_audioTextQueue.empty()) {
+           m_audioTextQueue.pop();
+       }
+       WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::ClearAudioTextQueue: 音频文本队列已清空");
+   }
+
 
 }
  
\ No newline at end of file
index b8a17d5..d1b7856 100644 (file)
@@ -28,6 +28,7 @@
 #include "graphic_service.h"
 #include "ln_api.h"
 #include "power_display_service.h"
+#include "ai_media.h"
 #ifdef __cplusplus
     extern "C"
     {
@@ -354,6 +355,8 @@ namespace OHOS
             ThunderBirdModel::GetInstance()->StopCountUpTimer();
             ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING);
             ln_ws_end_audio_chat();
+            //清空音频文本队列
+            ThunderBirdModel::GetInstance()->ClearAudioTextQueue();
         } else {
             // 开始录音
             ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
@@ -638,29 +641,38 @@ namespace OHOS
      */
     void ThunderBirdPresenter::HandleFuncKeyLongPress(void)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ThunderBirdPresenter::HandleFuncKeyLongPress - FUNC key long press detected");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdPresenter::HandleFuncKeyLongPress - FUNC key long press detected");
         // 长按FUNC键2秒的处理逻辑
         // 触发对话模式切换
         if (ThunderBirdMainView::GetInstance()) {
             int16_t currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
             int16_t currentSubView = ThunderBirdMainView::GetInstance()->GetCurrentSubView();
             
-            if(currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW)
+            if(currentView == THUNDERBIRD_DIALOGUEVIEW && currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW)
             {
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
                 isDialogueing = true;
                 ln_ws_start_audio_chat(LN_AUDIO_CHAT_VOICE_CHAT_REQUEST);//开始对话
             }
-            else
+            else if(currentView == THUNDERBIRD_DIALOGUEVIEW)
             {
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW);
                 if(currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING)
                 {
                     ThunderBirdModel::GetInstance()->StopCountUpTimer();
                 }
+                // 停止实际的音频播放
+                ai_media_play_stop();
+                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ThunderBirdDialogueView::AudioPlaybackEnd: Stopped audio playback");
                 ln_ws_end_audio_chat();//结束对话
                 isDialogueing = false;
             }
+            //当为故事模式
+            else if(currentView = THUNDERBIRD_LULLABYVIEW && currentSubView == ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdPresenter::HandleFuncKeyLongPress");
+                ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_LULLABYVIEW, ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_5);
+            }
         }
     }
 
index 00904fa..c14ab40 100644 (file)
@@ -161,7 +161,7 @@ namespace OHOS
                 // 文本位置:图标右侧,紧挨着
                 TextLabel->SetPosition(96, 64, 300, 42);
                 TextLabel->SetText("11点了该睡觉了");
-                TextLabel->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); // 左对齐,因为已经整体居中了
+                TextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); // 左对齐,因为已经整体居中了
                 TextLabel->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); 
                 TextLabel->SetRollSpeed(35);
                 TextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
@@ -172,7 +172,7 @@ namespace OHOS
                 // 黑色文本:位置比白色文本偏移2像素
                 TextLabel_Y->SetPosition(98, 66, 300, 42);
                 TextLabel_Y->SetText("11点了该睡觉了");
-                TextLabel_Y->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
+                TextLabel_Y->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
                 TextLabel_Y->SetStyle(STYLE_TEXT_COLOR, 0xff000000);
                 TextLabel_Y->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); 
                 TextLabel_Y->SetRollSpeed(35);