跳至主要内容

組合式訊息原語

自訂渲染器讓你完全接管一則訊息怎麼畫。但多數情況下你想換的只是 內容,不是版面——滿寬的 bot 文字、靠右的 user 泡泡、時間戳的格式與主題色,這些都應該照舊。

為此 SDK 把組成預設訊息列的原語都外露了,你可以直接拿來組。

組合式訊息原語

想自訂訊息列的內容、又不想重刻 SDK 的版面(滿寬 bot 文字、靠右 user 泡泡、時間戳格式與主題色)時,可以直接組合外露的原語:TemplateBox、TemplateBoxContent、BotMessageText、UserMessageText、Time。搭配 renderMessageContent 使用,未命中的訊息呼叫 renderDefaultContent() 回退預設。

import {
  TemplateBox, TemplateBoxContent,
  BotMessageText, UserMessageText, Time,
} from '@asgard-js/react';

<Chatbot
  renderMessageContent={({ message, renderDefaultContent }) => {
    if (message.type === 'user') {
      return (
        <TemplateBox type="user" direction="horizontal">
          <UserMessageText>{/* 你的內容 */}</UserMessageText>
          <Time time={message.time} />
        </TemplateBox>
      );
    }
    return renderDefaultContent();
  }}
/>

兩個模式的版面應完全一致——差別只在自組模式把 user 訊息開頭的提及字串換成 chip。這正是這些原語存在的目的:換內容、不換版面。

聊天機器人載入中…

原語一覽

原語作用
TemplateBox訊息列的外框,決定對齊與方向(type: 'user' | 'bot'
TemplateBoxContentbot 列的內容容器,負責快速回覆與訊息操作
BotMessageTextbot 的文字本體,含 Markdown 渲染與主題色
UserMessageTextuser 的文字泡泡
Time時間戳,套用 template.time.style 的格式與主題色

用法

搭配 renderMessageContent沒命中的訊息呼叫 renderDefaultContent() 回退預設

import {
TemplateBox,
TemplateBoxContent,
BotMessageText,
UserMessageText,
Time,
} from "@asgard-js/react";
import { MessageTemplateType } from "@asgard-js/core";

<Chatbot
renderMessageContent={({ message, renderDefaultContent }) => {
// user 列:把開頭的提及字串換成 chip,其餘照舊
if (message.type === "user" && message.text.startsWith(MENTION)) {
return (
<TemplateBox type="user" direction="horizontal">
<UserMessageText>
<span className="mention-chip">{MENTION}</span>
{message.text.slice(MENTION.length)}
</UserMessageText>
<Time time={message.time} />
</TemplateBox>
);
}

// bot 文字列
if (message.type === "bot") {
const template = message.message?.template;
const isText = template?.type === MessageTemplateType.TEXT || !template?.type;
const text = message.isTyping ? message.typingText : message.message?.text;

if (isText && text) {
return (
<TemplateBox type="bot" direction="horizontal">
<TemplateBoxContent
message={message}
quickReplies={template?.quickReplies}
references={template?.references}
>
<BotMessageText>{text}</BotMessageText>
</TemplateBoxContent>
</TemplateBox>
);
}
}

return renderDefaultContent();
}}
/>

串流中的文字

message.isTyping 為真時要讀 message.typingText 而不是 message.message.text—— 後者要等訊息完成才有值。上面的範例已經處理了這件事。

為什麼不直接自己刻

自己刻的話,這些會跟著跑掉,而且會在 SDK 改版時繼續跑掉:

  • bot 文字是滿寬無泡泡的,user 才是泡泡——兩者版面規則不同
  • 時間戳的格式與顏色來自主題設定,不是寫死的
  • TemplateBoxContent 順帶處理快速回覆與訊息操作列的位置

換句話說:換內容,不換版面

ChatHeader

同樣的想法也適用於標題列。ChatHeader 已外露,可搭配 renderHeader 使用;若只想換標題區 而保留其餘結構,用 renderTitle 即可。詳見自訂 Header

也看看