155 lines
5.7 KiB
JavaScript
155 lines
5.7 KiB
JavaScript
class FilePreview extends Window {
|
|
_visible = false
|
|
_file = null
|
|
_url = null
|
|
|
|
open(file, url) {
|
|
this._file = file
|
|
this._url = url
|
|
this._visible = true
|
|
this.rerender()
|
|
}
|
|
|
|
close() {
|
|
this._visible = false
|
|
this.rerender()
|
|
}
|
|
|
|
render() {
|
|
this.style.position = "fixed"
|
|
this.style.inset = "0"
|
|
this.style.zIndex = "300"
|
|
this.style.pointerEvents = this._visible ? "all" : "none"
|
|
|
|
if (!this._visible) return
|
|
|
|
const x = this.getX()
|
|
const y = this.getY()
|
|
const w = this.getWidth()
|
|
const h = this.getHeight()
|
|
|
|
const type = this._file?.type ?? ""
|
|
const isImage = type.startsWith("image/")
|
|
const isPDF = type === "application/pdf"
|
|
const isOffice = [
|
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
'application/msword',
|
|
'application/vnd.ms-excel',
|
|
'application/vnd.ms-powerpoint',
|
|
'text/plain',
|
|
].includes(type)
|
|
const displayName = this._file?.original_name ?? this._file?.name ?? "File"
|
|
|
|
VStack(() => {
|
|
const panel = VStack(() => {
|
|
// Header
|
|
HStack(() => {
|
|
HStack(() => {
|
|
div().attr({ class: "tl tl-close" }).onClick((done) => { if (done) this.close() })
|
|
div().attr({ class: "tl tl-min" })
|
|
div().attr({ class: "tl tl-max" })
|
|
})
|
|
.attr({ class: "traffic-lights" })
|
|
.flexShrink(0)
|
|
|
|
p(displayName)
|
|
.margin(0)
|
|
.fontSize(0.88, em)
|
|
.fontWeight("600")
|
|
.color("var(--headertext)")
|
|
.overflow("hidden")
|
|
.whiteSpace("nowrap")
|
|
.textOverflow("ellipsis")
|
|
.flex(1)
|
|
.textAlign("center")
|
|
|
|
div().width("52px").flexShrink(0)
|
|
})
|
|
.paddingHorizontal(1, em)
|
|
.paddingVertical(0.75, em)
|
|
.alignItems("center")
|
|
.gap(1, em)
|
|
.background("var(--darkaccent)")
|
|
.borderBottom("1px solid var(--divider)")
|
|
.width(100, pct)
|
|
.boxSizing("border-box")
|
|
.flexShrink(0)
|
|
|
|
// Content
|
|
if (isImage) {
|
|
img(this._url, "auto", "auto")
|
|
.display("block")
|
|
.maxWidth(100, pct)
|
|
.maxHeight(h - 48, px)
|
|
.margin("0 auto")
|
|
} else if (isPDF) {
|
|
const wrap = div()
|
|
.flex(1)
|
|
.width(100, pct)
|
|
.overflow("hidden")
|
|
wrap.innerHTML = `<iframe src="${this._url}" style="width:100%;height:100%;border:none;display:block;"></iframe>`
|
|
} else {
|
|
const icon = {
|
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': "📄",
|
|
'application/msword': "📄",
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': "📊",
|
|
'application/vnd.ms-excel': "📊",
|
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation': "📋",
|
|
'application/vnd.ms-powerpoint': "📋",
|
|
'text/plain': "📄",
|
|
}[type] ?? "📎"
|
|
|
|
VStack(() => {
|
|
p(icon).fontSize(3, em).margin(0)
|
|
p(displayName)
|
|
.margin(0)
|
|
.fontSize(0.9, em)
|
|
.color("var(--headertext)")
|
|
.textAlign("center")
|
|
|
|
a(this._url, "Download")
|
|
.attr({ download: displayName })
|
|
.fontSize(0.85, em)
|
|
.color("var(--quillred)")
|
|
.fontWeight("600")
|
|
.fontFamily("Arial")
|
|
.textDecoration("none")
|
|
.cursor("pointer")
|
|
.marginTop(0.25, em)
|
|
.onHover(function(hovering) {
|
|
this.style.textDecoration = hovering ? "underline" : "none"
|
|
})
|
|
})
|
|
.gap(0.5, em)
|
|
.alignItems("center")
|
|
.padding(2, em)
|
|
}
|
|
})
|
|
.background("var(--window)")
|
|
.backdropFilter("blur(18px)")
|
|
.border("0.5px solid var(--window-border)")
|
|
.borderRadius(12, px)
|
|
.overflow("hidden")
|
|
.width(100, pct)
|
|
.boxSizing("border-box")
|
|
|
|
if (isPDF) panel.height(h, px)
|
|
else panel.maxHeight(h, px)
|
|
panel.onClick((done, e) => { e.stopPropagation() })
|
|
})
|
|
.position("fixed")
|
|
.x(x, px)
|
|
.y(y, px)
|
|
.width(w, px)
|
|
.height(h, px)
|
|
.justifyContent(isPDF ? "flex-start" : "center")
|
|
.alignItems("center")
|
|
.onClick((done) => { if (done) this.close() })
|
|
.onEvent("resize", () => this.rerender())
|
|
}
|
|
}
|
|
|
|
register(FilePreview)
|