extend media display
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import type { AudioHTMLAttributes } from 'react';
|
||||
|
||||
import { useResolvedAssetReadUrl } from '../hooks/useResolvedAssetReadUrl';
|
||||
|
||||
type ResolvedAssetAudioProps = Omit<
|
||||
AudioHTMLAttributes<HTMLAudioElement>,
|
||||
'src'
|
||||
> & {
|
||||
src?: string | null;
|
||||
objectKey?: string | null;
|
||||
fallbackSrc?: string | null;
|
||||
refreshKey?: string | number | null;
|
||||
};
|
||||
|
||||
export function ResolvedAssetAudio({
|
||||
src,
|
||||
objectKey,
|
||||
fallbackSrc,
|
||||
refreshKey,
|
||||
...rest
|
||||
}: ResolvedAssetAudioProps) {
|
||||
const { resolvedUrl } = useResolvedAssetReadUrl(src, {
|
||||
objectKey,
|
||||
refreshKey,
|
||||
});
|
||||
const finalSrc = resolvedUrl || fallbackSrc?.trim() || '';
|
||||
|
||||
if (!finalSrc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <audio {...rest} src={finalSrc} />;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Check, Image as ImageIcon, Loader2, X } from 'lucide-react';
|
||||
import { Check, Image as ImageIcon, Loader2, Volume2, X } from 'lucide-react';
|
||||
|
||||
import type {
|
||||
EditorAgentAttachmentRef,
|
||||
@@ -8,7 +8,9 @@ import type {
|
||||
import { attachmentKey } from '@/src/components/image-editor/EditorAgentConversation/common.ts';
|
||||
import { PendingToolCall } from '@/src/components/image-editor/EditorAgentConversation/PendingToolCall.tsx';
|
||||
import { editorAgentToolLabel } from '@/src/components/image-editor/EditorAgentConversation/toolCallPresentation.ts';
|
||||
import { ResolvedAssetAudio } from '@/src/components/ResolvedAssetAudio.tsx';
|
||||
import { ResolvedAssetImage } from '@/src/components/ResolvedAssetImage.tsx';
|
||||
import { ResolvedAssetVideo } from '@/src/components/ResolvedAssetVideo.tsx';
|
||||
|
||||
function messageRoleLabel(role: EditorAgentMessage['role']) {
|
||||
if (role === 'user') {
|
||||
@@ -55,6 +57,8 @@ export function AttachmentChip({
|
||||
}
|
||||
|
||||
function ToolCallView({ toolCall }: { toolCall: EditorAgentToolCall }) {
|
||||
const videos = toolCall.videos ?? [];
|
||||
const audios = toolCall.audios ?? [];
|
||||
const isExecuting = toolCall.status === 'executing';
|
||||
const statusLabel =
|
||||
toolCall.status === 'completed'
|
||||
@@ -102,6 +106,54 @@ function ToolCallView({ toolCall }: { toolCall: EditorAgentToolCall }) {
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{videos.length ? (
|
||||
<div className="mt-2 grid grid-cols-1 gap-2">
|
||||
{videos.map((video, index) => (
|
||||
<div
|
||||
key={`${toolCall.toolName}-${video.resourceId ?? video.objectKey ?? index}`}
|
||||
className="overflow-hidden rounded-xl border border-slate-200 bg-slate-100"
|
||||
>
|
||||
<ResolvedAssetVideo
|
||||
src={video.videoSrc}
|
||||
objectKey={video.objectKey}
|
||||
fallbackSrc={video.thumbnailSrc}
|
||||
refreshKey={
|
||||
video.resourceId ?? video.objectKey ?? toolCall.toolName
|
||||
}
|
||||
controls
|
||||
playsInline
|
||||
preload="metadata"
|
||||
className="max-h-56 w-full bg-black object-contain"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{audios.length ? (
|
||||
<div className="mt-2 space-y-2">
|
||||
{audios.map((audio, index) => (
|
||||
<div
|
||||
key={`${toolCall.toolName}-${audio.resourceId ?? audio.objectKey ?? index}`}
|
||||
className="flex items-center gap-2 rounded-xl border border-slate-200 bg-slate-50 p-2"
|
||||
>
|
||||
<Volume2
|
||||
className="h-4 w-4 shrink-0 text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<ResolvedAssetAudio
|
||||
src={audio.audioSrc}
|
||||
objectKey={audio.objectKey}
|
||||
refreshKey={
|
||||
audio.resourceId ?? audio.objectKey ?? toolCall.toolName
|
||||
}
|
||||
controls
|
||||
preload="metadata"
|
||||
className="min-w-0 flex-1"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -298,7 +298,9 @@ export function useEditorAgentConversation({
|
||||
nextMessages.some(
|
||||
(message) =>
|
||||
message.toolCall?.status === 'completed' &&
|
||||
message.toolCall.images.length > 0,
|
||||
(message.toolCall.images.length > 0 ||
|
||||
(message.toolCall.videos?.length ?? 0) > 0 ||
|
||||
(message.toolCall.audios?.length ?? 0) > 0),
|
||||
)
|
||||
) {
|
||||
onCanvasRefreshRequested?.();
|
||||
|
||||
Reference in New Issue
Block a user