void ClearAll(void);
void Show(int16_t showView);
void UpdateDialogueText(const char *text);
+ void AudioPlaybackEnd();
enum : int16_t {
THUNDERBIRD_DIALOGUEVIEW_SPEAKING = 0, // 说话中
MediaVideoPlay *videoPlay_ = nullptr;
UIImageView *batteryimage{nullptr}; // 电池图片
UILabel *batteryLabel{nullptr}; // 电池电量
+ UILabel *batteryLabelBlack{nullptr}; // 黑色电量组件
UIBoxProgress *progress{nullptr}; // 电池进度条
UIImageView *chargeBatteryicon{nullptr}; // 充电图标
bool isChargeBatteryIconVisible{false}; // 充电图标是否可见
UIViewGroup *group1{nullptr};
UILabelExt *timeLabel{nullptr};
+ UILabelExt *timeLabelBlack{nullptr}; // 黑色时间组件
UIImageView *showSignalStrength[4]{nullptr}; // 信号强度
UIImageView *NoSignal{nullptr}; // 无信号
// 对话文本管理函数
std::string GetTextStr();
- void SetTextStr(const char *textId);
+ void SetTextStr(char *textId);
void ClearTextStr();
size_t GetTextLength() const;
bool IsTextEmpty() const;
// 恢复视频帧率
void HighFrequence();
+ // 音频播放结束处理函数
+ void HandleAudioPlaybackEnd();
+
void at_set_fps(uint32_t freq);
uint32_t at_get_fps(void);
// 任务提醒文本更新接口(用于 THUNDERBIRD_REMINDERVIEW_TASK_REMINDER)
void UpdateTaskReminderText(const char* title, const char* content);
void UpdateTaskReminderText(const char* text);
-
+ void UpdateTaskReminderIcon(const char* icon);
+
enum : int16_t {
THUNDERBIRD_REMINDERVIEW_VOLUME = 0, // 音量调节
THUNDERBIRD_REMINDERVIEW_TASK_REMINDER, // 事项提醒
TextLabel->SetText(text);
TextLabel_Y->SetText(text);
}
+
+ void ThunderBirdDialogueView::AudioPlaybackEnd()
+ {
+ if(!TextLabel || !TextLabel_Y) return;
+ TextLabel->SetText("");
+ TextLabel_Y->SetText("");
+ if(speakAnimator) {speakAnimator->Stop();}
+ }
}
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdLullabyView::Show: THUNDERBIRD_LULLABYVIEW_4");
//长亮屏
ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
- //ThunderBirdModel::GetInstance()->StartCountUpTimer(15 * 60);
if (TextLabel)
{
TextLabel->SetPosition(0, 64, 360, 42);
- //TextLabel->SetText("从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?");
TextLabel->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE);
TextLabel->SetRollSpeed(35);
TextLabel->SetVisible(true);
if (TextLabel_Y)
{
TextLabel_Y->SetPosition(2, 66, 360, 42);
- //TextLabel_Y->SetText("从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?从前有座山,山里有座庙,庙里有个老和尚,老和尚给小和尚讲故事,讲什么呢?");
TextLabel_Y->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE);
+ TextLabel_Y->SetStyle(STYLE_TEXT_COLOR, 0xff000000);
TextLabel_Y->SetRollSpeed(35);
TextLabel_Y->SetVisible(true);
}
delete timeLabel;
timeLabel = nullptr;
}
+ if (timeLabelBlack != nullptr)
+ {
+ delete timeLabelBlack;
+ timeLabelBlack = nullptr;
+ }
for (int i = 0; i < 4; i++)
{
if (showSignalStrength[i] != nullptr)
delete batteryLabel;
batteryLabel = nullptr;
}
+ if (batteryLabelBlack != nullptr)
+ {
+ delete batteryLabelBlack;
+ batteryLabelBlack = nullptr;
+ }
if (progress != nullptr)
{
delete progress;
timeLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 24);
timeLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
timeLabel->SetVisible(true);
+ // 先创建黑色时间组件(作为背景)
+ timeLabelBlack = new UILabelExt();
+ if (timeLabelBlack == nullptr)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "timeLabelBlack new fail");
+ return nullptr;
+ }
+ timeLabelBlack->SetPosition(2, 6, 60, 33); // 位置偏移+2
+ timeLabelBlack->SetViewId("timeLabelBlack");
+ timeLabelBlack->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 24);
+ timeLabelBlack->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+ timeLabelBlack->SetStyle(STYLE_TEXT_COLOR, Color::Black().full); // 黑色
+ timeLabelBlack->SetVisible(true);
+ timeLabelBlack->SetText(ThunderBirdModel::GetInstance()->GetCurrentTimeStr().c_str()); // 每秒变化
+ group1->Add(timeLabelBlack);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "timeLabelBlack add success - Position: (2,6) Size: (60,33) Color: Black");
+
+ // 再创建白色时间组件(作为前景)
timeLabel->SetText(ThunderBirdModel::GetInstance()->GetCurrentTimeStr().c_str()); // 每秒变化
group1->Add(timeLabel);
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "timeLabel add success");
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "batteryLabel new fail");
return nullptr;
}
- batteryLabel->SetPosition(batteryimage->GetX() + 35, (group1->GetHeight() - 14) / 2, 30, 30);
+ batteryLabel->SetPosition(batteryimage->GetX() + 35, (group1->GetHeight() - 14) / 2-2, 32, 30);
batteryLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 15);
+ // 先创建黑色电量组件(作为背景)
+ batteryLabelBlack = new UILabel();
+ if (batteryLabelBlack == nullptr)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "batteryLabelBlack new fail");
+ return nullptr;
+ }
+ batteryLabelBlack->SetPosition(batteryimage->GetX() + 37, (group1->GetHeight() - 14) / 2 , 32, 30); // 位置偏移+2
+ batteryLabelBlack->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 15);
+ batteryLabelBlack->SetText("100");
+ batteryLabelBlack->SetStyle(STYLE_TEXT_COLOR, Color::Black().full); // 黑色
+ batteryLabelBlack->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_LEFT);
+ group1->Add(batteryLabelBlack);
+
+ // 再创建白色电量组件(作为前景)
batteryLabel->SetText("100");
batteryLabel->SetStyle(STYLE_TEXT_COLOR, Color::White().full);
batteryLabel->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_LEFT);
void ThunderBirdMainView::UpdateTimeText(const char *time)
{
timeLabel->SetText(time); // 每秒变化
+ if (timeLabelBlack != nullptr) {
+ timeLabelBlack->SetText(time); // 同时更新黑色时间组件
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "UpdateTimeText: Updated black time component with: %s", time);
+ } else {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateTimeText: timeLabelBlack is null!");
+ }
}
void ThunderBirdMainView::updateSignalDisplay() // 信号接收
{
batteryLabel->SetText((std::to_string(static_cast<int>(Batteryvalue))).c_str()); // 电量
}
+ if (batteryLabelBlack)
+ {
+ batteryLabelBlack->SetText((std::to_string(static_cast<int>(Batteryvalue))).c_str()); // 同时更新黑色电量组件
+ }
if (progress)
{
progress->SetValue(Batteryvalue);
#include "NativeRegisterManager.h"
#include "graphic_service_wrapper.h"
#include "cJSON.h"
+#include "font/ui_font.h"
#define JUHEPINGTAI 0
#if JUHEPINGTAI
#include "websocket_server_manager.h"
// ==================== 对话文本管理函数 ====================
std::string ThunderBirdModel::GetTextStr()
{
- WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "获取对话文本: %s", m_currentTimeStr.c_str());
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "获取对话文本: %s", m_currentTimeStr.c_str());
return m_currentTimeStr;
}
+ static int32_t chat_filter_unsupported_chars(const char *input_str, char *output_str, uint32_t max_len)
+ {
+ if (input_str == NULL || output_str == NULL || max_len == 0)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid parameters for asr_filter_unsupported_chars\n");
+ return -1;
+ }
+
+ // 初始化输出缓冲区
+ memset(output_str, 0, max_len);
+
+ uint32_t input_len = strlen(input_str);
+ uint32_t output_pos = 0;
+ uint32_t input_pos = 0;
+
+ while (input_pos < input_len && output_pos < max_len - 1)
+ {
+ uint32_t char_start = input_pos;
+ uint32_t char_end = input_pos;
+
+ // 获取下一个UTF-8字符
+ uint32_t unicode_char = 0;
+ bool valid_utf8 = false;
+
+ // 简单的UTF-8解码
+ if ((unsigned char)input_str[input_pos] < 0x80)
+ {
+ // ASCII字符
+ unicode_char = (unsigned char)input_str[input_pos];
+ char_end = input_pos + 1;
+ valid_utf8 = true;
+ }
+ else if ((unsigned char)input_str[input_pos] >= 0xC0 && (unsigned char)input_str[input_pos] < 0xE0)
+ {
+ // 2字节UTF-8字符
+ if (input_pos + 1 < input_len)
+ {
+ unicode_char = ((unsigned char)input_str[input_pos] & 0x1F) << 6 |
+ ((unsigned char)input_str[input_pos + 1] & 0x3F);
+ char_end = input_pos + 2;
+ valid_utf8 = true;
+ }
+ }
+ else if ((unsigned char)input_str[input_pos] >= 0xE0 && (unsigned char)input_str[input_pos] < 0xF0)
+ {
+ // 3字节UTF-8字符
+ if (input_pos + 2 < input_len)
+ {
+ unicode_char = ((unsigned char)input_str[input_pos] & 0x0F) << 12 |
+ ((unsigned char)input_str[input_pos + 1] & 0x3F) << 6 |
+ ((unsigned char)input_str[input_pos + 2] & 0x3F);
+ char_end = input_pos + 3;
+ valid_utf8 = true;
+ }
+ }
+ else if ((unsigned char)input_str[input_pos] >= 0xF0 && (unsigned char)input_str[input_pos] < 0xF8)
+ {
+ // 4字节UTF-8字符
+ if (input_pos + 3 < input_len)
+ {
+ unicode_char = ((unsigned char)input_str[input_pos] & 0x07) << 18 |
+ ((unsigned char)input_str[input_pos + 1] & 0x3F) << 12 |
+ ((unsigned char)input_str[input_pos + 2] & 0x3F) << 6 |
+ ((unsigned char)input_str[input_pos + 3] & 0x3F);
+ char_end = input_pos + 4;
+ valid_utf8 = true;
+ }
+ }
+
+ if (!valid_utf8)
+ {
+ // 无效的UTF-8字符,跳过
+ input_pos++;
+ continue;
+ }
+
+ // 使用GetGlyphPathData接口检查字符是否可以在字体中显示
+ bool char_supported = true;
+
+ // 对于ASCII字符,直接支持
+ if (unicode_char < 0x80)
+ {
+ char_supported = true;
+ }
+ else
+ {
+ // 使用字体引擎检查字符是否支持
+ OHOS::UIFont *fontEngine = OHOS::UIFont::GetInstance();
+ if (fontEngine != NULL)
+ {
+ // 使用GetGlyphPathData检查字符是否支持
+ OHOS::GlyphPathData path;
+ if (!fontEngine->GetGlyphPathData(unicode_char, 0, path))
+ {
+ // 字符不支持,标记为不支持
+ char_supported = false;
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Character 0x%X not supported by font engine\n", unicode_char);
+ }
+ else
+ {
+ // 字符支持
+ char_supported = true;
+ }
+ }
+ else
+ {
+ // 字体引擎不可用,使用简化的字符范围检查
+ if (unicode_char >= 0x4E00 && unicode_char <= 0x9FFF)
+ {
+ // 中文字符范围
+ char_supported = true;
+ }
+ else if (unicode_char >= 0xAC00 && unicode_char <= 0xD7AF)
+ {
+ // 韩文字符范围
+ char_supported = true;
+ }
+ else if (unicode_char >= 0x3040 && unicode_char <= 0x309F)
+ {
+ // 平假名
+ char_supported = true;
+ }
+ else if (unicode_char >= 0x30A0 && unicode_char <= 0x30FF)
+ {
+ // 片假名
+ char_supported = true;
+ }
+ else if (unicode_char >= 0x2000 && unicode_char <= 0x206F)
+ {
+ // 标点符号
+ char_supported = true;
+ }
+ else
+ {
+ // 其他字符,标记为不支持
+ char_supported = false;
+ }
+ }
+ }
+
+ if (char_supported)
+ {
+ // 字符支持,复制到输出缓冲区
+ uint32_t char_len = char_end - char_start;
+ if (output_pos + char_len < max_len)
+ {
+ memcpy(&output_str[output_pos], &input_str[char_start], char_len);
+ output_pos += char_len;
+ }
+ else
+ {
+ break; // 输出缓冲区已满
+ }
+ }
+ else
+ {
+ // 字符不支持,跳过不支持的字符
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Unsupported character: 0x%X, skipping\n", unicode_char);
+ }
+
+ input_pos = char_end;
+ }
+
+ // 确保输出字符串以null结尾
+ output_str[output_pos] = '\0';
+
+ WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Filtered string: '%s' -> '%s' (length: %d)\n",
+ input_str, output_str, output_pos);
+
+ return output_pos;
+ }
+
+ /**
+ * @brief 过滤chat结果中的无法显示字符
+ * @param result chat识别结果字符串
+ * @return 过滤后的字符串长度,-1表示失败
+ */
+ static int32_t chat_filter_result_chars(char *result)
+ {
+ if (result == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " result string is NULL\n");
+ return -1;
+ }
+
+ uint32_t max_len = strlen(result) + 1;
+ char *temp_buffer = (char *)malloc(max_len);
+ if (temp_buffer == NULL)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to allocate memory for temp buffer\n");
+ return -1;
+ }
+
+ int32_t filtered_len = chat_filter_unsupported_chars(result, temp_buffer, max_len);
+ if (filtered_len >= 0)
+ {
+ strcpy(result, temp_buffer);
+ }
+
+ free(temp_buffer);
+ return filtered_len;
+ }
- void ThunderBirdModel::SetTextStr(const char *textId)
+ void ThunderBirdModel::SetTextStr(char *textId)
{
+ //chat_filter_result_chars(textId);
if (textId == nullptr) {
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置对话文本: textId is null");
return;
ThunderBirdMainView *view = ThunderBirdMainView::GetInstance();
if (view) {
std::string currentTime = GetCurrentTimeStr();
+ // 检查夜间更新状态(每天凌晨2点检查)
+ if(currentTime == "2:00")
+ {
+ // 从KV存储中读取夜间更新状态
+ char temp[10] = { 0 };
+ (void)UtilsGetValue("night_update_enabled", temp, 10);
+ if(strcmp(temp, "1") == 0)
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "检测到夜间更新已启用,切换到OTA slice");
+ // 切换到OTA slice
+ NativeAbility::GetInstance().SwitchSlice(VIEW_OTA);
+ }
+ }
view->UpdateTimeText(currentTime.c_str());
WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TimeDisplayCallback: %s", currentTime.c_str());
}
// 这里可以添加聊天体力更改的具体处理逻辑
if (ThunderBirdMainView::GetInstance()) {
int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
+ //更新充值二维码
+ if(ThunderBirdReminderView::GetInstance())
+ {
+ ThunderBirdReminderView::GetInstance()->UpdateTaskReminderIcon(qrcodeUrl);
+ }
if((chatLeft < 20 && chatLeft > 0))//对话不足
{
ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_REMINDERVIEW, ThunderBirdReminderView::THUNDERBIRD_REMINDERVIEW_DIALOGUE_NOT_ENOUGH);
NativeAbility::GetInstance().ChangeSlice(VIEW_OTA);
}
+ void ThunderBirdModel::HandleAudioPlaybackEnd()
+ {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackEnd");
+ if(ThunderBirdDialogueView::GetInstance())
+ {
+ ThunderBirdDialogueView::GetInstance()->AudioPlaybackEnd();
+ }
+ }
+
int ThunderBirdModel::GetDownloadFile()
{
return downloadFileType;
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateDialogueText:%s\n",dialogueText.c_str());
ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(dialogueText.c_str());
}
+ else{
+ //如果不是对话需要判断是否服务准备好
+ if(ThunderBirdModel::GetInstance()->Get_is_all_services_ready() == false)
+ ThunderBirdDialogueView::GetInstance()->UpdateDialogueText("等待网络连接");
+ else
+ ThunderBirdDialogueView::GetInstance()->UpdateDialogueText("网络连接成功");
+ }
+
+ }
+ }
+ //如果是哄睡界面 需要更新哄睡文本
+ if(currentView == THUNDERBIRD_LULLABYVIEW && currentSubView == ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4)
+ {
+ if(ThunderBirdLullabyView::GetInstance() != nullptr)
+ {
+ std::string lullabyText = ThunderBirdModel::GetInstance()->GetTextStr();
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateLullabyText:%s\n",lullabyText.c_str());
+ ThunderBirdLullabyView::GetInstance()->UpdateLullabyText(lullabyText.c_str());
}
}
}