Support downloading files from zip files in filesystem
This commit is contained in:
@@ -46,14 +46,11 @@ const update_base = async base => {
|
||||
transfer_used = j.transfer_free + j.transfer_paid
|
||||
}
|
||||
socket.onerror = err => {
|
||||
if (socket === null) {
|
||||
return
|
||||
}
|
||||
console.error("WS error", err)
|
||||
socket.close()
|
||||
socket = null
|
||||
error_msg = "failed to get stats, retrying..."
|
||||
|
||||
close_socket()
|
||||
|
||||
window.setTimeout(() => {
|
||||
if (socket === null) {
|
||||
update_base(base)
|
||||
|
@@ -37,30 +37,35 @@ const add_styles = (style, properties) => {
|
||||
if (properties.brand_input_color) {
|
||||
style.input_background = properties.brand_input_color
|
||||
style.input_hover_background = properties.brand_input_color
|
||||
style.input_text = add_light(properties.brand_input_color, 70)
|
||||
style.input_text = add_contrast(properties.brand_input_color, 70)
|
||||
}
|
||||
if (properties.brand_highlight_color) {
|
||||
style.highlight_color = properties.brand_highlight_color
|
||||
style.highlight_background = properties.brand_highlight_color
|
||||
style.highlight_text_color = add_light(properties.brand_highlight_color, 70)
|
||||
style.link_color = properties.brand_highlight_color
|
||||
style.highlight_text_color = add_contrast(properties.brand_highlight_color, 70)
|
||||
|
||||
// If we have a body colour to compare it to we use the highlight colour
|
||||
// to generate the link colour
|
||||
if (properties.brand_body_color) {
|
||||
style.link_color = generate_link_color(properties.brand_highlight_color, properties.brand_body_color)
|
||||
}
|
||||
}
|
||||
if (properties.brand_danger_color) {
|
||||
style.danger_color = properties.brand_danger_color
|
||||
style.danger_text_color = add_light(properties.brand_danger_color, 70)
|
||||
style.danger_text_color = add_contrast(properties.brand_danger_color, 70)
|
||||
}
|
||||
if (properties.brand_background_color) {
|
||||
style.background_color = properties.brand_background_color
|
||||
style.background = properties.brand_background_color
|
||||
style.background_text_color = add_light(properties.brand_background_color, 70)
|
||||
style.background_text_color = add_contrast(properties.brand_background_color, 70)
|
||||
style.background_pattern_color = properties.brand_background_color
|
||||
}
|
||||
if (properties.brand_body_color) {
|
||||
style.body_color = properties.brand_body_color
|
||||
style.body_background = properties.brand_body_color
|
||||
style.body_text_color = add_light(properties.brand_body_color, 70)
|
||||
style.body_text_color = add_contrast(properties.brand_body_color, 70)
|
||||
style.shaded_background = set_alpha(properties.brand_body_color, 0.8)
|
||||
style.separator = add_light(properties.brand_body_color, 5)
|
||||
style.separator = add_contrast(properties.brand_body_color, 6)
|
||||
style.shadow_color = darken(properties.brand_body_color, 0.8)
|
||||
}
|
||||
if (properties.brand_card_color) {
|
||||
@@ -74,7 +79,7 @@ const add_styles = (style, properties) => {
|
||||
}
|
||||
}
|
||||
|
||||
const add_light = (color, amt) => {
|
||||
const add_contrast = (color, amt) => {
|
||||
let hsl = rgb2hsl(parse(color)) // Convert hex to hsl
|
||||
// If the lightness is less than 40 it is considered a dark colour. This
|
||||
// threshold is 40 instead of 50 because overall dark text is more legible
|
||||
@@ -99,3 +104,17 @@ const set_alpha = (color, amt) => {
|
||||
rgb.push(amt)
|
||||
return "rgba(" + rgb.join(", ") + ")"
|
||||
}
|
||||
|
||||
const generate_link_color = (link_color, body_color) => {
|
||||
let link = rgb2hsl(parse(link_color))
|
||||
let body = rgb2hsl(parse(body_color))
|
||||
|
||||
// If the body and link colours are both dark we lighten the link, and the
|
||||
// other way around too
|
||||
if (body[2] < 50 && link[2] < 50) {
|
||||
link[2] = link[2] + 40 // Dark color, add lightness
|
||||
} else if (body[2] > 50 && link[2] > 50) {
|
||||
link[2] = link[2] - 40 // Light color, remove lightness
|
||||
}
|
||||
return rgb2hex(hsl2rgb(link)) // Convert back to hex
|
||||
}
|
||||
|
@@ -119,6 +119,76 @@ const copy_magnet = () => {
|
||||
</button>
|
||||
</IconBlock>
|
||||
|
||||
<TextBlock>
|
||||
<details>
|
||||
<summary>How do I download this? (expand for more information)</summary>
|
||||
<p>
|
||||
This is a torrent file, which means you will need a torrent client to
|
||||
download it. Here are some good torrent clients for various platforms:
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="https://transmissionbt.com/download">Transmission</a> (Linux, Mac, Windows)</li>
|
||||
<li><a href="https://www.qbittorrent.org/download">qBittorrent</a> (Linux, Mac, Windows)</li>
|
||||
<li><a href="https://play.google.com/store/apps/details?id=org.proninyaroslav.libretorrent">LibreTorrent</a> (Android)</li>
|
||||
</ul>
|
||||
<p>
|
||||
After installing your torrent client you will be able to use the
|
||||
<a href={magnet}><Magnet/> Open magnet link</a>
|
||||
button to download the files in your torrent client.
|
||||
</p>
|
||||
<h3>What is a torrent?</h3>
|
||||
<p>
|
||||
<a href="https://wikipedia.org/wiki/BitTorrent">BitTorrent</a> is a
|
||||
peer-to-peer network for sharing files. This torrent file does not
|
||||
actually contain the files listed below, instead it contains
|
||||
instructions for your torrent client to download the files from
|
||||
other people who happen to be downloading the same files currently.
|
||||
This means that instead of connecting to a single server (like
|
||||
pixeldrain), you will be connecting to other people on the internet
|
||||
to download these files.
|
||||
</p>
|
||||
<p>
|
||||
Torrents are a highly efficient and free method of transferring
|
||||
files over the internet. Since the bandwidth is shared directly
|
||||
between users there is no need for expensive servers to host the
|
||||
files for you.
|
||||
</p>
|
||||
<h3>Is this safe?</h3>
|
||||
<p>
|
||||
Your torrent client will make sure that the files you receive from
|
||||
your peers are actually what they say it is. This makes it just as
|
||||
safe as any other form of downloading. Like always when downloading
|
||||
files you still need to be aware of what you are downloading. Don't
|
||||
just blindly trust any file anyone sends you.
|
||||
</p>
|
||||
<h3>Is it private?</h3>
|
||||
<p>
|
||||
When downloading a torrent file you will be part of the so-called
|
||||
'torrent swarm'. Anyone in the swarm can see each other's IP
|
||||
addresses. This is not a bad thing on its own, but there a few cases
|
||||
in which this can be abused.
|
||||
</p>
|
||||
<p>
|
||||
Anyone in the swarm will be able to see what you are downloading,
|
||||
even across different torrents. This is something to keep in mind
|
||||
when downloading torrents. If someone can link your IP address to
|
||||
your identity then there are ways to find out which files you have
|
||||
downloaded in the past (provided that your IP address has not
|
||||
changed since then).
|
||||
</p>
|
||||
<p>
|
||||
If you are downloading copyrighted material (which I do not condone)
|
||||
then rightsholders will be able to see your IP address. In most
|
||||
cases this is not a problem because your ISP will still protect your
|
||||
identity. But there are some countries (notably the USA) where your
|
||||
ISP will not respect your right to privacy and the rightsholder will
|
||||
be able to contact you. If this worries you then you should look
|
||||
into VPN services to protect your privacy, like <a
|
||||
href="https://mullvad.net">Mullvad</a>.
|
||||
</p>
|
||||
</details>
|
||||
</TextBlock>
|
||||
|
||||
{#if status === "finished"}
|
||||
<TextBlock>
|
||||
<h2>Files in this torrent</h2>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { formatDataVolume, formatDate } from "../../util/Formatting.svelte"
|
||||
import ZipItem from "./ZipItem.svelte";
|
||||
import ZipItem from "../../file_viewer/viewers/ZipItem.svelte";
|
||||
import IconBlock from "../../file_viewer/viewers/IconBlock.svelte";
|
||||
import TextBlock from "../../file_viewer/viewers/TextBlock.svelte";
|
||||
import { fs_node_icon, fs_path_url } from "../FilesystemUtil";
|
||||
@@ -18,10 +18,17 @@ let zip = {
|
||||
}
|
||||
let uncomp_size = 0
|
||||
let comp_ratio = 0
|
||||
let archive_type = ""
|
||||
|
||||
export const update = async () => {
|
||||
dispatch("loading", true)
|
||||
|
||||
if (state.base.file_type === "application/zip") {
|
||||
archive_type = "zip"
|
||||
} else if (state.base.file_type === "application/x-7z-compressed") {
|
||||
archive_type = "7z"
|
||||
}
|
||||
|
||||
try {
|
||||
let resp = await fetch(fs_path_url(state.base.path)+"?zip_info")
|
||||
|
||||
@@ -32,6 +39,13 @@ export const update = async () => {
|
||||
|
||||
zip = await resp.json()
|
||||
|
||||
// Check if the zip has the property which allows separate files to be
|
||||
// downloaded. If so then we set the download URL for each file
|
||||
if (zip.properties && zip.properties.includes("read_individual_files")) {
|
||||
// Set the download URL for each file in the zip
|
||||
recursive_set_url(fs_path_url(state.base.path)+"?zip_file=", zip)
|
||||
}
|
||||
|
||||
uncomp_size = recursive_size(zip)
|
||||
comp_ratio = (uncomp_size / state.base.file_size)
|
||||
} catch (err) {
|
||||
@@ -43,6 +57,16 @@ export const update = async () => {
|
||||
status = "finished"
|
||||
}
|
||||
|
||||
const recursive_set_url = (parent_path, file) => {
|
||||
file.download_url = parent_path
|
||||
|
||||
if (file.children) {
|
||||
Object.entries(file.children).forEach(child => {
|
||||
recursive_set_url(file.download_url + "/" + child[0], child[1])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const recursive_size = (file) => {
|
||||
let size = file.size
|
||||
|
||||
@@ -64,8 +88,14 @@ const recursive_size = (file) => {
|
||||
<h1>{state.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||
{#if archive_type === "7z"}
|
||||
This is a 7-zip archive. You will need
|
||||
<a href="https://www.7-zip.org/">7-zip</a> or compatible software to
|
||||
extract it<br/>
|
||||
{/if}
|
||||
|
||||
Compressed size: {formatDataVolume(state.base.file_size, 3)}<br/>
|
||||
Uncompressed size: {formatDataVolume(uncomp_size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
||||
Uncompressed size: {formatDataVolume(zip.size, 3)} (Ratio: {comp_ratio.toFixed(2)}x)<br/>
|
||||
Uploaded on: {formatDate(state.base.created, true, true, true)}
|
||||
<br/>
|
||||
<button class="button_highlight" on:click={() => {dispatch("download")}}>
|
||||
|
@@ -1,44 +0,0 @@
|
||||
<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>
|
Reference in New Issue
Block a user