File viewer gallery view
This commit is contained in:
@@ -286,7 +286,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
h4 {
|
h4 {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
font-family: sans-serif;
|
font-family: "light", sans-serif;
|
||||||
border-bottom: 1px var(--layer_2_color_border) solid;
|
border-bottom: 1px var(--layer_2_color_border) solid;
|
||||||
}
|
}
|
||||||
h5 {
|
h5 {
|
||||||
|
@@ -11,6 +11,7 @@ export let file = {
|
|||||||
size: 0,
|
size: 0,
|
||||||
downloads: 0,
|
downloads: 0,
|
||||||
bandwidth_used: 0,
|
bandwidth_used: 0,
|
||||||
|
bandwidth_used_paid: 0,
|
||||||
description: "",
|
description: "",
|
||||||
timeseries_href: "",
|
timeseries_href: "",
|
||||||
}
|
}
|
||||||
@@ -20,6 +21,9 @@ let view_chart
|
|||||||
|
|
||||||
$: update_charts(file.id)
|
$: update_charts(file.id)
|
||||||
let update_charts = () => {
|
let update_charts = () => {
|
||||||
|
if (file.id === "") {
|
||||||
|
return
|
||||||
|
}
|
||||||
console.log("updating graph")
|
console.log("updating graph")
|
||||||
|
|
||||||
let today = new Date()
|
let today = new Date()
|
||||||
|
@@ -1,21 +1,41 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import Spinner from "../util/Spinner.svelte"
|
||||||
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let file = {
|
export let file = {
|
||||||
id: "",
|
id: "",
|
||||||
name: "",
|
name: "",
|
||||||
get_href: "",
|
get_href: "",
|
||||||
|
can_edit: false,
|
||||||
|
}
|
||||||
|
export let list = {
|
||||||
|
id: "",
|
||||||
|
title: "",
|
||||||
|
files: [],
|
||||||
|
can_edit: false,
|
||||||
|
info_href: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_name = ""
|
let loading = false
|
||||||
let result_success = false
|
let result_success = false
|
||||||
let result_text = ""
|
let result_text = ""
|
||||||
|
|
||||||
|
let file_name = ""
|
||||||
$: update_file(file.id)
|
$: update_file(file.id)
|
||||||
let update_file = () => {
|
let update_file = () => {
|
||||||
file_name = file.name
|
file_name = file.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let list_name = ""
|
||||||
|
$: update_list(list.id)
|
||||||
|
let update_list = () => {
|
||||||
|
list_name = list.title
|
||||||
|
}
|
||||||
|
|
||||||
let rename_file = async e => {
|
let rename_file = async e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
loading = true
|
||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("action", "rename")
|
form.append("action", "rename")
|
||||||
@@ -32,6 +52,9 @@ let rename_file = async e => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
result_success = false
|
result_success = false
|
||||||
result_text = "Could not change file name: " + err
|
result_text = "Could not change file name: " + err
|
||||||
|
} finally {
|
||||||
|
loading = false
|
||||||
|
dispatch("reload")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +62,7 @@ let delete_file = async e => {
|
|||||||
if (!confirm("Are you sure you want to delete '" + file.name + "'?")) {
|
if (!confirm("Are you sure you want to delete '" + file.name + "'?")) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
loading = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(file.get_href, { method: "DELETE" });
|
const resp = await fetch(file.get_href, { method: "DELETE" });
|
||||||
@@ -51,39 +75,132 @@ let delete_file = async e => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
result_success = false
|
result_success = false
|
||||||
result_text = "Could not delete file: " + err
|
result_text = "Could not delete file: " + err
|
||||||
|
} finally {
|
||||||
|
loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rename_list = async e => {
|
||||||
|
e.preventDefault()
|
||||||
|
loading = true
|
||||||
|
|
||||||
|
let listjson = {
|
||||||
|
title: list_name,
|
||||||
|
files: [],
|
||||||
|
}
|
||||||
|
list.files.forEach(f => {
|
||||||
|
listjson.files.push({
|
||||||
|
id: f.id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch(
|
||||||
|
list.info_href,
|
||||||
|
{ method: "PUT", body: JSON.stringify(listjson) },
|
||||||
|
);
|
||||||
|
if (resp.status >= 400) {
|
||||||
|
throw (await resp.json()).message
|
||||||
|
}
|
||||||
|
|
||||||
|
result_success = true
|
||||||
|
result_text = "Album name has been changed. Reload the page to see the changes"
|
||||||
|
} catch (err) {
|
||||||
|
result_success = false
|
||||||
|
result_text = "Could not change album name: " + err
|
||||||
|
} finally {
|
||||||
|
loading = false
|
||||||
|
dispatch("reload")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let delete_list = async e => {
|
||||||
|
if (!confirm("Are you sure you want to delete '" + list.title + "'?")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch(list.info_href, { method: "DELETE" });
|
||||||
|
if (resp.status >= 400) {
|
||||||
|
throw (await resp.json()).message
|
||||||
|
}
|
||||||
|
|
||||||
|
result_success = true
|
||||||
|
result_text = "This album has been deleted, you can close the page"
|
||||||
|
} catch (err) {
|
||||||
|
result_success = false
|
||||||
|
result_text = "Could not delete album: " + err
|
||||||
|
} finally {
|
||||||
|
loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
{#if loading}
|
||||||
|
<div class="spinner_container">
|
||||||
|
<Spinner></Spinner>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{#if result_text !== ""}
|
{#if result_text !== ""}
|
||||||
<div class:highlight_green={result_success} class:highligt_red={!result_success}>
|
<div class:highlight_green={result_success} class:highligt_red={!result_success}>
|
||||||
{result_text}
|
{result_text}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<h3>Rename</h3>
|
{#if list.can_edit}
|
||||||
<form on:submit={rename_file} style="display: flex; width: 100%">
|
<h3>Edit album</h3>
|
||||||
|
<h4>Rename</h4>
|
||||||
|
<form on:submit={rename_list} class="indent" style="display: flex;">
|
||||||
|
<input bind:value={list_name} type="text" style="flex: 1 1 auto"/>
|
||||||
|
<button type="submit" style="flex: 0 0 auto">
|
||||||
|
<i class="icon">save</i> Save
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<h4>Delete</h4>
|
||||||
|
<p>
|
||||||
|
When you delete an album the files in the album will not be deleted,
|
||||||
|
only the album itself.
|
||||||
|
</p>
|
||||||
|
<div class="indent">
|
||||||
|
<button on:click={delete_list} class="button_red">
|
||||||
|
<i class="icon small">delete</i> Delete album
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if file.can_edit}
|
||||||
|
<h3>Edit file</h3>
|
||||||
|
<h4>Rename</h4>
|
||||||
|
<form on:submit={rename_file} class="indent" style="display: flex;">
|
||||||
<input bind:value={file_name} type="text" style="flex: 1 1 auto"/>
|
<input bind:value={file_name} type="text" style="flex: 1 1 auto"/>
|
||||||
<button type="submit" style="flex: 0 0 auto">
|
<button type="submit" style="flex: 0 0 auto">
|
||||||
<i class="icon">save</i> Save
|
<i class="icon">save</i> Save
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<h3>Delete</h3>
|
<h4>Delete</h4>
|
||||||
<p>
|
<p>
|
||||||
When you delete a file it cannot be recovered.
|
When you delete a file it cannot be recovered.
|
||||||
Nobody will be able to download it and the link will
|
Nobody will be able to download it and the link will
|
||||||
stop working. The file will also disappear from any
|
stop working. The file will also disappear from any
|
||||||
lists it's contained in.
|
lists it's contained in.
|
||||||
</p>
|
</p>
|
||||||
<div style="text-align: center;">
|
<div class="indent">
|
||||||
<button on:click={delete_file} class="button_red">
|
<button on:click={delete_file} class="button_red">
|
||||||
<i class="icon small">delete</i> Delete this file
|
<i class="icon small">delete</i> Delete file
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.spinner_container {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -15,46 +15,60 @@ import AdHead from "./AdHead.svelte";
|
|||||||
import AdLeaderboard from "./AdLeaderboard.svelte";
|
import AdLeaderboard from "./AdLeaderboard.svelte";
|
||||||
import AdSkyscraper from "./AdSkyscraper.svelte";
|
import AdSkyscraper from "./AdSkyscraper.svelte";
|
||||||
import Sharebar from "./Sharebar.svelte";
|
import Sharebar from "./Sharebar.svelte";
|
||||||
|
import GalleryView from "./GalleryView.svelte";
|
||||||
|
import Spinner from "../util/Spinner.svelte";
|
||||||
|
|
||||||
let is_list = false
|
const file_struct = {
|
||||||
let embedded = false
|
|
||||||
let view_token = ""
|
|
||||||
let current_file = {
|
|
||||||
id: "",
|
id: "",
|
||||||
name: "loading...",
|
name: "",
|
||||||
size: 0,
|
size: 0,
|
||||||
bandwidth_used: 0,
|
bandwidth_used: 0,
|
||||||
|
bandwidth_used_paid: 0,
|
||||||
downloads: 0,
|
downloads: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
mime_type: "",
|
mime_type: "",
|
||||||
availability: "",
|
availability: "",
|
||||||
|
abuse_type: "",
|
||||||
show_ads: false,
|
show_ads: false,
|
||||||
can_edit: false,
|
can_edit: false,
|
||||||
get_href: "",
|
get_href: "",
|
||||||
|
info_href: "",
|
||||||
download_href: "",
|
download_href: "",
|
||||||
icon_href: "",
|
icon_href: "",
|
||||||
}
|
}
|
||||||
let current_list = {
|
const list_struct = {
|
||||||
id: "",
|
id: "",
|
||||||
title: "",
|
title: "",
|
||||||
files: [],
|
files: [],
|
||||||
download_href: "",
|
download_href: "",
|
||||||
|
info_href: "",
|
||||||
|
can_edit: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let loading = true
|
||||||
|
let embedded = false
|
||||||
|
let view_token = ""
|
||||||
|
let ads_enabled = false
|
||||||
|
|
||||||
|
let view = "" // file or gallery
|
||||||
|
let file = file_struct
|
||||||
|
let list = list_struct
|
||||||
|
let is_list = false
|
||||||
|
|
||||||
let button_home
|
let button_home
|
||||||
let list_navigator
|
let list_navigator
|
||||||
let list_shuffle = false
|
let list_shuffle = false
|
||||||
let toggle_shuffle = () => {
|
let toggle_shuffle = () => {
|
||||||
list_shuffle = !list_shuffle
|
list_shuffle = !list_shuffle
|
||||||
list_navigator.set_shuffle(list_shuffle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sharebar
|
let sharebar
|
||||||
let sharebar_visible = false
|
let sharebar_visible = false
|
||||||
let toggle_sharebar = () => {
|
let toggle_sharebar = () => {
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
let name = current_file.name
|
let name = file.name
|
||||||
if (is_list) {
|
if (is_list) {
|
||||||
name = current_list.title
|
name = list.title
|
||||||
}
|
}
|
||||||
|
|
||||||
navigator.share({
|
navigator.share({
|
||||||
@@ -104,40 +118,109 @@ onMount(() => {
|
|||||||
if (viewer_data.type === "list") {
|
if (viewer_data.type === "list") {
|
||||||
open_list(viewer_data.api_response)
|
open_list(viewer_data.api_response)
|
||||||
} else {
|
} else {
|
||||||
open_file(viewer_data.api_response)
|
list.files = [viewer_data.api_response]
|
||||||
|
open_file_index(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ads_enabled = list.files[0].show_ads
|
||||||
|
loading = false
|
||||||
|
})
|
||||||
|
const reload = async () => {
|
||||||
|
loading = true
|
||||||
|
if (is_list) {
|
||||||
|
try {
|
||||||
|
const resp = await fetch(list.info_href);
|
||||||
|
if (resp.status >= 400) {
|
||||||
|
throw (await resp.json()).message
|
||||||
|
}
|
||||||
|
|
||||||
|
open_list(await resp.json())
|
||||||
|
} catch (err) {
|
||||||
|
alert(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const resp = await fetch(file.info_href);
|
||||||
|
if (resp.status >= 400) {
|
||||||
|
throw (await resp.json()).message
|
||||||
|
}
|
||||||
|
|
||||||
|
list.files = [await resp.json()]
|
||||||
|
open_file_index(0)
|
||||||
|
} catch (err) {
|
||||||
|
alert(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const open_list = async l => {
|
||||||
|
l.download_href = window.api_endpoint+"/list/"+l.id+"/zip"
|
||||||
|
l.info_href = window.api_endpoint+"/list/"+l.id
|
||||||
|
l.files.forEach(f => {
|
||||||
|
file_set_href(f)
|
||||||
})
|
})
|
||||||
|
|
||||||
const open_list = (list) => {
|
list = l
|
||||||
list.download_href = window.api_endpoint+"/list/"+list.id+"/zip"
|
|
||||||
list.files.forEach(file => {
|
|
||||||
file_set_href(file)
|
|
||||||
})
|
|
||||||
|
|
||||||
current_list = list
|
|
||||||
|
|
||||||
// Setting is_list to true activates the ListNavgator, which makes sure the
|
// Setting is_list to true activates the ListNavgator, which makes sure the
|
||||||
// correct file is opened
|
// correct file is opened
|
||||||
is_list = true
|
is_list = true
|
||||||
|
|
||||||
|
// Skip to the file defined in the link hash
|
||||||
|
let matches = location.hash.match(new RegExp('item=([^&]*)'))
|
||||||
|
let hashID = parseInt(matches ? matches[1] : null)
|
||||||
|
if (Number.isInteger(hashID)) {
|
||||||
|
// The URL contains an item number. Navigate to that item
|
||||||
|
view = "file"
|
||||||
|
open_file_index(parseInt(hashID))
|
||||||
|
} else {
|
||||||
|
view = "gallery"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const open_file_index = async index => {
|
||||||
|
if (index >= list.files.length) {
|
||||||
|
index = 0
|
||||||
|
} else if (index < 0) {
|
||||||
|
index = list.files.length - 1
|
||||||
|
}
|
||||||
|
console.debug("received request to open file", index)
|
||||||
|
|
||||||
|
file_set_href(list.files[index])
|
||||||
|
file = list.files[index]
|
||||||
|
view = "file"
|
||||||
|
|
||||||
|
if (is_list) {
|
||||||
|
// Wait for the ListNavigator to render
|
||||||
|
await tick()
|
||||||
|
|
||||||
|
// Update the URL
|
||||||
|
location.replace("#item=" + index)
|
||||||
|
list_navigator.set_item(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
const open_file = (file) => {
|
|
||||||
file_set_href(file)
|
|
||||||
current_file = file
|
|
||||||
|
|
||||||
// Register a file view
|
// Register a file view
|
||||||
fetch(window.api_endpoint + "/file/" + current_file.id + "/view", {
|
fetch(window.api_endpoint + "/file/" + file.id + "/view", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
body: "token=" + view_token
|
body: "token=" + view_token
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const file_set_href = f => {
|
||||||
const file_set_href = file => {
|
f.get_href = window.api_endpoint+"/file/"+f.id
|
||||||
file.get_href = window.api_endpoint+"/file/"+file.id
|
f.info_href = window.api_endpoint+"/file/"+f.id+"/info"
|
||||||
file.download_href = window.api_endpoint+"/file/"+file.id+"?download"
|
f.download_href = window.api_endpoint+"/file/"+f.id+"?download"
|
||||||
file.icon_href = window.api_endpoint+"/file/"+file.id+"/thumbnail"
|
f.icon_href = window.api_endpoint+"/file/"+f.id+"/thumbnail"
|
||||||
file.timeseries_href = window.api_endpoint+"/file/"+file.id+"/timeseries"
|
f.timeseries_href = window.api_endpoint+"/file/"+f.id+"/timeseries"
|
||||||
|
}
|
||||||
|
const toggle_gallery = () => {
|
||||||
|
if (view === "gallery") {
|
||||||
|
open_file_index(0)
|
||||||
|
} else {
|
||||||
|
location.replace("#gallery")
|
||||||
|
view = "gallery"
|
||||||
|
file = file_struct // Empty the file struct
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let download_frame
|
let download_frame
|
||||||
@@ -149,12 +232,12 @@ let captcha_container
|
|||||||
const download = () => {
|
const download = () => {
|
||||||
if (!window.viewer_data.captcha_key) {
|
if (!window.viewer_data.captcha_key) {
|
||||||
console.debug("Server doesn't support captcha, starting download")
|
console.debug("Server doesn't support captcha, starting download")
|
||||||
download_frame.src = current_file.download_href
|
download_frame.src = file.download_href
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (current_file.availability === "") {
|
if (file.availability === "") {
|
||||||
console.debug("File is available, starting download")
|
console.debug("File is available, starting download")
|
||||||
download_frame.src = current_file.download_href
|
download_frame.src = file.download_href
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +247,7 @@ const download = () => {
|
|||||||
// we trigger the download using the captcha token Google provided us with
|
// we trigger the download using the captcha token Google provided us with
|
||||||
let captcha_complete_callback = token => {
|
let captcha_complete_callback = token => {
|
||||||
// Download the file using the recaptcha token
|
// Download the file using the recaptcha token
|
||||||
download_frame.src = current_file.download_href + "&recaptcha_response=" + token
|
download_frame.src = file.download_href + "&recaptcha_response=" + token
|
||||||
download_captcha_window.hide()
|
download_captcha_window.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,10 +263,10 @@ const download = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_file.availability === "file_rate_limited_captcha_required") {
|
if (file.availability === "file_rate_limited_captcha_required") {
|
||||||
captcha_type = "rate_limit"
|
captcha_type = "rate_limit"
|
||||||
captcha_window_title = "Rate limiting enabled!"
|
captcha_window_title = "Rate limiting enabled!"
|
||||||
} else if (current_file.availability === "virus_detected_captcha_required") {
|
} else if (file.availability === "virus_detected_captcha_required") {
|
||||||
captcha_type = "malware"
|
captcha_type = "malware"
|
||||||
captcha_window_title = "Malware warning!"
|
captcha_window_title = "Malware warning!"
|
||||||
}
|
}
|
||||||
@@ -202,7 +285,7 @@ const download = () => {
|
|||||||
}
|
}
|
||||||
const download_list = () => {
|
const download_list = () => {
|
||||||
if (is_list) {
|
if (is_list) {
|
||||||
download_frame.src = current_list.download_href
|
download_frame.src = list.download_href
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,12 +316,12 @@ const copy_url = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const grab_file = async () => {
|
const grab_file = async () => {
|
||||||
if (!window.user_authenticated || current_file.can_edit) {
|
if (!window.user_authenticated || file.can_edit) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("grab_file", current_file.id)
|
form.append("grab_file", file.id)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(
|
const resp = await fetch(
|
||||||
@@ -297,7 +380,7 @@ const keyboard_event = evt => {
|
|||||||
details_window.toggle()
|
details_window.toggle()
|
||||||
break
|
break
|
||||||
case 69: // E to open the edit window
|
case 69: // E to open the edit window
|
||||||
if (current_file.can_edit) {
|
if (file.can_edit) {
|
||||||
edit_window.toggle()
|
edit_window.toggle()
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -321,6 +404,12 @@ const keyboard_event = evt => {
|
|||||||
<!-- Head elements for the ads -->
|
<!-- Head elements for the ads -->
|
||||||
<AdHead></AdHead>
|
<AdHead></AdHead>
|
||||||
|
|
||||||
|
{#if loading}
|
||||||
|
<div class="spinner_container">
|
||||||
|
<Spinner></Spinner>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div id="headerbar" class="headerbar" class:embedded>
|
<div id="headerbar" class="headerbar" class:embedded>
|
||||||
<button on:click={toolbar_toggle} class="button_toggle_toolbar round" class:button_highlight={toolbar_visible}>
|
<button on:click={toolbar_toggle} class="button_toggle_toolbar round" class:button_highlight={toolbar_visible}>
|
||||||
<i class="icon">menu</i>
|
<i class="icon">menu</i>
|
||||||
@@ -329,8 +418,8 @@ const keyboard_event = evt => {
|
|||||||
<PixeldrainLogo style="height: 1.6em; width: 1.6em; margin: 0 4px 0 0;"></PixeldrainLogo>
|
<PixeldrainLogo style="height: 1.6em; width: 1.6em; margin: 0 4px 0 0;"></PixeldrainLogo>
|
||||||
</a>
|
</a>
|
||||||
<div id="file_viewer_headerbar_title" class="file_viewer_headerbar_title">
|
<div id="file_viewer_headerbar_title" class="file_viewer_headerbar_title">
|
||||||
<div id="list_title">{current_list.title}</div>
|
{#if list.title !== ""}{list.title}<br/>{/if}
|
||||||
<div id="lile_title">{current_file.name}</div>
|
{#if file.name !== ""}{file.name}{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if embedded && supports_fullscreen}
|
{#if embedded && supports_fullscreen}
|
||||||
<button class="round" on:click={toggle_fullscreen}>
|
<button class="round" on:click={toggle_fullscreen}>
|
||||||
@@ -339,27 +428,43 @@ const keyboard_event = evt => {
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if is_list}
|
{#if is_list && view === "file"}
|
||||||
<ListNavigator bind:this={list_navigator} files={current_list.files} on:set_file={(e) => { open_file(e.detail) }}></ListNavigator>
|
<ListNavigator
|
||||||
|
bind:this={list_navigator}
|
||||||
|
files={list.files}
|
||||||
|
shuffle={list_shuffle}
|
||||||
|
on:set_file={e => { open_file_index(e.detail) }}>
|
||||||
|
</ListNavigator>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div id="file_preview_window" class="file_preview_window">
|
<div id="file_preview_window" class="file_preview_window">
|
||||||
<div id="toolbar" class="toolbar" class:toolbar_visible><div><div>
|
<div id="toolbar" class="toolbar" class:toolbar_visible><div><div>
|
||||||
<FileStats file={current_file}></FileStats>
|
{#if is_list}
|
||||||
|
<button on:click={toggle_gallery} class="toolbar_button button_full_width" class:button_highlight={view === "gallery"}>
|
||||||
|
<i class="icon">photo_library</i>
|
||||||
|
Gallery
|
||||||
|
</button>
|
||||||
<hr/>
|
<hr/>
|
||||||
{#if current_file.abuse_type === ""}
|
{/if}
|
||||||
|
|
||||||
|
{#if view === "file"}
|
||||||
|
<FileStats file={file}></FileStats>
|
||||||
|
<hr/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if file.abuse_type === "" && view === "file"}
|
||||||
<button on:click={download} class="toolbar_button button_full_width">
|
<button on:click={download} class="toolbar_button button_full_width">
|
||||||
<i class="icon">save</i>
|
<i class="icon">download</i>
|
||||||
<span>Download</span>
|
<span>Download</span>
|
||||||
</button>
|
</button>
|
||||||
{#if is_list}
|
{/if}
|
||||||
|
{#if file.abuse_type === "" && is_list}
|
||||||
<button on:click={download_list} class="toolbar_button button_full_width">
|
<button on:click={download_list} class="toolbar_button button_full_width">
|
||||||
<i class="icon">save</i>
|
<i class="icon">download</i>
|
||||||
<span>DL all files</span>
|
<span>DL all files</span>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
|
||||||
<button on:click={copy_url}
|
<button on:click={copy_url}
|
||||||
class="toolbar_button button_full_width"
|
class="toolbar_button button_full_width"
|
||||||
class:button_highlight={copy_url_status === "copied"}
|
class:button_highlight={copy_url_status === "copied"}
|
||||||
@@ -375,21 +480,23 @@ const keyboard_event = evt => {
|
|||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button on:click={toggle_sharebar} class="toolbar_button button_full_width" class:button_highlight={sharebar_visible}>
|
<button on:click={toggle_sharebar} class="toolbar_button button_full_width" class:button_highlight={sharebar_visible}>
|
||||||
<i class="icon">share</i>
|
<i class="icon">share</i>
|
||||||
<span>Share</span>
|
<span>Share</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="toolbar_button button_full_width" on:click={qr_window.toggle} class:button_highlight={qr_visible}>
|
<button class="toolbar_button button_full_width" on:click={qr_window.toggle} class:button_highlight={qr_visible}>
|
||||||
<i class="icon">qr_code</i>
|
<i class="icon">qr_code</i>
|
||||||
<span>QR code</span>
|
<span>QR code</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if is_list}
|
{#if is_list}
|
||||||
<button
|
<button
|
||||||
class="toolbar_button button_full_width"
|
class="toolbar_button button_full_width"
|
||||||
title="Randomize the order of the files in this list"
|
title="Randomize the order of the files in this list"
|
||||||
class:button_highlight={list_shuffle}
|
class:button_highlight={list_shuffle}
|
||||||
on:click={toggle_shuffle}
|
on:click={toggle_shuffle}>
|
||||||
>
|
|
||||||
<i class="icon">shuffle</i>
|
<i class="icon">shuffle</i>
|
||||||
{#if list_shuffle}
|
{#if list_shuffle}
|
||||||
<span>Shuffle ☑</span>
|
<span>Shuffle ☑</span>
|
||||||
@@ -398,46 +505,65 @@ const keyboard_event = evt => {
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if view === "file"}
|
||||||
<button class="toolbar_button button_full_width" on:click={details_window.toggle} class:button_highlight={details_visible}>
|
<button class="toolbar_button button_full_width" on:click={details_window.toggle} class:button_highlight={details_visible}>
|
||||||
<i class="icon">help</i>
|
<i class="icon">help</i>
|
||||||
<span>Deta<u>i</u>ls</span>
|
<span>Deta<u>i</u>ls</span>
|
||||||
</button>
|
</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
{#if current_file.can_edit}
|
|
||||||
|
{#if file.can_edit || list.can_edit}
|
||||||
<button class="toolbar_button button_full_width" on:click={edit_window.toggle} class:button_highlight={edit_visible}>
|
<button class="toolbar_button button_full_width" on:click={edit_window.toggle} class:button_highlight={edit_visible}>
|
||||||
<i class="icon">edit</i>
|
<i class="icon">edit</i>
|
||||||
<span><u>E</u>dit</span>
|
<span><u>E</u>dit</span>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if window.user_authenticated && !current_file.can_edit}
|
|
||||||
|
{#if view === "file" && window.user_authenticated && !file.can_edit}
|
||||||
<button on:click={grab_file} class="toolbar_button button_full_width" title="Copy this file to your own pixeldrain account">
|
<button on:click={grab_file} class="toolbar_button button_full_width" title="Copy this file to your own pixeldrain account">
|
||||||
<i class="icon">save_alt</i>
|
<i class="icon">save_alt</i>
|
||||||
<span><u>G</u>rab file</span>
|
<span><u>G</u>rab file</span>
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button class="toolbar_button button_full_width" title="Include this file in your own webpages" on:click={embed_window.toggle} class:button_highlight={embed_visible}>
|
<button class="toolbar_button button_full_width" title="Include this file in your own webpages" on:click={embed_window.toggle} class:button_highlight={embed_visible}>
|
||||||
<i class="icon">code</i>
|
<i class="icon">code</i>
|
||||||
<span>E<u>m</u>bed</span>
|
<span>E<u>m</u>bed</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{#if view === "file"}
|
||||||
<button class="toolbar_button button_full_width" title="Report abuse in this file" on:click={report_window.toggle} class:button_highlight={report_visible}>
|
<button class="toolbar_button button_full_width" title="Report abuse in this file" on:click={report_window.toggle} class:button_highlight={report_visible}>
|
||||||
<i class="icon">flag</i>
|
<i class="icon">flag</i>
|
||||||
<span>Report</span>
|
<span>Report</span>
|
||||||
</button>
|
</button>
|
||||||
|
{/if}
|
||||||
<br/>
|
<br/>
|
||||||
</div></div></div>
|
</div></div></div>
|
||||||
|
|
||||||
<Sharebar bind:this={sharebar}></Sharebar>
|
<Sharebar bind:this={sharebar}></Sharebar>
|
||||||
|
|
||||||
<div id="file_preview" class="file_preview checkers" class:toolbar_visible class:skyscraper_visible>
|
<div id="file_preview" class="file_preview checkers" class:toolbar_visible class:skyscraper_visible>
|
||||||
|
{#if view === "file"}
|
||||||
<FilePreview
|
<FilePreview
|
||||||
file={current_file}
|
file={file}
|
||||||
on:download={download}
|
on:download={download}
|
||||||
on:prev={() => { if (list_navigator) { list_navigator.prev() }}}
|
on:prev={() => { if (list_navigator) { list_navigator.prev() }}}
|
||||||
on:next={() => { if (list_navigator) { list_navigator.next() }}}>
|
on:next={() => { if (list_navigator) { list_navigator.next() }}}>
|
||||||
</FilePreview>
|
</FilePreview>
|
||||||
|
{:else if view === "gallery"}
|
||||||
|
<GalleryView
|
||||||
|
list={list}
|
||||||
|
on:set_file={e => { open_file_index(e.detail) }}
|
||||||
|
on:reload={reload}
|
||||||
|
on:loading={e => {loading = e.detail}}>
|
||||||
|
</GalleryView>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if current_file.show_ads}
|
{#if ads_enabled}
|
||||||
<AdSkyscraper on:visibility={e => {skyscraper_visible = e.detail}}></AdSkyscraper>
|
<AdSkyscraper on:visibility={e => {skyscraper_visible = e.detail}}></AdSkyscraper>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -445,36 +571,36 @@ const keyboard_event = evt => {
|
|||||||
<iframe bind:this={download_frame} title="File download frame" style="display: none; width: 1px; height: 1px;"></iframe>
|
<iframe bind:this={download_frame} title="File download frame" style="display: none; width: 1px; height: 1px;"></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if current_file.show_ads}
|
{#if ads_enabled}
|
||||||
<AdLeaderboard></AdLeaderboard>
|
<AdLeaderboard></AdLeaderboard>
|
||||||
{:else if !window.viewer_data.user_ads_enabled && !embedded}
|
{:else if !window.viewer_data.user_ads_enabled && !embedded}
|
||||||
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
||||||
Thank you for supporting pixeldrain!
|
Thank you for supporting pixeldrain!
|
||||||
</div>
|
</div>
|
||||||
{:else if !current_file.show_ads && !embedded}
|
{:else if !ads_enabled && !embedded}
|
||||||
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
<div style="text-align: center; line-height: 1.3em; font-size: 13px;">
|
||||||
The uploader of this file disabled advertisements. You can do the same for <a href="/#pro">only €2 per month</a>!
|
The uploader of this file disabled advertisements. You can do the same for <a href="/#pro">only €2 per month</a>!
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Modal bind:this={details_window} on:is_visible={e => {details_visible = e.detail}} title="File details" width="1200px">
|
<Modal bind:this={details_window} on:is_visible={e => {details_visible = e.detail}} title="File details" width="1200px">
|
||||||
<DetailsWindow file={current_file}></DetailsWindow>
|
<DetailsWindow file={file}></DetailsWindow>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={qr_window} on:is_visible={e => {qr_visible = e.detail}} title="QR code" width="500px">
|
<Modal bind:this={qr_window} on:is_visible={e => {qr_visible = e.detail}} title="QR code" width="500px">
|
||||||
<img src="{window.api_endpoint}/misc/qr?text={encodeURIComponent(window.location.href)}" alt="QR code" style="display: block; width: 100%;"/>
|
<img src="{window.api_endpoint}/misc/qr?text={encodeURIComponent(window.location.href)}" alt="QR code" style="display: block; width: 100%;"/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={edit_window} on:is_visible={e => {edit_visible = e.detail}} title={"Editing "+current_file.name}>
|
<Modal bind:this={edit_window} on:is_visible={e => {edit_visible = e.detail}} title={"Editing "+file.name}>
|
||||||
<EditWindow file={current_file} list={current_list}></EditWindow>
|
<EditWindow file={file} list={list} on:reload={reload}></EditWindow>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={embed_window} on:is_visible={e => {embed_visible = e.detail}} title="Embed file" width="850px">
|
<Modal bind:this={embed_window} on:is_visible={e => {embed_visible = e.detail}} title="Embed file" width="850px">
|
||||||
<EmbedWindow file={current_file} list={current_list}></EmbedWindow>
|
<EmbedWindow file={file} list={list}></EmbedWindow>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={report_window} on:is_visible={e => {report_visible = e.detail}} title="Report abuse" width="800px">
|
<Modal bind:this={report_window} on:is_visible={e => {report_visible = e.detail}} title="Report abuse" width="800px">
|
||||||
<ReportWindow file={current_file} list={current_list}></ReportWindow>
|
<ReportWindow file={file} list={list}></ReportWindow>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={download_captcha_window} title={captcha_window_title} width="500px">
|
<Modal bind:this={download_captcha_window} title={captcha_window_title} width="500px">
|
||||||
@@ -498,17 +624,22 @@ const keyboard_event = evt => {
|
|||||||
<IntroPopup target={button_home}></IntroPopup>
|
<IntroPopup target={button_home}></IntroPopup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Viewer container */
|
.spinner_container {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
||||||
.file_viewer {
|
.file_viewer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
top: 0;
|
width: 100%;
|
||||||
right: 0;
|
height: 100%;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: var(--layer_2_color);
|
background-color: var(--layer_2_color);
|
||||||
}
|
}
|
||||||
@@ -582,7 +713,7 @@ const keyboard_event = evt => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
transition: left 0.5s, right 0.5s;
|
transition: left 0.5s, right 0.5s;
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
box-shadow: inset 2px 2px 10px 2px var(--shadow_color);
|
box-shadow: inset 2px 2px 10px 2px var(--shadow_color);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
|
120
svelte/src/file_viewer/GalleryView.svelte
Normal file
120
svelte/src/file_viewer/GalleryView.svelte
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<script>
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
export let list = {
|
||||||
|
id: "",
|
||||||
|
title: "",
|
||||||
|
files: [],
|
||||||
|
download_href: "",
|
||||||
|
info_href: "",
|
||||||
|
can_edit: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const click_file = index => {
|
||||||
|
dispatch("set_file", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
const delete_file = async index => {
|
||||||
|
dispatch("loading", true)
|
||||||
|
|
||||||
|
let listjson = {
|
||||||
|
title: list.title,
|
||||||
|
files: [],
|
||||||
|
}
|
||||||
|
list.files.forEach((f, idx) => {
|
||||||
|
if (idx !== index) {
|
||||||
|
listjson.files.push({
|
||||||
|
id: f.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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 {
|
||||||
|
dispatch("reload")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="gallery">
|
||||||
|
{#each list.files as file, index}
|
||||||
|
<div class="file" on:click={() => {click_file(index)}}>
|
||||||
|
<div
|
||||||
|
class="icon_container"
|
||||||
|
class:editing={list.can_edit}
|
||||||
|
style="background-image: url('{file.icon_href}?width=256&height=256');">
|
||||||
|
{#if list.can_edit}
|
||||||
|
<!-- <i class="icon" style="cursor: grab;">drag_indicator</i>
|
||||||
|
<i class="icon">chevron_left</i>
|
||||||
|
<i class="icon">chevron_right</i> -->
|
||||||
|
<i class="icon" on:click|stopPropagation={() => {delete_file(index)}}>delete</i>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{file.name}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<!-- {#if list.can_edit}
|
||||||
|
<div class="file" style="font-size: 1.5em; padding-top: 2.5em; cursor: pointer;">
|
||||||
|
<i class="icon">add</i>
|
||||||
|
<br/>
|
||||||
|
Add files
|
||||||
|
</div>
|
||||||
|
{/if} -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.gallery{
|
||||||
|
padding: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.file{
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 200px;
|
||||||
|
max-width: 90%;
|
||||||
|
height: 200px;
|
||||||
|
margin: 8px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 2px 2px 8px 0 var(--shadow_color);
|
||||||
|
background-color: var(--layer_3_color);
|
||||||
|
word-break: break-all;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.2em;
|
||||||
|
display: inline-block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.file:hover {
|
||||||
|
box-shadow: 0 0 2px 2px var(--highlight_color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.icon_container {
|
||||||
|
width: 100%;
|
||||||
|
height: 136px;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.icon_container.editing {
|
||||||
|
box-shadow: inset 0 60px 40px -40px #000000;
|
||||||
|
}
|
||||||
|
.icon_container > i:hover {
|
||||||
|
color: var(--highlight_color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher, onMount } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
let dispatch = createEventDispatcher()
|
let dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@@ -7,27 +7,17 @@ export let files = []
|
|||||||
let file_list_div
|
let file_list_div
|
||||||
let selected_file_index = 0
|
let selected_file_index = 0
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
// Skip to the file defined in the link hash
|
|
||||||
let matches = location.hash.match(new RegExp('item=([^&]*)'))
|
|
||||||
let hashID = matches ? matches[1] : null
|
|
||||||
let idx = 0
|
|
||||||
if (Number.isInteger(parseInt(hashID))) {
|
|
||||||
idx = parseInt(hashID)
|
|
||||||
}
|
|
||||||
|
|
||||||
set_item(idx)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const next = () => {
|
export const next = () => {
|
||||||
if (shuffle) {
|
if (shuffle) {
|
||||||
rand_item()
|
rand_item()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
set_item(selected_file_index+1)
|
select_item_event(selected_file_index+1)
|
||||||
|
}
|
||||||
|
export const prev = () => {
|
||||||
|
select_item_event(selected_file_index-1)
|
||||||
}
|
}
|
||||||
export const prev = () => { set_item(selected_file_index-1) }
|
|
||||||
|
|
||||||
let history = []
|
let history = []
|
||||||
export const rand_item = () => {
|
export const rand_item = () => {
|
||||||
@@ -41,23 +31,15 @@ export const rand_item = () => {
|
|||||||
set_item(rand)
|
set_item(rand)
|
||||||
}
|
}
|
||||||
|
|
||||||
let shuffle = false
|
export let shuffle = false
|
||||||
export const set_shuffle = s => { shuffle = s }
|
|
||||||
|
|
||||||
export const set_item = idx => {
|
export const set_item = idx => {
|
||||||
if (idx >= files.length) {
|
|
||||||
idx = 0
|
|
||||||
} else if (idx < 0) {
|
|
||||||
idx = files.length - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the class from the previous selected file
|
// Remove the class from the previous selected file
|
||||||
files[selected_file_index].selected = false
|
|
||||||
selected_file_index = idx
|
selected_file_index = idx
|
||||||
files[idx].selected = true
|
files.forEach((f, i) => {
|
||||||
|
f.selected = selected_file_index === i
|
||||||
// Update the URL
|
})
|
||||||
location.hash = "item=" + idx
|
files = files
|
||||||
|
|
||||||
// Add item to history
|
// Add item to history
|
||||||
if(history.length >= (files.length - 6)){
|
if(history.length >= (files.length - 6)){
|
||||||
@@ -65,8 +47,6 @@ export const set_item = idx => {
|
|||||||
}
|
}
|
||||||
history.push(idx)
|
history.push(idx)
|
||||||
|
|
||||||
dispatch("set_file", files[idx])
|
|
||||||
|
|
||||||
// Smoothly scroll the navigator to the correct element
|
// Smoothly scroll the navigator to the correct element
|
||||||
let selected_file = file_list_div.children[idx]
|
let selected_file = file_list_div.children[idx]
|
||||||
let cst = window.getComputedStyle(selected_file)
|
let cst = window.getComputedStyle(selected_file)
|
||||||
@@ -88,11 +68,20 @@ export const set_item = idx => {
|
|||||||
}
|
}
|
||||||
animateScroll(start, 0)
|
animateScroll(start, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// select_item signals to the FileViewer that the file needs to be changed. The
|
||||||
|
// FileViewer then calls set_item if the change has been approved. ListNavigator
|
||||||
|
// cannot call set_item itself because it will cause a loop.
|
||||||
|
const select_item_event = idx => {
|
||||||
|
dispatch("set_file", idx)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={file_list_div} class="list_navigator">
|
<div bind:this={file_list_div} class="list_navigator">
|
||||||
{#each files as file, index}
|
{#each files as file, index}
|
||||||
<div class="list_item file_button" class:file_button_selected={file.selected} on:click={() => { set_item(index) }}>
|
<div class="list_item file_button"
|
||||||
|
class:file_button_selected={file.selected}
|
||||||
|
on:click={() => { select_item_event(index) }}>
|
||||||
<img src={file.icon_href+"?width=48&height=48"} alt={file.name} class="list_item_thumbnail" />
|
<img src={file.icon_href+"?width=48&height=48"} alt={file.name} class="list_item_thumbnail" />
|
||||||
{file.name}
|
{file.name}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -23,16 +23,22 @@ export let file = {
|
|||||||
<button class="button_highlight" on:click={() => {dispatch("download")}}>
|
<button class="button_highlight" on:click={() => {dispatch("download")}}>
|
||||||
<i class="icon">save</i> Download
|
<i class="icon">save</i> Download
|
||||||
</button>
|
</button>
|
||||||
{#if file.size > 1e9}
|
</div>
|
||||||
|
{#if file.size > 5e8}
|
||||||
|
<br/>
|
||||||
|
<div class="description" style="max-width: 700px; text-align: center;">
|
||||||
|
<!-- If the file is larger than 500 MB-->
|
||||||
<hr/>
|
<hr/>
|
||||||
Your download speed is currently limited to 4 MiB/s. Downloading this
|
Your download speed is currently limited to 4 MiB/s. Downloading this
|
||||||
file for free will take {formatDuration((file.size/4194304)*1000)}.
|
file for free will take at least
|
||||||
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12" class="button">
|
{formatDuration((file.size/4194304)*1000)}.
|
||||||
Upgrade to Pro
|
You can
|
||||||
|
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12">
|
||||||
|
upgrade to Pro
|
||||||
</a>
|
</a>
|
||||||
to download at the fastest speed available.
|
to download at the fastest speed available.
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@@ -72,7 +72,7 @@ let download = () => { dispatch("download", {}) }
|
|||||||
{:else}
|
{:else}
|
||||||
<h1>This is a video file on pixeldrain</h1>
|
<h1>This is a video file on pixeldrain</h1>
|
||||||
<img src={file.icon_href} alt="Video icon" style="display: inline-block; vertical-align: top;">
|
<img src={file.icon_href} alt="Video icon" style="display: inline-block; vertical-align: top;">
|
||||||
<div style="display: inline-block; text-align: left; padding-left: 8px; vertical-align: middle; max-width: 600px;">
|
<div class="description">
|
||||||
The online video player on pixeldrain has been disabled due to
|
The online video player on pixeldrain has been disabled due to
|
||||||
repeated abuse. You can still watch videos online by upgrading to
|
repeated abuse. You can still watch videos online by upgrading to
|
||||||
Pro. Or download the video and watch it locally on your computer.
|
Pro. Or download the video and watch it locally on your computer.
|
||||||
@@ -83,17 +83,23 @@ let download = () => { dispatch("download", {}) }
|
|||||||
<button on:click={download}>
|
<button on:click={download}>
|
||||||
<i class="icon">save</i> Download
|
<i class="icon">save</i> Download
|
||||||
</button>
|
</button>
|
||||||
{#if file.size > 1e9}
|
</div>
|
||||||
|
{#if file.size > 5e8}
|
||||||
|
<br/>
|
||||||
|
<div class="description" style="max-width: 700px; text-align: center;">
|
||||||
|
<!-- If the file is larger than 500 MB-->
|
||||||
<hr/>
|
<hr/>
|
||||||
Your download speed is currently limited to 4 MiB/s. Downloading this
|
Your download speed is currently limited to 4 MiB/s. Downloading this
|
||||||
file for free will take {formatDuration((file.size/4194304)*1000)}.
|
file for free will take at least
|
||||||
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12" class="button">
|
{formatDuration((file.size/4194304)*1000)}.
|
||||||
Upgrade to Pro
|
You can
|
||||||
|
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427&cadence=12">
|
||||||
|
upgrade to Pro
|
||||||
</a>
|
</a>
|
||||||
to download at the fastest speed available.
|
to download at the fastest speed available.
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -114,4 +120,11 @@ let download = () => { dispatch("download", {}) }
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
.description {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -34,19 +34,3 @@ $: frac = used / total
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
|
||||||
.progress_bar_outer {
|
|
||||||
display: block;
|
|
||||||
background-color: var(--layer_1_color);
|
|
||||||
width: 100%;
|
|
||||||
height: 3px;
|
|
||||||
margin: 6px 0 12px 0;
|
|
||||||
}
|
|
||||||
.progress_bar_inner {
|
|
||||||
background-color: var(--highlight_color);
|
|
||||||
height: 100%;
|
|
||||||
width: 0;
|
|
||||||
transition: width 1s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
Reference in New Issue
Block a user