Add header image to branding options
This commit is contained in:
@@ -4,9 +4,10 @@ import { formatDataVolume, formatDate, formatThousands } from "../util/Formattin
|
||||
import Modal from "../util/Modal.svelte";
|
||||
import { fs_timeseries } from "./FilesystemAPI";
|
||||
import { fs_path_url } from "./FilesystemUtil";
|
||||
import { generate_share_url } from "./Sharebar.svelte";
|
||||
import { color_by_name } from "../util/Util.svelte";
|
||||
import { generate_share_path, generate_share_url } from "./Sharebar.svelte";
|
||||
import { color_by_name, copy_text } from "../util/Util.svelte";
|
||||
import { tick } from "svelte";
|
||||
import Button from "../layout/Button.svelte";
|
||||
|
||||
export let state
|
||||
export let visible = false
|
||||
@@ -21,6 +22,7 @@ const visibility_change = visible => {
|
||||
|
||||
$: direct_url = window.location.origin+fs_path_url(state.base.path)
|
||||
$: share_url = generate_share_url(state.path)
|
||||
$: direct_share_url = window.location.origin+fs_path_url(generate_share_path(state.path))
|
||||
|
||||
let chart
|
||||
let chart_timespan = 0
|
||||
@@ -171,9 +173,28 @@ let update_chart = async (base, timespan, interval) => {
|
||||
</tr>
|
||||
<tr><td>SHA256 sum</td><td>{state.base.sha256_sum}</td></tr>
|
||||
{/if}
|
||||
<tr><td>Direct URL</td><td><a href="{direct_url}">{direct_url}</a></td></tr>
|
||||
<tr>
|
||||
<td>Direct link</td>
|
||||
<td>
|
||||
<Button highlight_on_click icon="content_copy" label="Copy" click={e => copy_text(direct_url)}/>
|
||||
<a href="{direct_url}">{direct_url}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{#if share_url !== ""}
|
||||
<tr><td>Share URL</td><td><a href="{share_url}">{share_url}</a></td></tr>
|
||||
<tr>
|
||||
<td>Sharing link</td>
|
||||
<td>
|
||||
<Button highlight_on_click icon="content_copy" label="Copy" click={e => copy_text(share_url)}/>
|
||||
<a href="{share_url}">{share_url}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Direct sharing link</td>
|
||||
<td>
|
||||
<Button highlight_on_click icon="content_copy" label="Copy" click={e => copy_text(direct_share_url)}/>
|
||||
<a href="{direct_share_url}">{direct_share_url}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</table>
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import LoadingIndicator from '../util/LoadingIndicator.svelte';
|
||||
import EditWindow from './EditWindow.svelte';
|
||||
import EditWindow from './edit_window/EditWindow.svelte';
|
||||
import Toolbar from './Toolbar.svelte';
|
||||
import Breadcrumbs from './Breadcrumbs.svelte';
|
||||
import DetailsWindow from './DetailsWindow.svelte';
|
||||
@@ -10,8 +10,8 @@ import FilePreview from './viewers/FilePreview.svelte';
|
||||
import SearchView from './SearchView.svelte';
|
||||
import UploadWidget from './upload_widget/UploadWidget.svelte';
|
||||
import HomeButton from '../file_viewer/HomeButton.svelte';
|
||||
import { fs_path_url } from './FilesystemUtil';
|
||||
import { branding_from_node, branding_from_path } from './BrandingOptions.svelte';
|
||||
import { fs_path_url } from './FilesystemUtil.js';
|
||||
import { branding_from_path } from './edit_window/Branding.js'
|
||||
|
||||
let loading = true
|
||||
let toolbar
|
||||
@@ -179,7 +179,6 @@ const update_css = path => document.documentElement.style = branding_from_path(p
|
||||
bind:visible={edit_visible}
|
||||
fs_navigator={fs_navigator}
|
||||
on:loading={loading_evt}
|
||||
on:style_change={e => document.documentElement.style = branding_from_node(e.detail)}
|
||||
/>
|
||||
|
||||
<UploadWidget
|
||||
|
@@ -13,6 +13,9 @@ export const fs_encode_path = path => {
|
||||
}
|
||||
|
||||
export const fs_path_url = path => {
|
||||
if (path[0] !== "/") {
|
||||
path = "/" + path
|
||||
}
|
||||
return window.api_endpoint + "/filesystem" + fs_encode_path(path)
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,12 @@
|
||||
<script context="module">
|
||||
export const generate_share_url = path => {
|
||||
let share_path = generate_share_path(path)
|
||||
if (share_path !== "") {
|
||||
share_path = window.location.protocol+"//"+window.location.host+"/d/"+share_path
|
||||
}
|
||||
return share_path
|
||||
}
|
||||
export const generate_share_path = path => {
|
||||
let share_url = ""
|
||||
let bucket_idx = -1
|
||||
|
||||
@@ -11,9 +18,7 @@ export const generate_share_url = path => {
|
||||
}
|
||||
}
|
||||
if (bucket_idx !== -1) {
|
||||
share_url = window.location.protocol+"//"+
|
||||
window.location.host+"/d/"+
|
||||
path[bucket_idx].id
|
||||
share_url = path[bucket_idx].id
|
||||
|
||||
// Construct the path starting from the bucket
|
||||
for (let i = bucket_idx+1; i < path.length; i++) {
|
||||
|
@@ -106,10 +106,12 @@ let expand = e => {
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<button on:click={share}>
|
||||
<i class="icon">share</i>
|
||||
<span>Share</span>
|
||||
</button>
|
||||
{#if state.base.id !== "me"}
|
||||
<button on:click={share}>
|
||||
<i class="icon">share</i>
|
||||
<span>Share</span>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<button on:click={() => details_visible = !details_visible} class:button_highlight={details_visible}>
|
||||
<i class="icon">help</i>
|
||||
|
101
svelte/src/filesystem/edit_window/Branding.js
Normal file
101
svelte/src/filesystem/edit_window/Branding.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import parse from "pure-color/parse"
|
||||
import rgb2hsl from "pure-color/convert/rgb2hsl";
|
||||
import hsl2rgb from "pure-color/convert/hsl2rgb";
|
||||
import rgb2hex from "pure-color/convert/rgb2hex";
|
||||
|
||||
// Generate a branding style from a file's properties map
|
||||
export const branding_from_path = path => {
|
||||
let style = {}
|
||||
for (let node of path) {
|
||||
add_styles(style, node.properties)
|
||||
}
|
||||
last_generated_style = style
|
||||
return gen_css(style)
|
||||
}
|
||||
|
||||
// The last style which was generated is cached, when we don't have a complete
|
||||
// path to generate the style with we will use the cached style as a basis
|
||||
let last_generated_style = {}
|
||||
export const branding_from_node = node => {
|
||||
add_styles(last_generated_style, node.properties)
|
||||
return gen_css(last_generated_style)
|
||||
}
|
||||
|
||||
const gen_css = style => {
|
||||
return Object.entries(style).map(([key, value]) => `--${key}:${value}`).join(';');
|
||||
}
|
||||
|
||||
// add_styles adds the styles configured in the properties struct to the
|
||||
// existing style which is passed as the first argument. When navigating to a
|
||||
// path this function is executed on every member of the path so all the styles
|
||||
// get combined
|
||||
const add_styles = (style, properties) => {
|
||||
if (!properties || !properties.branding_enabled || properties.branding_enabled !== "true") {
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
if (properties.brand_danger_color) {
|
||||
style.danger_color = properties.brand_danger_color
|
||||
style.danger_text_color = add_light(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_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.shaded_background = set_alpha(properties.brand_body_color, 0.8)
|
||||
style.separator = add_light(properties.brand_body_color, 5)
|
||||
style.shadow_color = darken(properties.brand_body_color, 0.8)
|
||||
}
|
||||
if (properties.brand_card_color) {
|
||||
style.card_color = properties.brand_card_color
|
||||
}
|
||||
if (properties.brand_background_image) {
|
||||
style.background_image = "url('/api/filesystem/" + properties.brand_background_image + "')"
|
||||
style.background_image_size = "cover"
|
||||
style.background_image_position = "center"
|
||||
style.background_image_repeat = "no-repeat"
|
||||
}
|
||||
}
|
||||
|
||||
const add_light = (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
|
||||
if (hsl[2] < 40) {
|
||||
hsl[2] = hsl[2] + amt // Dark color, add lightness
|
||||
} else {
|
||||
hsl[2] = hsl[2] - amt // Light color, remove lightness
|
||||
}
|
||||
return rgb2hex(hsl2rgb(hsl)) // Convert back to hex
|
||||
}
|
||||
|
||||
// Darken and desaturate. Only used for shadows
|
||||
const darken = (color, percent) => {
|
||||
let hsl = rgb2hsl(parse(color)) // Convert hex to hsl
|
||||
hsl[1] = hsl[1] * percent
|
||||
hsl[2] = hsl[2] * percent
|
||||
return rgb2hex(hsl2rgb(hsl)) // Convert back to hex
|
||||
}
|
||||
|
||||
const set_alpha = (color, amt) => {
|
||||
let rgb = parse(color)
|
||||
rgb.push(amt)
|
||||
return "rgba(" + rgb.join(", ") + ")"
|
||||
}
|
@@ -1,124 +1,21 @@
|
||||
<script context="module">
|
||||
import parse from "pure-color/parse"
|
||||
import rgb2hsl from "pure-color/convert/rgb2hsl";
|
||||
import hsl2rgb from "pure-color/convert/hsl2rgb";
|
||||
import rgb2hex from "pure-color/convert/rgb2hex";
|
||||
|
||||
// Generate a branding style from a file's properties map
|
||||
export const branding_from_path = path => {
|
||||
let style = {}
|
||||
for (let node of path) {
|
||||
add_styles(style, node.properties)
|
||||
}
|
||||
last_generated_style = style
|
||||
return gen_css(style)
|
||||
}
|
||||
|
||||
// The last style which was generated is cached, when we don't have a complete
|
||||
// path to generate the style with we will use the cached style as a basis
|
||||
let last_generated_style = {}
|
||||
export const branding_from_node = node => {
|
||||
add_styles(last_generated_style, node.properties)
|
||||
return gen_css(last_generated_style)
|
||||
}
|
||||
|
||||
const gen_css = style => {
|
||||
return Object.entries(style).map(([key, value]) => `--${key}:${value}`).join(';');
|
||||
}
|
||||
|
||||
// add_styles adds the styles configured in the properties struct to the
|
||||
// existing style which is passed as the first argument. When navigating to a
|
||||
// path this function is executed on every member of the path so all the styles
|
||||
// get combined
|
||||
const add_styles = (style, properties) => {
|
||||
if (!properties || !properties.branding_enabled || properties.branding_enabled !== "true") {
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
if (properties.brand_danger_color) {
|
||||
style.danger_color = properties.brand_danger_color
|
||||
style.danger_text_color = add_light(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_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.shaded_background = set_alpha(properties.brand_body_color, 0.8)
|
||||
style.separator = add_light(properties.brand_body_color, 5)
|
||||
style.shadow_color = darken(properties.brand_body_color, 0.8)
|
||||
}
|
||||
if (properties.brand_card_color) {
|
||||
style.card_color = properties.brand_card_color
|
||||
}
|
||||
if (properties.brand_background_image) {
|
||||
style.background_image = "url('/api/filesystem/"+properties.brand_background_image+"')"
|
||||
style.background_image_size = "cover"
|
||||
style.background_image_position = "center"
|
||||
style.background_image_repeat = "no-repeat"
|
||||
}
|
||||
}
|
||||
|
||||
const add_light = (color, amt) => {
|
||||
let hsl = rgb2hsl(parse(color)) // Convert hex to hsl
|
||||
// If the lightness is less than 30 it is considered a dark colour. This
|
||||
// threshold is 30 instead of 50 because overall dark text is more legible
|
||||
if (hsl[2] < 30) {
|
||||
hsl[2] = hsl[2]+amt // Dark color, add lightness
|
||||
} else {
|
||||
hsl[2] = hsl[2]-amt // Light color, remove lightness
|
||||
}
|
||||
return rgb2hex(hsl2rgb(hsl)) // Convert back to hex
|
||||
}
|
||||
|
||||
// Darken and desaturate. Only used for shadows
|
||||
const darken = (color, percent) => {
|
||||
let hsl = rgb2hsl(parse(color)) // Convert hex to hsl
|
||||
hsl[1] = hsl[1]*percent
|
||||
hsl[2] = hsl[2]*percent
|
||||
return rgb2hex(hsl2rgb(hsl)) // Convert back to hex
|
||||
}
|
||||
|
||||
const set_alpha = (color, amt) => {
|
||||
let rgb = parse(color)
|
||||
rgb.push(amt)
|
||||
return "rgba("+rgb.join(", ")+")"
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import FilePicker from "./filemanager/FilePicker.svelte";
|
||||
import { fs_update } from "./FilesystemAPI";
|
||||
import { fs_node_type } from "./FilesystemUtil";
|
||||
import FilePicker from "../filemanager/FilePicker.svelte";
|
||||
import { fs_update } from "../FilesystemAPI";
|
||||
import { fs_node_type } from "../FilesystemUtil";
|
||||
import CustomBanner from "../viewers/CustomBanner.svelte";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let file = {
|
||||
properties: {
|
||||
branding_enabled: "false",
|
||||
brand_input_color: "#2d2d2d",
|
||||
brand_highlight_color: "#75b72d",
|
||||
brand_danger_color: "#bd5f69",
|
||||
brand_background_color: "#141414",
|
||||
brand_body_color: "#1e1e1e",
|
||||
brand_card_color: "#282828",
|
||||
branding_enabled: "",
|
||||
brand_input_color: "",
|
||||
brand_highlight_color: "",
|
||||
brand_danger_color: "",
|
||||
brand_background_color: "",
|
||||
brand_body_color: "",
|
||||
brand_card_color: "",
|
||||
brand_header_image: "",
|
||||
brand_header_link: "",
|
||||
brand_footer_image: "",
|
||||
@@ -133,7 +30,7 @@ $: update_colors(file)
|
||||
const update_colors = file => {
|
||||
if (enabled) {
|
||||
file.properties.branding_enabled = "true"
|
||||
dispatch("style_change", file)
|
||||
dispatch("style_change")
|
||||
} else {
|
||||
file.properties.branding_enabled = ""
|
||||
}
|
||||
@@ -208,15 +105,13 @@ const handle_picker = async e => {
|
||||
<div>Card</div>
|
||||
<input type="color" bind:value={file.properties.brand_card_color}/>
|
||||
<input type="text" bind:value={file.properties.brand_card_color}/>
|
||||
<div class="span3">
|
||||
<hr/>
|
||||
|
||||
<p class="span3">
|
||||
You can choose an image to show above or behind the files in this
|
||||
directory. The image will be picked from your filesystem. The image will
|
||||
get a shared file link. You can move and rename the file like normal,
|
||||
but if you remove the shared file property your branding will stop
|
||||
working.
|
||||
</div>
|
||||
working. Recommended dimensions for the header image are 1000x90 px.
|
||||
</p>
|
||||
<div>Header image ID</div>
|
||||
<button on:click={() => pick_image("brand_header_image")}>
|
||||
<i class="icon">folder_open</i>
|
||||
@@ -243,7 +138,9 @@ const handle_picker = async e => {
|
||||
|
||||
<div class="example example_body">
|
||||
<div>The content body. <a href="/">A link</a>!</div>
|
||||
|
||||
<hr/>
|
||||
<div>Below is your custom header image, if you chose one.</div>
|
||||
<CustomBanner path={[file]}/>
|
||||
<hr/>
|
||||
|
||||
<div class="example_button_row">
|
@@ -1,10 +1,11 @@
|
||||
<script>
|
||||
import { fs_delete_all, fs_rename, fs_update } from "./FilesystemAPI";
|
||||
import Modal from "../util/Modal.svelte";
|
||||
import { fs_delete_all, fs_rename, fs_update } from "../FilesystemAPI";
|
||||
import Modal from "../../util/Modal.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import Button from "../layout/Button.svelte";
|
||||
import Button from "../../layout/Button.svelte";
|
||||
import BrandingOptions from "./BrandingOptions.svelte";
|
||||
import PathLink from "./util/PathLink.svelte";
|
||||
import PathLink from "../util/PathLink.svelte";
|
||||
import { branding_from_node } from "./Branding";
|
||||
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
@@ -17,6 +18,7 @@ let file = {
|
||||
properties: {},
|
||||
};
|
||||
|
||||
let custom_css = ""
|
||||
$: is_root_dir = file.path === "/"+file.id
|
||||
|
||||
export let visible
|
||||
@@ -33,7 +35,14 @@ export const edit = (f, oae = false, t = "file") => {
|
||||
if (file.properties === undefined) {
|
||||
file.properties = {}
|
||||
}
|
||||
|
||||
branding_enabled = file.properties.branding_enabled === "true"
|
||||
if (branding_enabled) {
|
||||
custom_css = branding_from_node(file)
|
||||
} else {
|
||||
custom_css = ""
|
||||
}
|
||||
|
||||
visible = true
|
||||
}
|
||||
|
||||
@@ -127,7 +136,7 @@ const delete_file = async e => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:visible={visible} title="Edit {file.name}" width="700px" form="edit_form">
|
||||
<Modal bind:visible={visible} title="Edit {file.name}" width="700px" form="edit_form" style="color: var(--body_text_color); {custom_css}">
|
||||
<div class="tab_bar">
|
||||
<button class:button_highlight={tab === "file"} on:click={() => tab = "file"}>
|
||||
<i class="icon">edit</i>
|
||||
@@ -184,7 +193,12 @@ const delete_file = async e => {
|
||||
</div>
|
||||
{:else if tab === "branding"}
|
||||
<div class="tab_content">
|
||||
<BrandingOptions bind:enabled={branding_enabled} bind:colors={branding_colors} file={file} on:style_change/>
|
||||
<BrandingOptions
|
||||
bind:enabled={branding_enabled}
|
||||
bind:colors={branding_colors}
|
||||
file={file}
|
||||
on:style_change={e => custom_css = branding_from_node(file)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</Modal>
|
@@ -71,9 +71,9 @@ const node_select = e => {
|
||||
state.children[index].fm_selected = !state.children[index].fm_selected
|
||||
}
|
||||
|
||||
const node_settings = e => {
|
||||
edit_window.edit(state.children[e.detail], false)
|
||||
}
|
||||
const node_settings = e => edit_window.edit(state.children[e.detail], false)
|
||||
const node_branding = e => edit_window.edit(state.children[e.detail], false, "branding")
|
||||
|
||||
const navigate_up = () => {
|
||||
creating_dir = false
|
||||
|
||||
@@ -352,6 +352,8 @@ onMount(() => {
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
{#if directory_view === "list"}
|
||||
<ListView
|
||||
state={state}
|
||||
@@ -361,6 +363,7 @@ onMount(() => {
|
||||
on:node_context={node_context}
|
||||
on:node_share_click={node_share_click}
|
||||
on:node_settings={node_settings}
|
||||
on:node_branding={node_branding}
|
||||
on:node_select={node_select}
|
||||
/>
|
||||
{:else if directory_view === "gallery"}
|
||||
|
@@ -5,6 +5,7 @@ import GalleryView from './GalleryView.svelte'
|
||||
import Modal from '../../util/Modal.svelte';
|
||||
import Navigator from '../Navigator.svelte';
|
||||
import LoadingIndicator from '../../util/LoadingIndicator.svelte';
|
||||
import Breadcrumbs from '../Breadcrumbs.svelte'
|
||||
|
||||
let fs_navigator
|
||||
let state
|
||||
@@ -172,6 +173,9 @@ onMount(() => {
|
||||
<i class="icon">done</i> Pick
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Breadcrumbs state={state} fs_navigator={fs_navigator}/>
|
||||
|
||||
{#if directory_view === "list"}
|
||||
<ListView
|
||||
state={state}
|
||||
|
@@ -47,8 +47,13 @@ export let large_icons = false
|
||||
<i class="icon" title="This file / directory is shared. Click to open public link">share</i>
|
||||
</a>
|
||||
{/if}
|
||||
{#if child.properties && child.properties.branding_enabled}
|
||||
<button class="action_button" on:click|preventDefault|stopPropagation={() => dispatch("node_branding", index)}>
|
||||
<i class="icon">palette</i>
|
||||
</button>
|
||||
{/if}
|
||||
{#if state.permissions.update}
|
||||
<button class="action_button" on:click|preventDefault|stopPropagation={() => {dispatch("node_settings", index)}}>
|
||||
<button class="action_button" on:click|preventDefault|stopPropagation={() => dispatch("node_settings", index)}>
|
||||
<i class="icon">edit</i>
|
||||
</button>
|
||||
{/if}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { fs_path_url } from '../FilesystemUtil';
|
||||
import FileTitle from '../../file_viewer/viewers/FileTitle.svelte';
|
||||
let dispatch = createEventDispatcher()
|
||||
|
||||
export let state
|
||||
@@ -37,7 +38,9 @@ onMount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
<div class="container">
|
||||
<FileTitle title={state.base.name}/>
|
||||
<button on:click={() => dispatch("open_sibling", -1) }><i class="icon">skip_previous</i></button>
|
||||
<button on:click={() => player.currentTime -= 10 }><i class="icon">replay_10</i></button>
|
||||
<button on:click={toggle_play}>
|
||||
@@ -65,7 +68,6 @@ onMount(() => {
|
||||
|
||||
<style>
|
||||
.container {
|
||||
margin: 50px 0 0 0;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
text-align: center;
|
||||
|
50
svelte/src/filesystem/viewers/CustomBanner.svelte
Normal file
50
svelte/src/filesystem/viewers/CustomBanner.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script>
|
||||
export let path = []
|
||||
|
||||
let image_uri
|
||||
let image_link
|
||||
$: update_links(path)
|
||||
const update_links = (path) => {
|
||||
image_uri = null
|
||||
image_link = null
|
||||
for (let node of path) {
|
||||
if (node.properties && node.properties.branding_enabled === "true") {
|
||||
if (node.properties.brand_header_image) {
|
||||
image_uri = "/api/filesystem/"+node.properties.brand_header_image
|
||||
}
|
||||
if (node.properties.brand_header_link) {
|
||||
image_link = node.properties.brand_header_link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if image_uri}
|
||||
<div class="container">
|
||||
{#if image_link}
|
||||
<a class="link" href={image_link} target="_blank" rel="noreferrer">
|
||||
<img class="image" src="{image_uri}" alt="User-provided banner"/>
|
||||
</a>
|
||||
{:else}
|
||||
<img class="image" src="{image_uri}" alt="User-provided banner"/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
margin: 6px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.link {
|
||||
display: inline-block;
|
||||
}
|
||||
.image {
|
||||
display: inline-block;
|
||||
margin: auto;
|
||||
max-height: 90px;
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
@@ -7,6 +7,8 @@ let dispatch = createEventDispatcher()
|
||||
export let state
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_thumbnail_url(state.base.path, 256, 256)}>
|
||||
|
@@ -11,6 +11,7 @@ import Text from "./Text.svelte";
|
||||
import Video from "./Video.svelte";
|
||||
import Torrent from "./Torrent.svelte";
|
||||
import Zip from "./Zip.svelte";
|
||||
import CustomBanner from "./CustomBanner.svelte";
|
||||
|
||||
export let fs_navigator
|
||||
export let edit_window
|
||||
@@ -51,9 +52,13 @@ const state_update = async (base) => {
|
||||
edit_window={edit_window}
|
||||
on:loading
|
||||
on:upload_picker
|
||||
/>
|
||||
>
|
||||
<CustomBanner path={state.path}/>
|
||||
</FileManager>
|
||||
{:else if viewer_type === "audio"}
|
||||
<Audio state={state} on:open_sibling/>
|
||||
<Audio state={state} on:open_sibling>
|
||||
<CustomBanner path={state.path}/>
|
||||
</Audio>
|
||||
{:else if viewer_type === "image"}
|
||||
<Image state={state} on:open_sibling/>
|
||||
{:else if viewer_type === "video"}
|
||||
@@ -61,13 +66,21 @@ const state_update = async (base) => {
|
||||
{:else if viewer_type === "pdf"}
|
||||
<Pdf state={state}/>
|
||||
{:else if viewer_type === "text"}
|
||||
<Text state={state}/>
|
||||
<Text state={state}>
|
||||
<CustomBanner path={state.path}/>
|
||||
</Text>
|
||||
{:else if viewer_type === "torrent"}
|
||||
<Torrent state={state} bind:this={viewer} on:loading on:download/>
|
||||
<Torrent state={state} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
</Torrent>
|
||||
{:else if viewer_type === "zip"}
|
||||
<Zip state={state} bind:this={viewer} on:loading on:download />
|
||||
<Zip state={state} bind:this={viewer} on:loading on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
</Zip>
|
||||
{:else}
|
||||
<File state={state} on:download/>
|
||||
<File state={state} on:download>
|
||||
<CustomBanner path={state.path}/>
|
||||
</File>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
@@ -75,6 +75,7 @@ const mouseup = (e) => {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 4px 0px var(--shadow_color);
|
||||
}
|
||||
.image.zoom {
|
||||
max-width: none;
|
||||
|
@@ -27,6 +27,7 @@ export const set_file = file => {
|
||||
|
||||
|
||||
<div class="container">
|
||||
<slot></slot>
|
||||
<pre bind:this={text_pre}>
|
||||
Loading...
|
||||
</pre>
|
||||
|
@@ -73,6 +73,8 @@ const copy_magnet = () => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||
|
@@ -59,6 +59,8 @@ const recursive_size = (file) => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<h1>{state.base.name}</h1>
|
||||
|
||||
<IconBlock icon_href={fs_node_icon(state.base, 256, 256)}>
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<script>
|
||||
export let highlight = false;
|
||||
export let highlight_on_click = false
|
||||
export let red = false;
|
||||
export let round = false;
|
||||
export let flat = false;
|
||||
@@ -14,11 +15,25 @@ export let click = e => {}
|
||||
export let style = ""
|
||||
export let type = ""
|
||||
export let form = ""
|
||||
|
||||
let click_int = e => {
|
||||
if (highlight_on_click) {
|
||||
try {
|
||||
click(e)
|
||||
highlight = true
|
||||
} catch (err) {
|
||||
red = true
|
||||
throw err
|
||||
}
|
||||
} else {
|
||||
click(e)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if link_target === ""}
|
||||
<button
|
||||
on:click={click}
|
||||
on:click={click_int}
|
||||
class="button"
|
||||
class:button_highlight={highlight}
|
||||
class:button_red={red}
|
||||
|
@@ -18,6 +18,7 @@ export let width = "800px";
|
||||
export let height = "auto";
|
||||
export let padding = false;
|
||||
export let visible = false;
|
||||
export let style = "";
|
||||
|
||||
const load_bg = background => {
|
||||
background.style.zIndex = global_index.valueOf();
|
||||
@@ -53,6 +54,7 @@ const keydown = e => {
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<div
|
||||
class="background"
|
||||
style={style}
|
||||
use:load_bg
|
||||
on:click={hide}
|
||||
transition:fade={{duration: 200}}
|
||||
|
Reference in New Issue
Block a user