diff --git a/config/mime.json b/config/mime.json index 66d85313..eb79e623 100644 --- a/config/mime.json +++ b/config/mime.json @@ -5,6 +5,7 @@ "3gpp": "video/3gpp", "7z": "application/x-7z-compressed", "a": "application/x-archive", + "aai": "image/x-dune-aai", "aco": "application/x-aco", "ai": "application/pdf", "aif": "audio/x-aiff", @@ -17,6 +18,7 @@ "asx": "video/x-ms-asf", "atom": "application/atom+xml", "avi": "video/x-msvideo", + "avif": "image/avif", "avro": "application/vnd.apache.avro", "bin": "application/octet-stream", "bmp": "image/x-ms-bmp", @@ -24,16 +26,20 @@ "cab": "application/vnd.ms-cab-compressed", "cap": "application/x-pcap", "cco": "application/x-cocoa", + "cdr": "application/vnd.corel-draw", + "cin": "image/x-cin", "cr2": "image/x-canon-cr2", "crt": "application/x-x509-ca-cert", "crw": "image/x-canon-crw", "css": "text/css", "csv": "text/csv", + "cur": "image/x-win-bitmap", "dae": "model/vnd.collada+xml", "db": "application/x-sqlite3", "dbf": "application/dbf", "dcm": "image/dicom", "dcr": "image/x-kodak-dcr", + "dds": "image/x-dds", "deb": "application/octet-stream", "der": "application/x-x509-ca-cert", "dll": "application/x-msdownload", @@ -45,16 +51,20 @@ "dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "dotm": "application/vnd.ms-word.template.macroEnabled.12", "dpkg": "application/dpkg-www-installer", + "dpx": "image/dpx", "ds_store": "application/octet-stream", "dxf": "application/dxf", "dwg": "application/acad", "dylib": "application/x-dylib", "ear": "application/java-archive", + "emf": "image/emf", + "emz": "image/x-emz", "eot": "application/vnd.ms-fontobject", "eps": "application/postscript", "epub": "application/epub+zip", "erf": "image/x-epson-erf", "exe": "application/octet-stream", + "exr": "image/x-exr", "fbx": "application/fbx", "fea": "application/vnd.apache.feather", "feather": "application/vnd.apache.feather", @@ -84,10 +94,12 @@ "jad": "text/vnd.sun.j2me.app-descriptor", "jar": "application/java-archive", "jardiff": "application/x-java-archive-diff", + "jfif": "image/jpeg", "jng": "image/x-jng", "jnlp": "application/x-java-jnlp-file", "jpeg": "image/jpeg", "jpg": "image/jpeg", + "jp2": "image/jp2", "js": "application/javascript", "json": "application/json", "kar": "audio/midi", @@ -96,6 +108,8 @@ "kicad_sch": "application/vnd.kicad-sch", "kml": "application/vnd.google-earth.kml+xml", "kmz": "application/vnd.google-earth.kmz", + "ktx": "image/ktx", + "ktx2": "image/ktx2", "m3u8": "application/vnd.apple.mpegurl", "m4a": "audio/x-m4a", "m4v": "video/x-m4v", @@ -135,19 +149,26 @@ "org": "text/org", "otf": "font/otf", "parquet": "application/vnd.apache.parquet", + "pbm": "image/x-portable-bitmap", "pdb": "application/x-pilot", "pcap": "application/vnd.tcpdump.pcap", "pcapng": "application/x-pcapng", + "pcd": "image/x-photo-cd", + "pcx": "image/vnd.zbrush.pcx", "pdf": "application/pdf", "pef": "image/x-pentax-pef", "pem": "application/x-x509-ca-cert", + "pes": "image/x-pes", + "pgm": "image/x-portable-greymap", "pkg": "application/x-newton-compatible-pkg", "pl": "application/x-perl", "pm": "application/x-perl", "png": "image/png", + "pnm": "image/x-portable-anymap", "potm": "application/vnd.ms-powerpoint.template.macroEnabled.12", "potx": "application/vnd.openxmlformats-officedocument.presentationml.template", "ppam": "application/vnd.ms-powerpoint.addin.macroEnabled.12", + "ppm": "image/x-portable-pixmap", "pps": "application/vnd.ms-powerpoint", "ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "ppsm": "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", @@ -164,6 +185,8 @@ "ram": "audio/x-pn-realaudio", "rar": "application/x-rar-compressed", "raw": "image/x-raw", + "rgb": "image/x-rgb", + "rgba": "image/x-rgba", "rpm": "application/x-redhat-package-manager", "rss": "application/rss+xml", "rtf": "application/rtf", @@ -171,15 +194,18 @@ "run": "application/x-makeself", "rw2": "image/x-panasonic-rw2", "sea": "application/x-sea", + "sgi": "image/x-sgi", "shtml": "text/html", "shp": "application/vnd.shp", "shx": "application/vnd.shx", "sit": "application/x-stuffit", + "sketch": "application/x-sketch", "so": "application/x-sharedlib", "sql": "application/x-sqlite3", "sqlite": "application/x-sqlite3", "sqlite3": "application/x-sqlite3", "sr2": "image/x-sony-sr2", + "srf": "image/x-sony-srf", "srw": "image/x-samsung-srw", "stl": "model/stl", "step": "model/step", @@ -189,6 +215,7 @@ "swf": "application/x-shockwave-flash", "tar": "application/x-tar", "tcl": "application/x-tcl", + "tga": "image/x-tga", "tgz": "application/x-gzip", "tif": "image/tiff", "tiff": "image/tiff", @@ -214,16 +241,22 @@ "wmv": "video/x-ms-wmv", "woff": "font/woff", "woff2": "font/woff2", + "wbmp": "image/vnd.wap.wbmp", "wrl": "x-world/x-vrml", "x3d": "model/x3d+xml", "x3dv": "model/x3d-vrml", "x3db": "model/x3d+fastinfoset", "x3f": "image/x-x3f", + "xbm": "image/x-xbitmap", + "xcf": "image/x-xcf", + "xd": "application/x-adobe-xd", "xhtml": "application/xhtml+xml", "xls": "application/vnd.ms-excel", "xlsx": "application/excel", "xml": "application/xml", "xpi": "application/x-xpinstall", + "xpm": "image/x-xpixmap", + "xwd": "image/x-xwindowdump", "xspf": "application/xspf+xml", "zip": "application/zip" } diff --git a/public/assets/pages/viewerpage/application_downloader.js b/public/assets/pages/viewerpage/application_downloader.js index bd7f87ae..246c88fd 100644 --- a/public/assets/pages/viewerpage/application_downloader.js +++ b/public/assets/pages/viewerpage/application_downloader.js @@ -9,10 +9,10 @@ import { transition } from "./common.js"; import "../../components/icon.js"; import "./component_menubar.js"; -export default async function(render, { acl$, getFilename, getDownloadUrl }) { +export default async function(render, { acl$, getFilename, getDownloadUrl, hasMenubar = true }) { const $page = createElement(`
- +
${t("DOWNLOAD")} diff --git a/public/assets/pages/viewerpage/application_image.css b/public/assets/pages/viewerpage/application_image.css index 8b01d090..360a76b7 100644 --- a/public/assets/pages/viewerpage/application_image.css +++ b/public/assets/pages/viewerpage/application_image.css @@ -2,14 +2,8 @@ body:not(.dark-mode) .component_imageviewer .component_image_container .fullscreen .component_pager .wrapper > span { background: #525659; } - -.component_imageviewer, .component_imageviewer .component_image_container > .images_wrapper { - flex: 1; - display: flex; - overflow: hidden; - width: 100%; - height: 100%; - flex-direction: column; +.dark-mode .component_imageviewer .component_image_container { + background: #2d2f31; } .component_imageviewer .component_image_container { @@ -19,10 +13,40 @@ body:not(.dark-mode) .component_imageviewer .component_image_container .fullscre width: 100%; text-align: center; overflow: hidden; - padding: 10px 10px 10px 10px; height: 100%; box-sizing: border-box; } +.component_imageviewer, .component_imageviewer .images_wrapper { + flex: 1; + display: flex; + overflow: hidden; + width: 100%; + height: 100%; + flex-direction: column; + position: relative; + justify-content: center; +} +.component_imageviewer img.photo { + margin: 10px; + width: fit-content; + max-width: 98%;; + min-height: 100px; + max-height: 100%; + background: var(--dark); + box-shadow: rgba(0, 0, 0, 0.14) 0px 4px 5px 0px, rgba(0, 0, 0, 0.12) 0px 1px 10px 0px, rgba(0, 0, 0, 0.2) 0px 2px 4px -1px; + border-radius: 2px; + align-self: center; +} +.component_imageviewer img.photo.idle { + transition: 0.2s ease transform; +} +@media screen and (max-width: 500px) { + .component_imageviewer img.photo { + margin: 7px; + } +} + +/* fullscreen mode */ .component_imageviewer .component_image_container.fullscreen { background: var(--dark); } @@ -32,161 +56,113 @@ body:not(.dark-mode) .component_imageviewer .component_image_container .fullscre .component_imageviewer .component_image_container.fullscreen img.photo { background: var(--color); } -@media screen and (max-height: 410px) { - .component_imageviewer .component_image_container { - padding: 5px 0px 40px 10px; - } - .component_imageviewer .component_image_container .component_pager .wrapper { - padding: 5px 0; - } - .component_imageviewer .component_image_container .component_pager .wrapper > span { - padding: 2px 5px; - } - .component_imageviewer .component_image_container .images_aside { - margin: -5px -5px -40px 10px !important; - } -} -.component_imageviewer .component_image_container .images_wrapper { - width: 100%; - position: relative; - justify-content: center; -} -.component_imageviewer .component_image_container .images_wrapper > span { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; -} -.component_imageviewer .component_image_container .images_aside { - flex: 0; - text-align: left; - width: 0; - z-index: 1; - min-width: 0px; - transition: 0.3s ease min-width; - border-left: 1px solid var(--color); - background: #949290; - margin: -15px -10px -65px 10px; - color: var(--dark); -} -.component_imageviewer .component_image_container .images_aside.open { - min-width: 300px; - transition: 0.5s ease min-width; -} -@media screen and (max-width: 850px) { - .component_imageviewer .component_image_container .images_aside.open { - min-width: 250px; - font-size: 0.94em; - } - .component_imageviewer .component_image_container .images_aside.open .header, .component_imageviewer .component_image_container .images_aside.open .content { - padding: 15px 15px 0px 15px; - } -} -@media screen and (max-width: 650px) { - .component_imageviewer .component_image_container .images_aside.open { - min-width: 200px; - } -} -@media screen and (max-width: 580px) { - .component_imageviewer .component_image_container .images_aside.open { - width: 0px; - min-width: 0; - } -} -.component_imageviewer .component_image_container .images_aside.open .content { - transform: translateX(0px); - opacity: 1; -} -.component_imageviewer .component_image_container .images_aside .content { - transition: 0.2s ease opacity, 0.3s ease transform; - opacity: 0; - transform: translateX(10px); - transition-delay: 0.2s; -} -.component_imageviewer .component_image_container .images_aside .header { - display: flex; - line-height: 25px; - white-space: nowrap; - padding: 20px 25px; - font-size: 1.25em; -} -.component_imageviewer .component_image_container .images_aside .header .component_icon { - height: 18px; - float: right; - cursor: pointer; -} -.component_imageviewer .component_image_container .images_aside .content { - padding: 10px 20px 0px 20px; -} -.component_imageviewer .component_image_container .images_aside .content .content_box { - clear: both; - opacity: 0.85; - margin-bottom: 20px; -} -.component_imageviewer .component_image_container .images_aside .content .content_box > div { - margin: 3px 0; - width: calc(100% - 40px); -} -.component_imageviewer .component_image_container .images_aside .content .content_box .component_icon { - height: 30px; - width: 30px; - float: left; - padding: 5px 10px 5px 0; -} -.component_imageviewer .component_image_container .images_aside .content .component_mapshot { - margin-bottom: 10px; -} -.component_imageviewer .component_image_container .images_aside .content .more, .component_imageviewer .component_image_container .images_aside .content .meta_key { - text-align: right; - font-size: 0.9em; - margin: 10px 0; -} -.component_imageviewer .component_image_container .images_aside .content .more_container { - margin: 30px 0 50px 0; - padding-bottom: 20px; -} -.component_imageviewer .component_image_container .images_aside .content .more_container .meta_key { - display: flex; - justify-content: space-between; - margin: 5px 0; - border-top: 1px dashed var(--color); - padding-top: 5px; -} -.component_imageviewer .component_image_container .images_aside .content .more_container .meta_key .title { - margin-right: 5px; -} -.component_imageviewer .component_image_container .images_aside .content .more_container .meta_key .value { - color: var(--bg-color); -} -.component_imageviewer .component_image_container img.photo:not(.error) { - margin: auto; - max-height: 100%; - max-width: 100%; - min-height: 100px; - background: var(--dark); - box-shadow: rgba(0, 0, 0, 0.14) 0px 4px 5px 0px, rgba(0, 0, 0, 0.12) 0px 1px 10px 0px, rgba(0, 0, 0, 0.2) 0px 2px 4px -1px; - border-radius: 2px; -} -.component_imageviewer .component_image_container img.photo.idle { - transition: 0.2s ease transform; -} +/* image loading spinner */ .component_imageviewer .component_loader { margin-top: 0; } .component_imageviewer .component_loader img { width: 40px; } -.component_imageviewer .error { + +/* error loading image */ +.component_imageviewer .component_filedownloader { margin: 0 auto; } + +/* information menu */ +.component_imageviewer .images_aside { + flex: 0; + text-align: left; + width: 0; + z-index: 1; + min-width: 0px; + transition: 0.15s ease min-width; + border-left: 1px solid var(--border); + background: #949290; color: var(--dark); - font-size: 1.3em; } -.component_imageviewer .component_image_container img.error { - filter: contrast(0.8); - width: 160px; - margin: 0 auto; +.dark-mode .component_imageviewer .images_aside { + background: #f2f2f2; } -.dark-mode .component_imageviewer .component_image_container { - background: #232426; +.component_imageviewer .images_aside.open { + min-width: 300px; + transition: 0.5s ease min-width; + transition: 0.3s ease min-width; +} +@media screen and (max-width: 850px) { + .component_imageviewer .images_aside.open { + min-width: 250px; + font-size: 0.94em; + } + .component_imageviewer .images_aside.open [data-bind="header"], + .component_imageviewer .images_aside.open [data-bind="body"] { + padding: 15px 15px 0px 15px; + } +} +@media screen and (max-width: 650px) { + .component_imageviewer .images_aside.open { + min-width: 200px; + } +} +@media screen and (max-width: 580px) { + .component_imageviewer .images_aside.open { + width: 0px; + min-width: 0; + } +} +.component_imageviewer .images_aside.open [data-bind="body"] { + transform: translateX(0px); + opacity: 1; +} +.component_imageviewer .images_aside [data-bind="body"] { + transition: 0.2s ease opacity, 0.3s ease transform; + opacity: 0; + transform: translateX(10px); + transition-delay: 0.2s; +} +.component_imageviewer .images_aside .header { + display: flex; + line-height: 25px; + white-space: nowrap; + padding: 20px 25px; + font-size: 1.25em; +} +.component_imageviewer .images_aside .header .component_icon { + height: 18px; + float: right; + cursor: pointer; +} +.component_imageviewer .images_aside [data-bind="body"] { + padding: 10px 20px 0px 20px; +} +.component_imageviewer .images_aside [data-bind="body"] .content_box { + clear: both; + opacity: 0.85; + margin-bottom: 20px; +} +.component_imageviewer .images_aside [data-bind="body"] .content_box > div { + width: calc(100% - 40px); +} +.component_imageviewer .images_aside [data-bind="body"] .content_box .component_icon { + height: 30px; + width: 30px; + float: left; + padding: 5px 10px 5px 0; +} +.component_imageviewer .images_aside [data-bind="body"] .component_mapshot { + margin-bottom: 10px; +} +.component_imageviewer .images_aside .meta_key { + display: flex; + justify-content: space-between; + margin: 5px 0; + border-top: 1px solid #ffffff15; + padding-top: 5px; + text-align: right; + font-size: 0.85em; +} +.component_imageviewer .images_aside .meta_key .title { + margin-right: 5px; +} +.component_imageviewer .images_aside .meta_key .value { + color: var(--bg-color); } diff --git a/public/assets/pages/viewerpage/application_image.js b/public/assets/pages/viewerpage/application_image.js index 5936ad2e..9d49d19a 100644 --- a/public/assets/pages/viewerpage/application_image.js +++ b/public/assets/pages/viewerpage/application_image.js @@ -1,10 +1,12 @@ import { createElement, createRender, onDestroy } from "../../lib/skeleton/index.js"; import { toHref } from "../../lib/skeleton/router.js"; import rxjs, { effect, onLoad, onClick } from "../../lib/rx.js"; +import ajax from "../../lib/ajax.js"; import { animate } from "../../lib/animate.js"; import { extname } from "../../lib/path.js"; import { qs } from "../../lib/dom.js"; import { get as getConfig } from "../../model/config.js"; +import { load as loadPlugin } from "../../model/plugin.js"; import { Chromecast } from "../../model/chromecast.js"; import { loadCSS } from "../../helpers/loader.js"; import { createLoader } from "../../components/loader.js"; @@ -15,17 +17,22 @@ import ctrlError from "../ctrl_error.js"; import { transition } from "./common.js"; import componentMetadata, { init as initMetadata } from "./application_image_metadata.js"; +import ctrlDownloader, { init as initDownloader } from "./application_downloader.js"; import componentPager, { init as initPager } from "./component_pager.js"; import { renderMenubar, buttonDownload, buttonFullscreen } from "./component_menubar.js"; -export default function(render, { getFilename, getDownloadUrl, hasMenubar = true }) { +class IImage { + getSRC() { throw new Error("NOT_IMPLEMENTED"); } +} + +export default function(render, { getFilename, getDownloadUrl, mime, hasMenubar = true, acl$ }) { const $page = createElement(`
- +
@@ -37,6 +44,7 @@ export default function(render, { getFilename, getDownloadUrl, hasMenubar = true const $imgContainer = qs($page, ".images_wrapper"); const $photo = qs($page, "img.photo"); + const $menubar = qs($page, "component-menubar"); const removeLoader = createLoader($imgContainer); const load$ = new rxjs.BehaviorSubject(null); const toggleInfo = () => { @@ -45,17 +53,25 @@ export default function(render, { getFilename, getDownloadUrl, hasMenubar = true }; renderMenubar( - qs($page, "component-menubar"), + $menubar, buttonDownload(getFilename(), getDownloadUrl()), buttonFullscreen(qs($page, ".component_image_container")), buttonInfo({ toggle: toggleInfo }), buttonChromecast(getFilename(), getDownloadUrl()), ); - effect(onLoad($photo).pipe( - rxjs.tap(() => { - load$.next($photo); + effect(rxjs.from(loadPlugin(mime)).pipe( + rxjs.mergeMap(async(loader) => { + let src = `${getDownloadUrl()}&size=${window.innerWidth}`; + if (loader) { + const { response } = await ajax({ url: getDownloadUrl(), responseType: "arraybuffer" }).toPromise(); + const img = new (await loader(IImage, { mime, $menubar, getFilename, getDownloadUrl }))(); + src = await img.getSRC(response); + } + $photo.setAttribute("src", src); + await onLoad($photo).toPromise(); }), + rxjs.tap(() => load$.next($photo)), removeLoader, rxjs.tap(() => animate($photo, { onEnter: () => $photo.classList.remove("hidden"), @@ -69,25 +85,18 @@ export default function(render, { getFilename, getDownloadUrl, hasMenubar = true })), rxjs.catchError((err) => { if (err.target instanceof HTMLElement && err.type === "error") { - return rxjs.of($photo).pipe( + return rxjs.of(initDownloader()).pipe( removeLoader, - rxjs.tap(($img) => { - $img.setAttribute("src", "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgaGVpZ2h0PSIxNiIKICAgd2lkdGg9IjE2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmcyNzU2IgogICBzb2RpcG9kaTpkb2NuYW1lPSJkb3dubG9hZC5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMi4yIChiMGE4NDg2NTQxLCAyMDIyLTEyLTAxKSIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMjc2MCIgLz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9Im5hbWVkdmlldzI3NTgiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjMDAwMDAwIgogICAgIGJvcmRlcm9wYWNpdHk9IjAuMjUiCiAgICAgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlY2hlY2tlcmJvYXJkPSIwIgogICAgIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIKICAgICBzaG93Z3JpZD0iZmFsc2UiCiAgICAgaW5rc2NhcGU6em9vbT0iNDEuNzE5MyIKICAgICBpbmtzY2FwZTpjeD0iMTEuMzI1NjkzIgogICAgIGlua3NjYXBlOmN5PSI4LjU1NzE5MDUiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxOTA0IgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjExNTciCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjciCiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjM0IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMjc1NiIgLz4KICA8cGF0aAogICAgIHN0eWxlPSJjb2xvcjojMDAwMDAwO3RleHQtaW5kZW50OjA7dGV4dC10cmFuc2Zvcm06bm9uZTtmaWxsOiMzYjQwNDU7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlLXdpZHRoOjAuOTg0ODEwNDEiCiAgICAgZD0ibSAyLDEzLjA4MjQxMiAwLjAxOTQ2MiwxLjQ5MjM0NyBjIDVlLTYsMC4yMjIxNDUgMC4yMDU1OTAyLDAuNDI0MjYyIDAuNDMxMTUwMiwwLjQyNDI3MiBMIDEzLjU4OTYxMiwxNSBDIDEzLjgxNTE3MywxNC45OTk5OTUgMTMuOTk5OTksMTQuNzk3ODc0IDE0LDE0LjU3NTcyOSB2IC0xLjQ5MzMxNyBjIC00LjE3MTg2OTIsMC42NjIwMjMgLTcuNjUxNjkyOCwwLjM5ODY5NiAtMTIsMCB6IgogICAgIGlkPSJwYXRoMjc1MCIgLz4KICA8cGF0aAogICAgIHN0eWxlPSJjb2xvcjojMDAwMDAwO3RleHQtaW5kZW50OjA7dGV4dC10cmFuc2Zvcm06bm9uZTtkaXNwbGF5OmlubGluZTtmaWxsOiNmOWY5ZmE7c3Ryb2tlLXdpZHRoOjAuOTg0MDgxMjc7ZmlsbC1vcGFjaXR5OjEiCiAgICAgZD0iTSAyLjM1MDEsMS4wMDEzMzEyIEMgMi4xNTI1OSwxLjAzODMyNDcgMS45OTY1OSwxLjIyNzI3MjMgMi4wMDAwOSwxLjQyNDkzNTYgViAxNC4xMzM0NTcgYyA1ZS02LDAuMjIxODE2IDAuMjA1MjMsMC40MjM2MzQgMC40MzA3OSwwLjQyMzY0NCBsIDExLjEzOSwtMS4wMWUtNCBjIDAuMjI1NTYsLTZlLTYgMC40MzAxMSwtMC4yMDA3NTggMC40MzAxMiwtMC40MjI1NzQgbCA2LjdlLTQsLTkuODIyNjQyNiBjIC0yLjQ4NDA0NiwtMS4zNTUwMDYgLTIuNDM1MjM0LC0yLjAzMTIyNTQgLTMuNTAwMSwtMy4zMDk3MDcgLTAuMDQzLC0wLjAxNTg4MiAwLjA0NiwwLjAwMTc0IDAsMCBMIDIuNDMwNjcsMS4wMDExMDggQyAyLjQwMzgzLDAuOTk4NTkgMi4zNzY3NCwwLjk5ODU5IDIuMzQ5OSwxLjAwMTEwOCBaIgogICAgIGlkPSJwYXRoMjc1MiIgLz4KICA8cGF0aAogICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZTtmaWxsOiMzYjQwNDU7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOiM5ZTc1NzU7c3Ryb2tlLXdpZHRoOjA7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6NDtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICBkPSJtIDEwLjUwMDU3LDEuMDAyMDc2NCBjIDAsMy4yNzY4MDI4IC0wLjAwNTIsMy4xNzM5MTYxIDAuMzYyOTIxLDMuMjY5ODIwMiAwLjI4MDEwOSwwLjA3Mjk4NCAzLjEzNzE4LDAuMDM5ODg3IDMuMTM3MTgsMC4wMzk4ODcgLTEuMTIwMDY3LC0xLjA1NTY2OTIgLTIuMzMzNCwtMi4yMDY0NzEzIC0zLjUwMDEsLTMuMzA5NzA3NCB6IgogICAgIGlkPSJwYXRoMjc1NCIgLz4KPC9zdmc+Cg=="); - $img.classList.remove("hidden"); - $img.classList.add("error"); - $img.parentElement.appendChild(createElement(` -
- ${t("Not Supported")} -
- `)); + rxjs.mergeMap(() => { + load$.error(err); + ctrlDownloader(createRender(qs($page, ".images_wrapper")), { acl$, getFilename, getDownloadUrl, hasMenubar: false }); + return rxjs.EMPTY; }), - rxjs.catchError(ctrlError()), ); } return ctrlError()(err); }), )); - componentPager(createRender(qs($page, ".component_pager"))); } diff --git a/public/assets/pages/viewerpage/application_image_metadata.js b/public/assets/pages/viewerpage/application_image_metadata.js index 981a44f2..b298945b 100644 --- a/public/assets/pages/viewerpage/application_image_metadata.js +++ b/public/assets/pages/viewerpage/application_image_metadata.js @@ -28,13 +28,12 @@ function componentHeader(render, { toggle }) {
`); render($header); - effect(onClick(qs($header, `[alt="close"]`)).pipe(rxjs.tap(toggle))); } function componentBody(render, { load$ }) { const $page = createElement(` -
+
schedule
-
@@ -63,6 +62,9 @@ function componentBody(render, { load$ }) { if (metadata.location) await componentMap(createRender(qs($page, `[data-bind="map"]`)), { metadata }); componentMore(createRender(qs($page, `[data-bind="all"]`)), { metadata }); + }), rxjs.catchError((err) => { + qs($page, `[data-bind="all"]`).remove(); + return rxjs.EMPTY; }))); } @@ -155,13 +157,6 @@ async function componentMap(render, { metadata }) { } function componentMore(render, { metadata }) { - const $page = createElement(` -
-
-
- `); - render($page); - const $all = document.createDocumentFragment(); const formatKey = (str) => str.replace(/([A-Z][a-z])/g, " $1"); const formatValue = (str) => { @@ -209,7 +204,7 @@ function componentMore(render, { metadata }) { `)); } }); - qs($page, ".more_container").appendChild($all); + render($all); } export function init() { @@ -222,6 +217,7 @@ export function init() { const extractExif = ($img) => new Promise((resolve) => window.EXIF.getData($img, function() { const metadata = window.EXIF.getAllTags($img); const to_date = (str = "") => { + if (str === "") return null; const digits = str.split(/[ :]/).map((digit) => parseInt(digit)); return new Date( digits[0] || 0, diff --git a/public/assets/pages/viewerpage/application_skeleton.js b/public/assets/pages/viewerpage/application_skeleton.js index 864fca31..d78056a8 100644 --- a/public/assets/pages/viewerpage/application_skeleton.js +++ b/public/assets/pages/viewerpage/application_skeleton.js @@ -7,10 +7,10 @@ import { createLoader } from "../../components/loader.js"; import ctrlError from "../ctrl_error.js"; import componentDownloader, { init as initDownloader } from "./application_downloader.js"; -export default function(render, { mime, getFilename, getDownloadUrl, acl$ }) { +export default function(render, { mime, getFilename, getDownloadUrl, acl$, hasMenubar = true }) { const $page = createElement(`
- +
`); diff --git a/public/assets/pages/viewerpage/mimetype.js b/public/assets/pages/viewerpage/mimetype.js index b7a17065..609f01aa 100644 --- a/public/assets/pages/viewerpage/mimetype.js +++ b/public/assets/pages/viewerpage/mimetype.js @@ -12,10 +12,7 @@ export function opener(file = "", mimes) { } const p = getPlugin(mime); - if (p) return [ - p[0], - { mime, loader: p[1] }, - ]; + if (p) return [p[0], { mime, ...p[1] }]; if (type === "text") { return ["editor", { mime }]; diff --git a/server/ctrl/plugin.go b/server/ctrl/plugin.go index f21c2425..7b275eb6 100644 --- a/server/ctrl/plugin.go +++ b/server/ctrl/plugin.go @@ -4,6 +4,7 @@ import ( "io" "net/http" "os" + "path/filepath" "strings" . "github.com/mickael-kerjean/filestash/server/common" @@ -32,7 +33,7 @@ func PluginExportHandler(ctx *App, res http.ResponseWriter, req *http.Request) { } plgExports[module["mime"]] = []string{ module["application"], - WithBase(JoinPath("/plugin/", name+index)), + WithBase(JoinPath("/plugin/", filepath.Join(name, index))), } } }