release: prepare 0629001 portal updates
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useUserAvatar } from '../hooks/useUserAvatar';
|
||||
import type { Message } from '../types';
|
||||
import { getDisplayText, getImageUrls, getRenderableImageUrls, getThinking } from '../utils/message';
|
||||
@@ -8,7 +8,6 @@ import { filterText } from '../utils/wordFilter';
|
||||
import { formatChatTime, shouldShowTimestamp } from '../utils/time';
|
||||
import { TKMindAvatar } from './TKMindAvatar';
|
||||
import { UserAvatar } from './UserAvatar';
|
||||
import { ChatSharePreviewModal } from './ChatSharePreviewModal';
|
||||
import { ChatWelcomePanel } from './ChatWelcomePanel';
|
||||
|
||||
function CopyIcon() {
|
||||
@@ -133,6 +132,33 @@ function CopyButton({ text }: { text: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function PublicLinkCopyButton({ url }: { url: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const copyTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
const copy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
setCopied(true);
|
||||
if (copyTimer.current) window.clearTimeout(copyTimer.current);
|
||||
copyTimer.current = window.setTimeout(() => setCopied(false), 1800);
|
||||
} catch {
|
||||
setCopied(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`msg-public-share-link${copied ? ' is-copied' : ''}`}
|
||||
onClick={() => void copy()}
|
||||
title={url}
|
||||
>
|
||||
{copied ? '已复制' : '复制链接'}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function TimeDivider({ timestamp }: { timestamp: number }) {
|
||||
return (
|
||||
<div className="msg-time-divider">
|
||||
@@ -184,7 +210,6 @@ function MessageRow({
|
||||
compact?: boolean;
|
||||
}) {
|
||||
const [actionsOpen, setActionsOpen] = useState(false);
|
||||
const [previewOpen, setPreviewOpen] = useState(false);
|
||||
const rawText = getDisplayText(message);
|
||||
const text = filterText(rawText);
|
||||
const saveActions = getMessageSaveActions(text, { userId: publishUserId, username: publishUsername });
|
||||
@@ -275,14 +300,8 @@ function MessageRow({
|
||||
>
|
||||
{saveActions.kind === 'page' ? '保存页面' : '保存为文章'}
|
||||
</button>
|
||||
{saveActions.previewUrl && sessionId && message.id && (
|
||||
<button
|
||||
type="button"
|
||||
className="msg-open-preview"
|
||||
onClick={() => setPreviewOpen(true)}
|
||||
>
|
||||
打开预览
|
||||
</button>
|
||||
{saveActions.previewUrl && (
|
||||
<PublicLinkCopyButton url={saveActions.previewUrl} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
@@ -301,14 +320,8 @@ function MessageRow({
|
||||
>
|
||||
{saveActions.kind === 'page' ? '保存页面' : '保存为文章'}
|
||||
</button>
|
||||
{saveActions.previewUrl && sessionId && message.id && (
|
||||
<button
|
||||
type="button"
|
||||
className="msg-open-preview"
|
||||
onClick={() => setPreviewOpen(true)}
|
||||
>
|
||||
打开预览
|
||||
</button>
|
||||
{saveActions.previewUrl && (
|
||||
<PublicLinkCopyButton url={saveActions.previewUrl} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
@@ -324,14 +337,6 @@ function MessageRow({
|
||||
title={onAvatarClick ? '点击更换头像' : undefined}
|
||||
/>
|
||||
)}
|
||||
{previewOpen && sessionId && message.id && (
|
||||
<ChatSharePreviewModal
|
||||
sessionId={sessionId}
|
||||
messageId={message.id}
|
||||
onClose={() => setPreviewOpen(false)}
|
||||
onSave={onSaveAsPage ? () => onSaveAsPage(message) : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -363,8 +368,13 @@ export function MessageList({
|
||||
{messages.map((message, index) => {
|
||||
const prev = index > 0 ? messages[index - 1] : undefined;
|
||||
const showTime = shouldShowTimestamp(message.created, prev?.created);
|
||||
const anchorId = message.id ?? `msg-${index}-${message.role}-${message.created}`;
|
||||
return (
|
||||
<div key={message.id ?? `msg-${index}`} className="msg-block">
|
||||
<div
|
||||
key={message.id ?? `msg-${index}`}
|
||||
className="msg-block"
|
||||
data-message-anchor={anchorId}
|
||||
>
|
||||
{showTime && <TimeDivider timestamp={message.created} />}
|
||||
<MessageRow
|
||||
message={message}
|
||||
|
||||
Reference in New Issue
Block a user