Files
fnx_web/svelte/src/file_viewer/GalleryView.svelte

222 lines
5.0 KiB
Svelte
Raw Normal View History

2021-11-23 23:45:42 +01:00
<script>
2021-11-26 22:06:35 +01:00
import { createEventDispatcher } from "svelte"
import { flip } from "svelte/animate"
import FilePicker from "./FilePicker.svelte"
2022-05-03 14:37:26 +02:00
import { file_type } from "./FileUtilities.svelte";
2021-11-23 23:45:42 +01:00
let dispatch = createEventDispatcher()
export let list = {
id: "",
title: "",
files: [],
download_href: "",
info_href: "",
can_edit: false,
}
let file_picker;
2021-11-26 22:06:35 +01:00
const update_list = async new_files => {
2021-11-23 23:45:42 +01:00
dispatch("loading", true)
2021-11-26 22:06:35 +01:00
// If the list is empty we simply delete it
if (list.files.length === 0) {
try {
let resp = await fetch(list.info_href, {method: "DELETE"})
if (resp.status >= 400) {
throw (await resp.json()).message
}
window.close()
} catch (err) {
alert("Failed to delete album: "+err)
} finally {
dispatch("loading", false)
}
return
}
2021-11-23 23:45:42 +01:00
let listjson = {
title: list.title,
files: [],
}
2021-11-26 22:06:35 +01:00
list.files.forEach(f => {
listjson.files.push({
id: f.id,
})
2021-11-23 23:45:42 +01:00
})
try {
const resp = await fetch(
list.info_href,
{ method: "PUT", body: JSON.stringify(listjson) },
);
if (resp.status >= 400) {
throw (await resp.json()).message
}
} catch (err) {
alert("Failed to update album: "+err)
} finally {
2021-11-26 22:06:35 +01:00
dispatch("loading", false)
}
}
const add_files = async files => {
let list_files = list.files;
files.forEach(f => {
list_files.push(f)
})
await update_list(list_files)
dispatch("reload")
}
2021-11-26 22:06:35 +01:00
const delete_file = async index => {
const list_files = list.files
2021-11-26 22:06:35 +01:00
list_files.splice(index, 1)
await update_list(list_files)
list.files = list_files
2021-11-26 22:06:35 +01:00
}
const move_left = async index => {
2021-11-26 22:06:35 +01:00
if (index === 0) {
return;
}
const f = list.files;
2021-11-26 22:06:35 +01:00
[f[index], f[index-1]] = [f[index-1], f[index]];
await update_list(f)
list.files = f
2021-11-26 22:06:35 +01:00
}
const move_right = async index => {
2021-11-26 22:06:35 +01:00
if (index >= list.files.length-1) {
return;
}
const f = list.files;
2021-11-26 22:06:35 +01:00
[f[index], f[index+1]] = [f[index+1], f[index]];
await update_list(f)
list.files = f
2021-11-26 22:06:35 +01:00
}
let hovering = -1
const drag = (e, index) => {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.dropEffect = 'move';
e.dataTransfer.setData('text/plain', index);
}
const drop = (e, index) => {
e.dataTransfer.dropEffect = 'move';
let start = parseInt(e.dataTransfer.getData("text/plain"));
let list_files = list.files
if (start < index) {
list_files.splice(index + 1, 0, list_files[start]);
list_files.splice(start, 1);
} else if (start > index) {
2021-11-26 22:06:35 +01:00
list_files.splice(index, 0, list_files[start]);
list_files.splice(start + 1, 1);
} else {
return; // Nothing changed
2021-11-23 23:45:42 +01:00
}
2021-11-26 22:06:35 +01:00
update_list(list_files)
2021-11-23 23:45:42 +01:00
}
</script>
<div class="gallery">
{#each list.files as file, index (file)}
2021-12-28 13:56:24 +01:00
<a
href="#item={index}"
2021-11-26 22:06:35 +01:00
class="file"
draggable={list.can_edit}
on:dragstart={e => drag(e, index)}
on:drop|preventDefault={e => drop(e, index)}
on:dragover|preventDefault|stopPropagation
on:dragenter={() => {hovering = index}}
on:dragend={() => {hovering = -1}}
2021-11-26 22:06:35 +01:00
class:highlight={hovering === index}
animate:flip={{duration: 500}}>
2021-11-23 23:45:42 +01:00
<div
class="icon_container"
class:editing={list.can_edit}
2022-05-03 14:37:26 +02:00
class:wide={file_type(file) === "image" || file_type(file) === "video"}
2021-11-23 23:45:42 +01:00
style="background-image: url('{file.icon_href}?width=256&height=256');">
{#if list.can_edit}
2021-12-28 13:56:24 +01:00
<i class="icon" on:click|stopPropagation|preventDefault style="cursor: grab;">drag_indicator</i>
<i class="icon" on:click|stopPropagation|preventDefault={() => {move_left(index)}}>chevron_left</i>
<i class="icon" on:click|stopPropagation|preventDefault={() => {move_right(index)}}>chevron_right</i>
<i class="icon" on:click|stopPropagation|preventDefault={() => {delete_file(index)}}>delete</i>
2021-11-23 23:45:42 +01:00
{/if}
</div>
{file.name}
2021-12-28 13:56:24 +01:00
</a>
2021-11-23 23:45:42 +01:00
{/each}
{#if list.can_edit}
<div class="file" on:click={file_picker.open} style="font-size: 1.5em; padding-top: 2.5em; cursor: pointer;">
2021-11-23 23:45:42 +01:00
<i class="icon">add</i>
<br/>
Add files
</div>
{/if}
2021-11-23 23:45:42 +01:00
</div>
<FilePicker bind:this={file_picker} on:files={e => {add_files(e.detail)}} multi_select={true} title="Select files to add to album"></FilePicker>
2021-11-27 17:20:17 +01:00
2021-11-23 23:45:42 +01:00
<style>
.gallery{
width: 100%;
2021-11-27 17:20:17 +01:00
max-height: 100%;
overflow: auto;
2021-11-27 17:20:17 +01:00
display: flex;
flex-wrap: wrap;
justify-content: center;
2021-11-23 23:45:42 +01:00
}
.file{
width: 200px;
2022-06-21 14:00:03 +02:00
max-width: 42%;
2021-11-23 23:45:42 +01:00
height: 200px;
margin: 8px;
overflow: hidden;
border-radius: 8px;
2022-03-30 19:35:26 +02:00
background: var(--input_background);
2021-11-23 23:45:42 +01:00
word-break: break-all;
text-align: center;
line-height: 1.2em;
display: inline-block;
text-overflow: ellipsis;
text-decoration: none;
vertical-align: top;
2022-03-29 21:41:46 +02:00
color: var(--body_text_color);
2022-03-30 19:35:26 +02:00
transition: background 0.2s;
2021-11-23 23:45:42 +01:00
}
2022-03-30 19:35:26 +02:00
.file:hover {
background: var(--input_hover_background);
}
2022-06-21 14:00:03 +02:00
2022-03-30 19:35:26 +02:00
.highlight {
2021-11-23 23:45:42 +01:00
box-shadow: 0 0 2px 2px var(--highlight_color);
text-decoration: none;
}
.icon_container {
2022-06-21 14:00:03 +02:00
margin: 3px;
height: 154px;
border-radius: 6px;
2021-11-23 23:45:42 +01:00
background-position: center;
2022-05-03 14:37:26 +02:00
background-size: contain;
background-repeat: no-repeat;
2021-11-26 22:06:35 +01:00
font-size: 22px;
2021-11-23 23:45:42 +01:00
text-align: left;
}
.icon_container.editing {
2022-03-29 21:41:46 +02:00
box-shadow: inset 0 60px 40px -20px var(--body_color);
2021-11-23 23:45:42 +01:00
}
2022-03-29 21:41:46 +02:00
.icon_container > .icon {
color: var(--body_text_color);
}
.icon_container > .icon:hover {
2021-11-23 23:45:42 +01:00
color: var(--highlight_color);
cursor: pointer;
}
2022-05-03 14:37:26 +02:00
.icon_container.wide {
background-size: cover;
}
2021-11-23 23:45:42 +01:00
</style>