2021-10-26 22:15:01 +02:00
< script >
2021-11-01 17:15:23 +01:00
import { onMount , tick } from "svelte";
2021-11-26 20:20:49 +01:00
import { copy_text } from "../util/Util.svelte";
2021-10-26 22:15:01 +02:00
import Modal from "../util/Modal.svelte";
import PixeldrainLogo from "../util/PixeldrainLogo.svelte";
import DetailsWindow from "./DetailsWindow.svelte";
import FilePreview from "./FilePreview.svelte";
import ListNavigator from "./ListNavigator.svelte";
2021-11-01 17:15:23 +01:00
import FileStats from "./FileStats.svelte";
import EditWindow from "./EditWindow.svelte";
import EmbedWindow from "./EmbedWindow.svelte";
import ReportWindow from "./ReportWindow.svelte";
import IntroPopup from "./IntroPopup.svelte";
2021-11-09 11:43:15 +01:00
import AdHead from "./AdHead.svelte";
2021-11-01 17:15:23 +01:00
import AdLeaderboard from "./AdLeaderboard.svelte";
import AdSkyscraper from "./AdSkyscraper.svelte";
2021-11-01 22:32:46 +01:00
import Sharebar from "./Sharebar.svelte";
2021-11-23 23:45:42 +01:00
import GalleryView from "./GalleryView.svelte";
import Spinner from "../util/Spinner.svelte";
2021-11-26 20:20:49 +01:00
import Downloader from "./Downloader.svelte";
2021-10-26 22:15:01 +02:00
2021-11-23 23:45:42 +01:00
const file_struct = {
2021-10-26 22:15:01 +02:00
id: "",
2021-11-23 23:45:42 +01:00
name: "",
2021-11-01 17:15:23 +01:00
size: 0,
bandwidth_used: 0,
2021-11-23 23:45:42 +01:00
bandwidth_used_paid: 0,
2021-11-01 17:15:23 +01:00
downloads: 0,
views: 0,
2021-10-26 22:15:01 +02:00
mime_type: "",
2021-11-01 17:15:23 +01:00
availability: "",
2021-11-23 23:45:42 +01:00
abuse_type: "",
2021-11-01 17:15:23 +01:00
show_ads: false,
can_edit: false,
2021-10-26 22:15:01 +02:00
get_href: "",
2021-11-23 23:45:42 +01:00
info_href: "",
2021-10-26 22:15:01 +02:00
download_href: "",
icon_href: "",
}
2021-11-23 23:45:42 +01:00
const list_struct = {
2021-10-26 22:15:01 +02:00
id: "",
title: "",
files: [],
download_href: "",
2021-11-23 23:45:42 +01:00
info_href: "",
can_edit: false,
2021-10-26 22:15:01 +02:00
}
2021-11-23 23:45:42 +01:00
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
2021-11-01 17:15:23 +01:00
let button_home
2021-10-26 22:15:01 +02:00
let list_navigator
let list_shuffle = false
let toggle_shuffle = () => {
list_shuffle = !list_shuffle
}
2021-11-01 22:32:46 +01:00
let sharebar
2021-10-26 22:15:01 +02:00
let sharebar_visible = false
2021-11-01 22:32:46 +01:00
let toggle_sharebar = () => {
2021-11-01 23:37:29 +01:00
if (navigator.share) {
2021-11-23 23:45:42 +01:00
let name = file.name
2021-11-01 23:37:29 +01:00
if (is_list) {
2021-11-23 23:45:42 +01:00
name = list.title
2021-11-01 23:37:29 +01:00
}
navigator.share({
title: name,
text: "I would like to share '" + name + "' with you",
url: window.location.href
})
return
}
2021-11-01 22:32:46 +01:00
sharebar_visible = !sharebar_visible
if (sharebar_visible) {
sharebar.show()
} else {
sharebar.hide()
}
}
2021-10-26 22:15:01 +02:00
let toolbar_visible = (window.innerWidth > 600)
let toolbar_toggle = () => {
toolbar_visible = !toolbar_visible
2021-11-01 22:32:46 +01:00
if (!toolbar_visible && sharebar_visible) {
toggle_sharebar()
2021-10-26 22:15:01 +02:00
}
}
2021-11-26 20:20:49 +01:00
let downloader
2021-10-26 22:15:01 +02:00
let details_window
let details_visible = false
let qr_window
let qr_visible = false
let edit_window
let edit_visible = false
let report_window
let report_visible = false
let embed_window
let embed_visible = false
2021-11-01 17:15:23 +01:00
let skyscraper_visible = false
2021-10-26 22:15:01 +02:00
onMount(() => {
let viewer_data = window.viewer_data
embedded = viewer_data.embedded
if (embedded) {
toolbar_visible = false
}
view_token = viewer_data.view_token
if (viewer_data.type === "list") {
open_list(viewer_data.api_response)
} else {
2021-11-23 23:45:42 +01:00
list.files = [viewer_data.api_response]
open_file_index(0)
2021-10-26 22:15:01 +02:00
}
2021-11-23 23:45:42 +01:00
ads_enabled = list.files[0].show_ads
loading = false
2021-10-26 22:15:01 +02:00
})
2021-11-23 23:45:42 +01:00
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
}
2021-10-26 22:15:01 +02:00
2021-11-24 18:09:01 +01:00
const open_list = l => {
2021-11-23 23:45:42 +01:00
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)
2021-10-26 22:15:01 +02:00
})
2021-11-23 23:45:42 +01:00
list = l
2021-11-01 17:15:23 +01:00
// Setting is_list to true activates the ListNavgator, which makes sure the
// correct file is opened
is_list = true
2021-11-23 23:45:42 +01:00
// 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
2021-11-24 18:09:01 +01:00
open_file_index(hashID)
} else if (view !== "gallery") {
toggle_gallery()
2021-11-23 23:45:42 +01:00
}
2021-10-26 22:15:01 +02:00
}
2021-11-23 23:45:42 +01:00
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]
2021-11-24 18:09:01 +01:00
if (view !== "file") {
view = "file"
await tick() // Wait for the ListNavigator to render
}
2021-10-26 22:15:01 +02:00
2021-11-24 18:09:01 +01:00
if (is_list) {
2021-11-23 23:45:42 +01:00
// Update the URL
location.replace("#item=" + index)
list_navigator.set_item(index)
}
2021-10-26 22:15:01 +02:00
// Register a file view
2021-11-23 23:45:42 +01:00
fetch(window.api_endpoint + "/file/" + file.id + "/view", {
2021-10-26 22:15:01 +02:00
method: "POST",
headers: { "Content-Type" : "application/x-www-form-urlencoded" } ,
body: "token=" + view_token
})
}
2021-11-23 23:45:42 +01:00
const file_set_href = f => {
f.get_href = window.api_endpoint+"/file/"+f.id
f.info_href = window.api_endpoint+"/file/"+f.id+"/info"
f.download_href = window.api_endpoint+"/file/"+f.id+"?download"
f.icon_href = window.api_endpoint+"/file/"+f.id+"/thumbnail"
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
}
2021-10-26 22:15:01 +02:00
}
let supports_fullscreen = !!document.documentElement.requestFullscreen
let fullscreen = false
const toggle_fullscreen = () => {
if (!fullscreen) {
document.documentElement.requestFullscreen()
document.getElementById("btn_fullscreen_icon").innerText = "fullscreen_exit"
fullscreen = true
} else {
document.exitFullscreen()
document.getElementById("btn_fullscreen_icon").innerText = "fullscreen"
fullscreen = false
}
}
2021-11-01 17:15:23 +01:00
let copy_url_status = "" // empty, copied, or error
const copy_url = () => {
if (copy_text(window.location.href)) {
copy_url_status = "copied"
} else {
copy_url_status = "error"
alert("Your browser does not support copying text.")
}
setTimeout(() => { copy_url_status = "" } , 60000)
}
const grab_file = async () => {
2021-11-23 23:45:42 +01:00
if (!window.user_authenticated || file.can_edit) {
2021-11-01 17:15:23 +01:00
return
}
const form = new FormData()
2021-11-23 23:45:42 +01:00
form.append("grab_file", file.id)
2021-11-01 17:15:23 +01:00
try {
const resp = await fetch(
window.api_endpoint + "/file",
{ method : "POST" , body : form } ,
);
if (resp.status >= 400) {
throw (await resp.json()).message
}
window.open("/u/" + (await resp.json()).id, "_blank")
} catch (err) {
alert("Failed to grab file: " + err)
return
}
}
2021-10-26 22:15:01 +02:00
const keyboard_event = evt => {
if (evt.ctrlKey || evt.altKey || evt.metaKey) {
return // prevent custom shortcuts from interfering with system shortcuts
}
if (document.activeElement.type && document.activeElement.type === "text") {
return // Prevent shortcuts from interfering with input fields
}
console.debug("Key pressed: " + evt.keyCode)
switch (evt.keyCode) {
case 65: // A or left arrow key go to previous file
case 37:
if (list_navigator) {
list_navigator.prev()
}
break
case 68: // D or right arrow key go to next file
case 39:
if (list_navigator) {
list_navigator.next()
}
break
case 83:
if (evt.shiftKey) {
download_list() // SHIFT + S downloads all files in list
} else {
download() // S to download the current file
}
break
case 82: // R to toggle list shuffle
if (list_navigator) {
toggle_shuffle()
}
break
case 67: // C to copy to clipboard
2021-11-01 17:15:23 +01:00
copy_url()
2021-10-26 22:15:01 +02:00
break
case 73: // I to open the details window
details_window.toggle()
break
case 69: // E to open the edit window
2021-11-23 23:45:42 +01:00
if (file.can_edit) {
2021-11-01 17:15:23 +01:00
edit_window.toggle()
}
2021-10-26 22:15:01 +02:00
break
case 77: // M to open the embed window
embed_window.toggle()
break
case 71: // G to grab this file
this.grabFile()
break
case 81: // Q to close the window
window.close()
break
}
}
< / script >
< svelte:window on:keydown = { keyboard_event } / >
< div id = "file_viewer" class = "file_viewer" >
2021-11-09 11:43:15 +01:00
<!-- Head elements for the ads -->
< AdHead > < / AdHead >
2021-11-23 23:45:42 +01:00
{ #if loading }
< div class = "spinner_container" >
< Spinner > < / Spinner >
< / div >
{ /if }
2021-10-26 22:15:01 +02:00
< div id = "headerbar" class = "headerbar" class:embedded >
< button on:click = { toolbar_toggle } class="button_toggle_toolbar round " class:button_highlight = { toolbar_visible } >
< i class = "icon" > menu< / i >
< / button >
2021-11-01 17:15:23 +01:00
< a href = "/" bind:this = { button_home } class="button button_home round " target = { embedded ? "_blank" : "" } >
2021-10-26 22:15:01 +02:00
< PixeldrainLogo style = "height: 1.6em; width: 1.6em; margin: 0 4px 0 0;" > < / PixeldrainLogo >
< / a >
< div id = "file_viewer_headerbar_title" class = "file_viewer_headerbar_title" >
2021-11-23 23:45:42 +01:00
{ #if list . title !== "" }{ list . title } < br /> { /if }
{ #if file . name !== "" }{ file . name }{ /if }
2021-10-26 22:15:01 +02:00
< / div >
{ #if embedded && supports_fullscreen }
< button class = "round" on:click = { toggle_fullscreen } >
< i class = "icon" id = "btn_fullscreen_icon" > fullscreen< / i >
< / button >
{ /if }
< / div >
2021-11-23 23:45:42 +01:00
{ #if is_list && view === "file" }
< ListNavigator
bind:this={ list_navigator }
files={ list . files }
shuffle={ list_shuffle }
on:set_file={ e => { open_file_index ( e . detail ) }} >
< / ListNavigator >
2021-10-26 22:15:01 +02:00
{ /if }
< div id = "file_preview_window" class = "file_preview_window" >
< div id = "toolbar" class = "toolbar" class:toolbar_visible > < div > < div >
2021-11-24 11:51:39 +01:00
{ #if view === "file" }
< FileStats file = { file } > </FileStats >
< hr / >
{ /if }
2021-11-23 23:45:42 +01:00
{ #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 >
{ /if }
{ #if file . abuse_type === "" && view === "file" }
2021-11-26 20:20:49 +01:00
< button on:click = { downloader . download_file } class="toolbar_button button_full_width " >
2021-11-23 23:45:42 +01:00
< i class = "icon" > download< / i >
2021-11-02 09:34:02 +01:00
< span > Download< / span >
2021-10-26 22:15:01 +02:00
< / button >
{ /if }
2021-11-23 23:45:42 +01:00
{ #if file . abuse_type === "" && is_list }
2021-11-26 20:20:49 +01:00
< button on:click = { downloader . download_list } class="toolbar_button button_full_width " >
2021-11-23 23:45:42 +01:00
< i class = "icon" > download< / i >
< span > DL all files< / span >
< / button >
{ /if }
2021-11-01 17:15:23 +01:00
< button on:click = { copy_url }
class="toolbar_button button_full_width"
class:button_highlight={ copy_url_status === "copied" }
class:button_red={ copy_url_status === "error" } >
2021-10-26 22:15:01 +02:00
< i class = "icon" > content_copy< / i >
2021-11-01 17:15:23 +01:00
< span >
{ #if copy_url_status === "copied" }
Copied!
{ :else if copy_url_status === "error" }
Error!
{ : else }
< u > C< / u > opy link
{ /if }
< / span >
2021-10-26 22:15:01 +02:00
< / button >
2021-11-23 23:45:42 +01:00
2021-11-01 22:32:46 +01:00
< button on:click = { toggle_sharebar } class="toolbar_button button_full_width " class:button_highlight = { sharebar_visible } >
2021-11-01 17:15:23 +01:00
< i class = "icon" > share< / i >
< span > Share< / span >
2021-10-26 22:15:01 +02:00
< / button >
2021-11-23 23:45:42 +01:00
2021-10-26 22:15:01 +02:00
< button class = "toolbar_button button_full_width" on:click = { qr_window . toggle } class:button_highlight= { qr_visible } >
< i class = "icon" > qr_code< / i >
< span > QR code< / span >
< / button >
2021-11-23 23:45:42 +01:00
2021-10-26 22:15:01 +02:00
{ #if is_list }
< button
class="toolbar_button button_full_width"
title="Randomize the order of the files in this list"
class:button_highlight={ list_shuffle }
2021-11-23 23:45:42 +01:00
on:click={ toggle_shuffle } >
2021-10-26 22:15:01 +02:00
< i class = "icon" > shuffle< / i >
{ #if list_shuffle }
< span > Shuffle ☑ < / span >
{ : else }
< span > Shuffle ☐ < / span >
{ /if }
< / button >
{ /if }
2021-11-23 23:45:42 +01:00
{ #if view === "file" }
< button class = "toolbar_button button_full_width" on:click = { details_window . toggle } class:button_highlight= { details_visible } >
< i class = "icon" > help< / i >
< span > Deta< u > i< / u > ls< / span >
< / button >
{ /if }
2021-10-26 22:15:01 +02:00
< hr / >
2021-11-23 23:45:42 +01:00
{ #if file . can_edit || list . can_edit }
2021-11-01 17:15:23 +01:00
< button class = "toolbar_button button_full_width" on:click = { edit_window . toggle } class:button_highlight= { edit_visible } >
< i class = "icon" > edit< / i >
< span > < u > E< / u > dit< / span >
< / button >
{ /if }
2021-11-23 23:45:42 +01:00
{ #if view === "file" && window . user_authenticated && ! file . can_edit }
2021-11-01 17:15:23 +01:00
< 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 >
< span > < u > G< / u > rab file< / span >
< / button >
{ /if }
2021-11-23 23:45:42 +01:00
2021-10-26 22:15:01 +02:00
< 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 >
< span > E< u > m< / u > bed< / span >
< / button >
2021-11-23 23:45:42 +01:00
{ #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 } >
< i class = "icon" > flag< / i >
< span > Report< / span >
< / button >
{ /if }
2021-10-26 22:15:01 +02:00
< br / >
< / div > < / div > < / div >
2021-11-01 22:32:46 +01:00
< Sharebar bind:this = { sharebar } > </Sharebar >
2021-10-26 22:15:01 +02:00
2021-11-01 17:15:23 +01:00
< div id = "file_preview" class = "file_preview checkers" class:toolbar_visible class:skyscraper_visible >
2021-11-23 23:45:42 +01:00
{ #if view === "file" }
< FilePreview
file={ file }
2021-11-26 20:20:49 +01:00
on:download={ downloader . download_file }
2021-11-23 23:45:42 +01:00
on:prev={() => { if ( list_navigator ) { list_navigator . prev () }}}
on:next={() => { if ( list_navigator ) { list_navigator . next () }}} >
< / 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 }
2021-10-26 22:15:01 +02:00
< / div >
2021-11-23 23:45:42 +01:00
{ #if ads_enabled }
2021-11-01 17:15:23 +01:00
< AdSkyscraper on:visibility = { e => { skyscraper_visible = e . detail }} > </AdSkyscraper >
{ /if }
2021-10-26 22:15:01 +02:00
< / div >
2021-11-23 23:45:42 +01:00
{ #if ads_enabled }
2021-11-01 17:15:23 +01:00
< AdLeaderboard > < / AdLeaderboard >
2021-11-02 09:34:02 +01:00
{ :else if ! window . viewer_data . user_ads_enabled && ! embedded }
2021-10-26 22:15:01 +02:00
< div style = "text-align: center; line-height: 1.3em; font-size: 13px;" >
Thank you for supporting pixeldrain!
< / div >
2021-11-23 23:45:42 +01:00
{ :else if ! ads_enabled && ! embedded }
2021-11-01 17:15:23 +01:00
< 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 > !
< / div >
{ /if }
2021-10-26 22:15:01 +02:00
< Modal bind:this = { details_window } on:is_visible= { e => { details_visible = e . detail }} title = "File details" width = "1200px" >
2021-11-23 23:45:42 +01:00
< DetailsWindow file = { file } > </DetailsWindow >
2021-10-26 22:15:01 +02:00
< / Modal >
2021-11-01 17:15:23 +01:00
< 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%;" />
2021-10-26 22:15:01 +02:00
< / Modal >
2021-11-01 17:15:23 +01:00
2021-11-23 23:45:42 +01:00
< Modal bind:this = { edit_window } on:is_visible= { e => { edit_visible = e . detail }} title = { "Editing " + file . name } >
< EditWindow file = { file } list= { list } on:reload = { reload } > </EditWindow >
2021-10-26 22:15:01 +02:00
< / Modal >
2021-11-01 17:15:23 +01:00
< Modal bind:this = { embed_window } on:is_visible= { e => { embed_visible = e . detail }} title = "Embed file" width = "850px" >
2021-11-23 23:45:42 +01:00
< EmbedWindow file = { file } list= { list } ></ EmbedWindow >
2021-10-26 22:15:01 +02:00
< / Modal >
2021-11-01 17:15:23 +01:00
2021-11-01 22:32:46 +01:00
< Modal bind:this = { report_window } on:is_visible= { e => { report_visible = e . detail }} title = "Report abuse" width = "800px" >
2021-11-23 23:45:42 +01:00
< ReportWindow file = { file } list= { list } ></ ReportWindow >
2021-10-26 22:15:01 +02:00
< / Modal >
2021-11-01 17:15:23 +01:00
< IntroPopup target = { button_home } > </IntroPopup >
2021-11-26 20:20:49 +01:00
< Downloader bind:this = { downloader } file= { file } list = { list } > </Downloader >
2021-10-26 22:15:01 +02:00
< / div >
< style >
2021-11-23 23:45:42 +01:00
.spinner_container {
position: absolute;
top: 10px;
right: 10px;
height: 100px;
width: 100px;
z-index: 10000;
}
2021-10-26 22:15:01 +02:00
.file_viewer {
position: absolute;
display: flex;
flex-direction: column;
2021-11-23 23:45:42 +01:00
width: 100%;
height: 100%;
2021-10-26 22:15:01 +02:00
overflow: hidden;
background-color: var(--layer_2_color);
}
/* Headerbar (row 1) */
.headerbar {
flex-grow: 0;
flex-shrink: 0;
display: flex;
flex-direction: row;
text-align: left;
z-index: 10;
box-shadow: none;
padding: 4px;
}
.headerbar.embedded {
padding: 2px;
}
/* Headerbar components */
.headerbar > * {
flex-grow: 0;
flex-shrink: 0;
margin-left: 4px;
margin-right: 4px;
display: inline;
}
.headerbar > .file_viewer_headerbar_title {
flex-grow: 1;
flex-shrink: 1;
display: flex;
flex-direction: column;
overflow: hidden;
line-height: 1.2em; /* When the page is a list there will be two lines. Dont's want to stretch the container*/
white-space: nowrap;
text-overflow: ellipsis;
justify-content: center;
}
.headerbar > button > .icon {
font-size: 1.6em;
}
.headerbar > .button_home::after {
content: "pixeldrain";
}
@media (max-width: 600px) {
.headerbar > .button_home::after {
content: "pd";
}
}
/* File preview area (row 3) */
.file_preview_window {
flex-grow: 1;
flex-shrink: 1;
position: relative;
display: inline-block;
width: auto;
height: auto;
margin: 0;
z-index: 9;
}
.file_preview {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: inline-block;
min-height: 100px;
min-width: 100px;
text-align: center;
vertical-align: middle;
transition: left 0.5s, right 0.5s;
2021-11-24 11:51:39 +01:00
overflow: hidden;
2021-10-26 22:15:01 +02:00
box-shadow: inset 2px 2px 10px 2px var(--shadow_color);
border-radius: 16px;
}
/* Toolbars */
.toolbar {
position: absolute;
width: 8em;
z-index: 49;
overflow: hidden;
left: -8em;
bottom: 0;
top: 0;
padding: 0;
text-align: left;
2021-11-01 17:15:23 +01:00
transition: left 0.5s, right 0.5s;
2021-10-26 22:15:01 +02:00
background-color: var(--layer_2_color);
}
.toolbar.toolbar_visible { left : 0 ; }
.file_preview.toolbar_visible { left : 8em ; }
2021-11-01 17:15:23 +01:00
.file_preview.skyscraper_visible { right : 160px ; }
2021-10-26 22:15:01 +02:00
/* Workaround to hide the scrollbar in non webkit browsers, it's really ugly' */
.toolbar > div {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: -30px;
overflow-y: scroll;
overflow-x: hidden;
}
.toolbar > div > div {
position: absolute;
left: 0;
top: 0;
width: 8em;
height: auto;
text-align: center;
}
.toolbar_button{
text-align: left;
}
.toolbar_button > span {
vertical-align: middle;
}
< / style >