180 lines
3.6 KiB
Svelte
180 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import { downloadMedia } from "$lib/api/download";
|
|
import type { MediaRef } from "$lib/api/types";
|
|
import Icon from "$lib/components/ui/Icon.svelte";
|
|
import { formatBytes, mediaKindLabel } from "$lib/format/media";
|
|
import { shareUi } from "$lib/stores/shares.svelte";
|
|
import { toasts } from "$lib/stores/toasts.svelte";
|
|
|
|
interface Props {
|
|
media: MediaRef;
|
|
own?: boolean;
|
|
}
|
|
|
|
const { media, own = false }: Props = $props();
|
|
|
|
let saving = $state(false);
|
|
|
|
const name = $derived(
|
|
media.file_name ?? mediaKindLabel(media.kind) ?? "Файл"
|
|
);
|
|
const size = $derived(formatBytes(media.file_size));
|
|
|
|
async function save() {
|
|
if (media.id === null || saving) {
|
|
return;
|
|
}
|
|
saving = true;
|
|
try {
|
|
await downloadMedia(media.id);
|
|
} catch {
|
|
toasts.error("Не удалось скачать файл");
|
|
} finally {
|
|
saving = false;
|
|
}
|
|
}
|
|
|
|
function share() {
|
|
if (media.id !== null) {
|
|
shareUi.share({ kind: "media", mediaId: media.id }, name);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="FileChip" class:own>
|
|
<button class="file-main" type="button" title={name} onclick={save}>
|
|
<span class="file-glyph" class:own>
|
|
<Icon name={saving ? "timer" : "document"} size="1.25rem" />
|
|
</span>
|
|
<span class="file-text">
|
|
<span class="file-name">{name}</span>
|
|
<span class="file-sub">{size || mediaKindLabel(media.kind)}</span>
|
|
</span>
|
|
</button>
|
|
<button
|
|
class="file-share"
|
|
type="button"
|
|
aria-label="Доступ по ссылке"
|
|
onclick={share}
|
|
>
|
|
<Icon name="allow-share" size="1.125rem" />
|
|
</button>
|
|
</div>
|
|
|
|
<style lang="scss">
|
|
.FileChip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.25rem;
|
|
|
|
width: 100%;
|
|
max-width: 20rem;
|
|
padding: 0.25rem 0.375rem 0.25rem 0.25rem;
|
|
border-radius: var(--border-radius-default-small);
|
|
|
|
background-color: var(--color-primary-tint);
|
|
|
|
&.own {
|
|
background-color: var(--color-code-own-bg);
|
|
}
|
|
}
|
|
|
|
.file-main {
|
|
cursor: pointer;
|
|
|
|
display: flex;
|
|
flex: 1;
|
|
align-items: center;
|
|
gap: 0.625rem;
|
|
|
|
min-width: 0;
|
|
padding: 0.25rem;
|
|
border: 0;
|
|
|
|
font-family: inherit;
|
|
text-align: start;
|
|
|
|
background: transparent;
|
|
}
|
|
|
|
.file-glyph :global(.icon) {
|
|
transform: translate(0.5px, -0.5px);
|
|
}
|
|
|
|
.file-glyph {
|
|
display: flex;
|
|
flex-shrink: 0;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
width: 2.25rem;
|
|
height: 2.25rem;
|
|
border-radius: 50%;
|
|
|
|
color: var(--color-white);
|
|
background-color: var(--color-primary);
|
|
|
|
&.own {
|
|
color: var(--color-own-links);
|
|
background-color: color-mix(
|
|
in srgb,
|
|
var(--color-own-links) 20%,
|
|
transparent
|
|
);
|
|
}
|
|
}
|
|
|
|
.file-text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
}
|
|
|
|
.file-name {
|
|
overflow: hidden;
|
|
|
|
font-size: 0.9375rem;
|
|
color: var(--color-text);
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.file-sub {
|
|
font-size: 0.75rem;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.own .file-sub {
|
|
color: var(--color-message-meta-own);
|
|
}
|
|
|
|
.file-share {
|
|
cursor: pointer;
|
|
|
|
display: flex;
|
|
flex-shrink: 0;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
width: 2rem;
|
|
height: 2rem;
|
|
border: 0;
|
|
border-radius: 50%;
|
|
|
|
color: var(--color-primary);
|
|
background: transparent;
|
|
|
|
&:hover {
|
|
background-color: var(--color-primary-opacity);
|
|
}
|
|
}
|
|
|
|
.own .file-share {
|
|
color: var(--color-own-links);
|
|
|
|
&:hover {
|
|
background-color: color-mix(in srgb, currentcolor 18%, transparent);
|
|
}
|
|
}
|
|
</style>
|