feat: artifacts download button

This commit is contained in:
Timothy Jaeryang Baek 2025-05-17 00:27:20 +04:00
parent 02e5bbc903
commit fcb93f3155

View File

@ -5,12 +5,14 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import { artifactCode, chatId, settings, showArtifacts, showControls } from '$lib/stores'; import { artifactCode, chatId, settings, showArtifacts, showControls } from '$lib/stores';
import XMark from '../icons/XMark.svelte';
import { copyToClipboard, createMessagesList } from '$lib/utils'; import { copyToClipboard, createMessagesList } from '$lib/utils';
import XMark from '../icons/XMark.svelte';
import ArrowsPointingOut from '../icons/ArrowsPointingOut.svelte'; import ArrowsPointingOut from '../icons/ArrowsPointingOut.svelte';
import Tooltip from '../common/Tooltip.svelte'; import Tooltip from '../common/Tooltip.svelte';
import SvgPanZoom from '../common/SVGPanZoom.svelte'; import SvgPanZoom from '../common/SVGPanZoom.svelte';
import ArrowLeft from '../icons/ArrowLeft.svelte'; import ArrowLeft from '../icons/ArrowLeft.svelte';
import ArrowDownTray from '../icons/ArrowDownTray.svelte';
export let overlay = false; export let overlay = false;
export let history; export let history;
@ -180,6 +182,18 @@
} }
}; };
const downloadArtifact = () => {
const blob = new Blob([contents[selectedContentIdx].content], { type: 'text/html' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `artifact-${$chatId}-${selectedContentIdx}.html`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};
onMount(() => { onMount(() => {
artifactCode.subscribe((value) => { artifactCode.subscribe((value) => {
if (contents) { if (contents) {
@ -205,7 +219,7 @@
<ArrowLeft className="size-3.5 text-gray-900 dark:text-white" /> <ArrowLeft className="size-3.5 text-gray-900 dark:text-white" />
</button> </button>
<div class="flex-1 flex items-center justify-between"> <div class="flex-1 flex items-center justify-between pr-1">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<div class="flex items-center gap-0.5 self-center min-w-fit" dir="ltr"> <div class="flex items-center gap-0.5 self-center min-w-fit" dir="ltr">
<button <button
@ -259,7 +273,7 @@
</div> </div>
</div> </div>
<div class="flex items-center gap-1"> <div class="flex items-center gap-1.5">
<button <button
class="copy-code-button bg-none border-none text-xs bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-md px-1.5 py-0.5" class="copy-code-button bg-none border-none text-xs bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-md px-1.5 py-0.5"
on:click={() => { on:click={() => {
@ -272,6 +286,15 @@
}}>{copied ? $i18n.t('Copied') : $i18n.t('Copy')}</button }}>{copied ? $i18n.t('Copied') : $i18n.t('Copy')}</button
> >
<Tooltip content={$i18n.t('Download')}>
<button
class=" bg-none border-none text-xs bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-md p-0.5"
on:click={downloadArtifact}
>
<ArrowDownTray className="size-3.5" />
</button>
</Tooltip>
{#if contents[selectedContentIdx].type === 'iframe'} {#if contents[selectedContentIdx].type === 'iframe'}
<Tooltip content={$i18n.t('Open in full screen')}> <Tooltip content={$i18n.t('Open in full screen')}>
<button <button