File size: 3,107 Bytes
0ad74ed |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
<script lang="ts">
import LikeDislike from "./LikeDislike.svelte";
import Copy from "./Copy.svelte";
import type { FileData } from "@gradio/client";
import DownloadIcon from "./Download.svelte";
import { DownloadLink } from "@gradio/wasm/svelte";
import type { NormalisedMessage, TextMessage } from "../types";
import { is_component_message } from "./utils";
import { Retry, Undo } from "@gradio/icons";
import { IconButtonWrapper, IconButton } from "@gradio/atoms";
export let likeable: boolean;
export let show_retry: boolean;
export let show_undo: boolean;
export let show_copy_button: boolean;
export let show: boolean;
export let message: NormalisedMessage | NormalisedMessage[];
export let position: "right" | "left";
export let avatar: FileData | null;
export let generating: boolean;
export let handle_action: (selected: string | null) => void;
export let layout: "bubble" | "panel";
function is_all_text(
message: NormalisedMessage[] | NormalisedMessage
): message is TextMessage[] | TextMessage {
return (
(Array.isArray(message) &&
message.every((m) => typeof m.content === "string")) ||
(!Array.isArray(message) && typeof message.content === "string")
);
}
function all_text(message: TextMessage[] | TextMessage): string {
if (Array.isArray(message)) {
return message.map((m) => m.content).join("\n");
}
return message.content;
}
$: message_text = is_all_text(message) ? all_text(message) : "";
$: show_copy = show_copy_button && message && is_all_text(message);
$: show_download =
!Array.isArray(message) &&
is_component_message(message) &&
message.content.value?.url;
</script>
{#if show}
<div
class="message-buttons-{position} {layout} message-buttons {avatar !==
null && 'with-avatar'}"
>
<IconButtonWrapper top_panel={false}>
{#if show_copy}
<Copy value={message_text} />
{/if}
{#if show_download && !Array.isArray(message) && is_component_message(message)}
<DownloadLink
href={message?.content?.value.url}
download={message.content.value.orig_name || "image"}
>
<IconButton Icon={DownloadIcon} />
</DownloadLink>
{/if}
{#if show_retry}
<IconButton
Icon={Retry}
label="Retry"
on:click={() => handle_action("retry")}
disabled={generating}
/>
{/if}
{#if show_undo}
<IconButton
label="Undo"
Icon={Undo}
on:click={() => handle_action("undo")}
disabled={generating}
/>
{/if}
{#if likeable}
<LikeDislike {handle_action} />
{/if}
</IconButtonWrapper>
</div>
{/if}
<style>
.bubble :global(.icon-button-wrapper) {
margin: 0px calc(var(--spacing-xl) * 2);
}
.message-buttons-left {
align-self: flex-start;
}
.bubble.message-buttons-right {
align-self: flex-end;
}
.message-buttons-right :global(.icon-button-wrapper) {
margin-left: auto;
}
.bubble.with-avatar {
margin-left: calc(var(--spacing-xl) * 5);
margin-right: calc(var(--spacing-xl) * 5);
}
.panel {
display: flex;
align-self: flex-start;
padding: 0 var(--spacing-xl);
z-index: var(--layer-1);
}
</style>
|