Add zip previewer

This commit is contained in:
2023-01-17 16:13:26 +01:00
parent c075cb4a72
commit ade760225a
9 changed files with 168 additions and 19 deletions

View File

@@ -1,6 +1,6 @@
## File Methods
<details class="request_post">
<details class="api_doc_details request_post">
<summary><span class="method">POST</span>/file</summary>
<div>
@@ -75,7 +75,7 @@ HTTP 413: Payload Too Large
</div>
</details>
<details class="request_put">
<details class="api_doc_details request_put">
<summary><span class="method">PUT</span>/file/{name}</summary>
<div>

View File

@@ -1,6 +1,6 @@
## File Methods
<details class="request_post">
<details class="api_doc_details request_post">
<summary><span class="method">POST</span>/file</summary>
<div>

View File

@@ -401,47 +401,47 @@ pre {
/* API documentation markup */
details {
.api_doc_details {
border-top: 1px solid;
border-bottom: 1px solid;
margin: 15px 0 15px 0;
}
details>summary {
.api_doc_details>summary {
padding: 2px;
font-family: monospace;
}
details>summary>.method {
.api_doc_details>summary>.method {
display: inline-block;
width: 80px;
}
details>div {
.api_doc_details>div {
padding: 8px;
}
details.request_get {
.api_doc_details.request_get {
border-color: #3636ff;
background-color: rgba(32, 32, 255, 0.2);
}
details.request_post {
.api_doc_details.request_post {
border-color: #00d000;
background-color: rgba(0, 255, 0, 0.05);
}
details.request_delete {
.api_doc_details.request_delete {
border-color: #B00000;
background-color: rgba(255, 0, 0, 0.05);
}
details.request_put {
.api_doc_details.request_put {
border-color: #B06000;
background-color: rgba(255, 128, 0, 0.05);
}
details.request_patch {
.api_doc_details.request_patch {
border-color: #6000B0;
background-color: rgba(128, 0, 255, 0.1);
}

View File

@@ -37,6 +37,8 @@ export const file_set_href = file => {
export const file_type = file => {
if (file.mime_type === "application/bittorrent" || file.mime_type === "application/x-bittorrent") {
return "torrent"
} else if (file.mime_type === "application/zip") {
return "zip"
} else if (file.mime_type.startsWith("image")) {
return "image"
} else if (

View File

@@ -13,6 +13,7 @@ import RateLimit from "./RateLimit.svelte";
import Torrent from "./Torrent.svelte";
import SpeedLimit from "./SpeedLimit.svelte";
import { download_limits } from "../DownloadLimitStore";
import Zip from "./Zip.svelte";
let viewer
let viewer_type = "loading"
@@ -68,7 +69,9 @@ export const set_file = async file => {
{:else if viewer_type === "text"}
<Text bind:this={viewer}></Text>
{:else if viewer_type === "torrent"}
<Torrent bind:this={viewer} on:loading on:download></Torrent>
<Torrent bind:this={viewer} on:loading on:download />
{:else if viewer_type === "zip"}
<Zip bind:this={viewer} on:loading on:download />
{:else if viewer_type === "file"}
<File bind:this={viewer} on:download on:reload></File>
{/if}

View File

@@ -0,0 +1,100 @@
<script>
import { createEventDispatcher } from "svelte";
import { formatDataVolume, formatDate } from "../../util/Formatting.svelte"
import TextBlock from "./TextBlock.svelte";
import ZipItem from "./ZipItem.svelte";
let dispatch = createEventDispatcher()
let status = "loading"
let file = {
name: "",
mime_type: "",
size: 0,
date_upload: "",
icon_href: ""
}
let zip = {
size: 0,
children: null,
}
let uncomp_size = 0
export const set_file = async f => {
file = f
dispatch("loading", true)
try {
let resp = await fetch(f.info_href+"/zip")
if (resp.status >= 400) {
status = "parse_failed"
return
}
zip = await resp.json()
uncomp_size = recursive_size(zip)
} catch (err) {
console.error(err)
} finally {
dispatch("loading", false)
}
status = "finished"
}
const recursive_size = (file) => {
let size = file.size
// If the file has children (array is iterable) we call this function on all
// the children and add the size to our size accumulator
if (file.children.forEach) {
file.children.forEach(child => {
size += recursive_size(child)
});
}
// Return the total size of this file and all its children
return size
}
</script>
<h1>{file.name}</h1>
<img src={file.icon_href} alt="File icon" class="icon">
<TextBlock width="600px">
Compressed size: {formatDataVolume(file.size, 3)}<br/>
Uncompressed size: {formatDataVolume(uncomp_size, 3)}<br/>
Uploaded on: {formatDate(file.date_upload, true, true, true)}
<br/>
<button class="button_highlight" on:click={() => {dispatch("download")}}>
<i class="icon">download</i>
<span>Download</span>
</button>
</TextBlock>
<br/><br/>
{#if status === "parse_failed"}
<TextBlock width="650px">
<p>
Zip archive could not be parsed. It may be corrupted.
</p>
</TextBlock>
{/if}
{#if status === "finished"}
<TextBlock width="1000px">
<h2>Files in this zip archive</h2>
<ZipItem item={zip} />
</TextBlock>
{/if}
<style>
h1 {
text-shadow: 1px 1px 3px var(--shadow_color);
line-break: anywhere;
}
</style>

View File

@@ -0,0 +1,44 @@
<script>
import { formatDataVolume } from "../../util/Formatting.svelte";
export let item = {
size: 0,
children: null,
}
</script>
<!-- First get directories and render them as details collapsibles -->
{#each Object.entries(item.children) as [name, child]}
{#if child.children}
<details>
<summary>
{name} ({formatDataVolume(child.size, 3)})
</summary>
<svelte:self item={child}></svelte:self>
</details>
{/if}
{/each}
<!-- Then get files and render them as list items -->
<ul>
{#each Object.entries(item.children) as [name, child]}
{#if !child.children}
<li>
{name} ({formatDataVolume(child.size, 3)})<br/>
</li>
{/if}
{/each}
</ul>
<style>
details {
padding-left: 12px;
border: none;
border-left: 2px solid var(--separator);
}
ul {
margin: 0;
padding-left: 30px;
border-left: 2px solid var(--separator);
}
</style>

View File

@@ -53,7 +53,7 @@ onMount(() => {
Data transfer limit
</div>
<div class="feat_normal">
<span class="text_highlight">20 GB</span> data transfer per week
Download limit of <span class="text_highlight">20 GB</span> per week
(168 hours). When this threshold is reached your download speed will
be reduced
</div>
@@ -153,7 +153,7 @@ onMount(() => {
<p>
Unlike most other sharing sites pixeldrain uses a postponing system for
expiring files. When a file is freshly uploaded it gets 60 days by
default (120 days if you have the pro plan). After these 60 days we will
default (240 days if you have the pro plan). After these 60 days we will
check when the file was last viewed. Files which are regularly viewed
could still bring new users to the platform, it would be rude to show
these people a File Not Found page. So if the file was viewed in the

View File

@@ -13,7 +13,7 @@
{/if}
</div>
<div class="feat_pro features_cell round_tr">
<div><span class="text_highlight">20 GB</span> max file size</div>
<div><span class="text_highlight">50 GB</span> max file size</div>
<div><span class="text_highlight">Files never expire</span></div>
<div><span class="text_highlight">4 TB</span> transfer limit</div>
<div><span class="text_highlight">4 TB</span> storage space</div>
@@ -39,7 +39,7 @@
{/if}
</div>
<div class="feat_pro features_cell">
<div><span class="text_highlight">20 GB</span> max file size</div>
<div><span class="text_highlight">50 GB</span> max file size</div>
<div><span class="text_highlight">Files never expire</span></div>
<div><span class="text_highlight">8 TB</span> transfer limit</div>
<div><span class="text_highlight">8 TB</span> storage space</div>
@@ -60,7 +60,7 @@
{/if}
</div>
<div class="feat_pro features_cell">
<div><span class="text_highlight">20 GB</span> max file size</div>
<div><span class="text_highlight">50 GB</span> max file size</div>
<div><span class="text_highlight">Files never expire</span></div>
<div><span class="text_highlight">16 TB</span> transfer limit</div>
<div><span class="text_highlight">16 TB</span> storage space</div>
@@ -81,7 +81,7 @@
{/if}
</div>
<div class="feat_pro features_cell round_br">
<div><span class="text_highlight">20 GB</span> max file size</div>
<div><span class="text_highlight">50 GB</span> max file size</div>
<div><span class="text_highlight">Files never expire</span></div>
<div><span class="text_highlight">32 TB</span> transfer limit</div>
<div><span class="text_highlight">32 TB</span> storage space</div>