File size: 3,881 Bytes
564e576
 
 
 
 
 
 
c58d011
 
 
564e576
 
c58d011
 
 
 
 
564e576
a5070fd
 
 
 
 
 
 
 
 
 
 
 
c58d011
 
 
 
332ed42
 
c58d011
 
 
564e576
 
c58d011
 
 
 
 
 
 
 
 
 
 
564e576
c58d011
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564e576
 
c58d011
 
564e576
c58d011
564e576
c58d011
564e576
c58d011
 
 
 
 
 
 
564e576
c58d011
 
 
 
 
 
 
 
 
 
 
 
 
332ed42
c58d011
 
 
 
 
 
 
 
 
 
 
 
 
 
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
121
<script lang="ts">
	import { createEventDispatcher } from "svelte";
	import { page } from "$app/stores";
	import type { MessageFile } from "$lib/types/Message";
	import CarbonClose from "~icons/carbon/close";
	import CarbonDocumentBlank from "~icons/carbon/document-blank";

	import Modal from "../Modal.svelte";
	import AudioPlayer from "../players/AudioPlayer.svelte";

	export let file: MessageFile;
	export let canClose = true;
	export let isPreview = false;

	$: showModal = false;
	$: urlNotTrailing = $page.url.pathname.replace(/\/$/, "");

	const dispatch = createEventDispatcher<{ close: void }>();

	function truncateMiddle(text: string, maxLength: number): string {
		if (text.length <= maxLength) {
			return text;
		}

		const halfLength = Math.floor((maxLength - 1) / 2);
		const start = text.substring(0, halfLength);
		const end = text.substring(text.length - halfLength);

		return `${start}${end}`;
	}

	const isImage = (mime: string) =>
		mime.startsWith("image/") || mime === "webp" || mime === "jpeg" || mime === "png";

	const isAudio = (mime: string) =>
		mime.startsWith("audio/") || mime === "mp3" || mime === "wav" || mime === "x-wav";
	const isVideo = (mime: string) => mime.startsWith("video/");

	$: isClickable = isImage(file.mime) && !isPreview;
</script>

{#if showModal && isClickable}
	<!-- show the image file full screen, click outside to exit -->
	<Modal width="sm:max-w-[500px]" on:close={() => (showModal = false)}>
		{#if file.type === "hash"}
			<img
				src={urlNotTrailing + "/output/" + file.value}
				alt="input from user"
				class="aspect-auto"
			/>
		{:else}
			<!-- handle the case where this is a base64 encoded image -->
			<img
				src={`data:${file.mime};base64,${file.value}`}
				alt="input from user"
				class="aspect-auto"
			/>
		{/if}
	</Modal>
{/if}

<button on:click={() => (showModal = true)} disabled={!isClickable}>
	<div class="group relative flex items-center rounded-xl shadow-sm">
		{#if isImage(file.mime)}
			<div class=" overflow-hidden rounded-xl" class:size-24={isPreview} class:size-48={!isPreview}>
				<img
					src={file.type === "base64"
						? `data:${file.mime};base64,${file.value}`
						: urlNotTrailing + "/output/" + file.value}
					alt={file.name}
					class="h-full w-full bg-gray-200 object-cover dark:bg-gray-800"
				/>
			</div>
		{:else if isAudio(file.mime)}
			<AudioPlayer
				src={file.type === "base64"
					? `data:${file.mime};base64,${file.value}`
					: urlNotTrailing + "/output/" + file.value}
				name={truncateMiddle(file.name, 28)}
			/>
		{:else if isVideo(file.mime)}
			<div
				class="border-1 w-72 overflow-clip rounded-xl border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-900"
			>
				<!-- svelte-ignore a11y-media-has-caption -->
				<video
					src={file.type === "base64"
						? `data:${file.mime};base64,${file.value}`
						: urlNotTrailing + "/output/" + file.value}
					controls
				/>
			</div>
		{:else}
			<div
				class="flex h-14 w-72 items-center gap-2 overflow-hidden rounded-xl border border-gray-200 bg-white p-2 dark:border-gray-800 dark:bg-gray-900"
			>
				<div
					class="grid size-10 flex-none place-items-center rounded-lg bg-gray-100 dark:bg-gray-800"
				>
					<CarbonDocumentBlank class="text-base text-gray-700 dark:text-gray-300" />
				</div>
				<dl class="flex flex-col truncate leading-tight">
					<dd class="text-sm">
						{truncateMiddle(file.name, 28)}
					</dd>
					<dt class="text-xs text-gray-400">{file.mime}</dt>
				</dl>
			</div>
		{/if}
		<!-- add a button on top that removes the image -->
		{#if canClose}
			<button
				class="invisible absolute -right-2 -top-2 grid size-6 place-items-center rounded-full border bg-black group-hover:visible dark:border-gray-700"
				on:click={() => dispatch("close")}
			>
				<CarbonClose class=" text-xs  text-white" />
			</button>
		{/if}
	</div>
</button>