flotilla/src/app/components/ContentLinkBlock.svelte

71 lines
2.3 KiB
Svelte
Raw Normal View History

2024-09-24 21:12:38 +00:00
<script lang="ts">
2025-06-16 18:45:05 +00:00
import {ellipsize, displayUrl, postJson} from "@welshman/lib"
import {dufflepud, imgproxy} from "@app/core/state"
2025-02-04 03:28:29 +00:00
import {preventDefault, stopPropagation} from "@lib/html"
2024-09-24 21:12:38 +00:00
import Link from "@lib/components/Link.svelte"
2024-10-17 23:03:50 +00:00
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
2025-04-28 22:46:48 +00:00
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
import {pushModal} from "@app/util/modal"
2024-09-24 21:12:38 +00:00
2025-04-28 22:46:48 +00:00
const {value, event} = $props()
2024-09-24 21:12:38 +00:00
let hideImage = $state(false)
2024-09-24 21:12:38 +00:00
const url = value.url.toString()
const loadPreview = async () => {
const json = await postJson(dufflepud("link/preview"), {url})
if (!json?.title && !json?.image) {
throw new Error("Failed to load link preview")
}
return json
}
2024-10-17 22:02:03 +00:00
const onError = () => {
hideImage = true
}
const expand = () => pushModal(ContentLinkDetail, {value, event}, {fullscreen: true})
2024-09-24 21:12:38 +00:00
</script>
2025-01-15 17:07:12 +00:00
<Link external href={url} class="my-2 block">
2025-06-05 20:37:50 +00:00
<div class="overflow-hidden rounded-box">
2024-11-18 22:57:27 +00:00
{#if url.match(/\.(mov|webm|mp4)$/)}
<video controls src={url} class="max-h-96 object-contain object-center">
<track kind="captions" />
</video>
{:else if url.match(/\.(jpe?g|png|gif|webp)$/)}
2025-02-04 00:37:14 +00:00
<button type="button" onclick={stopPropagation(preventDefault(expand))}>
<ContentLinkBlockImage {value} {event} class="m-auto max-h-96 rounded-box" />
2024-11-18 22:57:27 +00:00
</button>
{:else}
{#await loadPreview()}
<div class="center my-12 w-full">
2025-02-03 23:01:42 +00:00
<span class="loading loading-spinner"></span>
2024-09-24 21:12:38 +00:00
</div>
2024-11-18 22:57:27 +00:00
{:then preview}
<div class="bg-alt flex max-w-xl flex-col leading-normal">
{#if preview.image && !hideImage}
2024-11-18 22:57:27 +00:00
<img
alt="Link preview"
onerror={onError}
2024-11-18 22:57:27 +00:00
src={imgproxy(preview.image)}
class="bg-alt max-h-72 rounded-t-box object-contain object-center" />
2024-11-18 22:57:27 +00:00
{/if}
2025-06-16 18:45:05 +00:00
<div class="flex flex-col gap-2 p-4">
<strong class="overflow-hidden text-ellipsis whitespace-nowrap"
>{preview.title || displayUrl(url)}</strong>
<p>{ellipsize(preview.description, 140)}</p>
</div>
2024-11-18 22:57:27 +00:00
</div>
{:catch}
2024-11-19 00:48:51 +00:00
<p class="bg-alt p-12 text-center leading-normal">
2024-11-18 22:57:27 +00:00
Unable to load a preview for {url}
</p>
{/await}
{/if}
</div>
2024-09-24 21:12:38 +00:00
</Link>