feat: release chat and mindspace UI updates
This commit is contained in:
@@ -12,6 +12,38 @@ import type { CapabilityMap, ChatState, Message, PortalUser, Session, ToolConfir
|
||||
import type { MindSpaceSaveCategory } from '../types';
|
||||
|
||||
const MAX_PENDING_IMAGES = 6;
|
||||
const CHAT_PLACEHOLDER_PROMPTS = [
|
||||
'帮我写一篇温柔一点的小短文',
|
||||
'讲个轻松的笑话,让我换换脑子',
|
||||
'帮我看看今天的天气和出门建议',
|
||||
'规划一份周末城市漫游攻略',
|
||||
'把这组数据整理成一段分析结论',
|
||||
'帮我总结一份会议纪要或文档',
|
||||
'写一个有记忆点的产品介绍',
|
||||
'设计一个简单好玩的小游戏',
|
||||
'帮我做一份旅行行程和预算',
|
||||
'把一段想法改成更专业的表达',
|
||||
'给我起几个品牌名和一句 slogan',
|
||||
'帮我写一封礼貌但坚定的邮件',
|
||||
'整理一份学习计划和每日任务',
|
||||
'分析一个产品页面哪里可以优化',
|
||||
'把复杂概念讲得像聊天一样简单',
|
||||
'帮我生成一份短视频脚本',
|
||||
'写一段适合发朋友圈的文案',
|
||||
'帮我拆解一个商业想法是否可行',
|
||||
'把长文压缩成三条重点',
|
||||
'做一个活动策划和执行清单',
|
||||
'帮我准备一次面试的回答思路',
|
||||
'写一个网页或小工具的需求说明',
|
||||
'帮我把表格数据变成洞察报告',
|
||||
'给孩子讲一个睡前故事',
|
||||
'帮我规划一周健康饮食',
|
||||
'把这段话翻译得自然一点',
|
||||
'帮我做一份竞品对比',
|
||||
'给一个新功能设计使用流程',
|
||||
'帮我写一段代码并解释思路',
|
||||
'整理一个今天就能开始的行动计划',
|
||||
];
|
||||
|
||||
type PendingChatImage = {
|
||||
id: string;
|
||||
@@ -76,6 +108,9 @@ export function ChatPanel({
|
||||
const [uploadingImage, setUploadingImage] = useState(false);
|
||||
const [imageError, setImageError] = useState<string | null>(null);
|
||||
const [voiceStopSignal, setVoiceStopSignal] = useState(0);
|
||||
const [randomPrompt] = useState(
|
||||
() => CHAT_PLACEHOLDER_PROMPTS[Math.floor(Math.random() * CHAT_PLACEHOLDER_PROMPTS.length)],
|
||||
);
|
||||
const imageInputRef = useRef<HTMLInputElement>(null);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef(input);
|
||||
@@ -105,6 +140,7 @@ export function ChatPanel({
|
||||
const canPublish = Boolean(capabilities?.static_publish) || hasPublishSkill;
|
||||
const chatSkills = filterChatSkills(CHAT_SKILL_OPTIONS, { grantedSkills, canPublish });
|
||||
const compact = variant === 'compact';
|
||||
const showHomeWelcome = !compact && messages.length === 0;
|
||||
|
||||
const placeholder = offlineBlocked
|
||||
? '网络断开,恢复连接后可继续输入'
|
||||
@@ -112,7 +148,7 @@ export function ChatPanel({
|
||||
? '正在连接会话…'
|
||||
: compact
|
||||
? '在这里继续和 Agent 对话…'
|
||||
: '输入任务,例如:列出当前目录文件';
|
||||
: randomPrompt;
|
||||
|
||||
const mergeVoiceText = (spoken: string) => {
|
||||
const base = voiceBaseRef.current.trimEnd();
|
||||
@@ -321,7 +357,7 @@ export function ChatPanel({
|
||||
|
||||
return (
|
||||
<>
|
||||
<main className={compact ? 'space-chat-panel-body' : 'main'}>
|
||||
<main className={compact ? 'space-chat-panel-body' : `main${showHomeWelcome ? ' main-home' : ''}`}>
|
||||
<MessageList
|
||||
messages={messages}
|
||||
streaming={chatState === 'streaming'}
|
||||
@@ -329,6 +365,7 @@ export function ChatPanel({
|
||||
onSaveAsPage={(message) => setPageSource(message)}
|
||||
publishUserId={user?.id}
|
||||
publishUsername={user?.username}
|
||||
sessionId={session?.id}
|
||||
compact={compact}
|
||||
/>
|
||||
{!compact && (
|
||||
@@ -369,7 +406,7 @@ export function ChatPanel({
|
||||
/>
|
||||
)}
|
||||
|
||||
<footer className={compact ? 'space-chat-panel-footer' : 'footer'}>
|
||||
<footer className={compact ? 'space-chat-panel-footer' : `footer${showHomeWelcome ? ' footer-home' : ''}`}>
|
||||
{voiceNotice && (
|
||||
<div className="voice-notice" role="status">
|
||||
{voiceNotice}
|
||||
@@ -399,8 +436,8 @@ export function ChatPanel({
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="chat-input-row">
|
||||
<div className="chat-input-shell">
|
||||
<div className={`chat-input-row${showHomeWelcome ? ' chat-input-row-home' : ''}`}>
|
||||
<div className={`chat-input-shell${showHomeWelcome ? ' chat-input-shell-home' : ''}`}>
|
||||
{onUploadImage && (
|
||||
<>
|
||||
<button
|
||||
@@ -449,7 +486,7 @@ export function ChatPanel({
|
||||
stopSignal={voiceStopSignal}
|
||||
/>
|
||||
</div>
|
||||
{chatSkills.length > 0 && (
|
||||
{!showHomeWelcome && chatSkills.length > 0 && (
|
||||
<ChatSkillPicker
|
||||
skills={chatSkills}
|
||||
disabled={voiceDisabled}
|
||||
@@ -457,16 +494,18 @@ export function ChatPanel({
|
||||
onPrefill={setInput}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="chat-skill-trigger"
|
||||
title="Design Style Generator"
|
||||
disabled={voiceDisabled}
|
||||
onClick={() => setDesignPanelOpen(true)}
|
||||
>
|
||||
<DesignBtnIcon className="chat-skill-trigger-icon" />
|
||||
<span className="chat-skill-trigger-label">design</span>
|
||||
</button>
|
||||
{!showHomeWelcome && (
|
||||
<button
|
||||
type="button"
|
||||
className="chat-skill-trigger"
|
||||
title="Design Style Generator"
|
||||
disabled={voiceDisabled}
|
||||
onClick={() => setDesignPanelOpen(true)}
|
||||
>
|
||||
<DesignBtnIcon className="chat-skill-trigger-icon" />
|
||||
<span className="chat-skill-trigger-label">design</span>
|
||||
</button>
|
||||
)}
|
||||
{designPanelOpen && (
|
||||
<DesignSkillPanel
|
||||
onClose={() => setDesignPanelOpen(false)}
|
||||
@@ -483,7 +522,7 @@ export function ChatPanel({
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
className="send-btn chat-input-action"
|
||||
className={`send-btn chat-input-action${showHomeWelcome ? ' chat-input-action-home' : ''}`}
|
||||
disabled={!canSubmit || voiceDisabled || uploadingImage}
|
||||
onClick={() => void handleSubmit()}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user