瀏覽代碼

Fix #9 popin shortcut & management

isundil 2 年之前
父節點
當前提交
a7898c6f0e

+ 2 - 0
router/api.js

@@ -9,6 +9,8 @@ const MediaFileTagModel = require('../model/mediaItemTag.js').MediaFileTagModel;
 const { AccessModel, ACCESS_TYPE, ACCESS_GRANT } = require('../model/access.js');
 
 function MediaToJson(mediaData) {
+    if (!mediaData)
+        return null;
     if (mediaData.accessType === ACCESS_GRANT.readNoMeta)
         mediaData.meta = {
             height: mediaData.meta?.height,

+ 69 - 6
static/public/css/style.css

@@ -1,3 +1,20 @@
+body.overlay-visible #fullScreenOverlay {
+    display: block;
+}
+
+#fullScreenOverlay {
+    display: none;
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: 0;
+    padding: 0;
+    background-color: rgba(0, 0, 0, .75);
+    z-index: 1040;
+}
+
 #pch-navbar .dropdown-menu[data-bs-popper] {
     left: initial;
     right: 0;
@@ -95,6 +112,7 @@ body.filter-active #pch-navbar .bt-filter-inactive {
 
 .pch-image {
     position: relative;
+    text-align: center;
 }
 
 .pch-image .spinner {
@@ -111,7 +129,7 @@ body.filter-active #pch-navbar .bt-filter-inactive {
 }
 
 .pch-image.loading img {
-    visibility: hidden;
+    display: none;
 }
 
 .hidden {
@@ -125,8 +143,11 @@ body.filter-active #pch-navbar .bt-filter-inactive {
     right: 0;
     top: 0;
     bottom: 0;
-    padding: 1.5em;
+    margin: 1.5em;
     overflow: hidden;
+    height: auto;
+    width: auto;
+    z-index: 1050;
 }
 
 #pch-fullPageMedia > div {
@@ -141,9 +162,39 @@ body.filter-active #pch-navbar .bt-filter-inactive {
 }
 
 #pch-fullPageMedia .modal-body {
+    overflow: hidden;
+    max-width: initial;
+}
+
+#pch-fullPageMedia .modal-body > .row {
+    height: 100%;
+    width: 100%;
+    display: inline-flex;
+    overflow: hidden;
+}
+
+#pch-fullPageMedia .modal-body > .row > .col:first-child {
+    display: inline-flex;
+    justify-content: center;
+    align-items: center;
+}
+
+#pch-fullPageMedia .modal-body > .row > .col {
+    height: 100%;
     overflow-x: hidden;
     overflow-y: auto;
-    max-width: initial;
+}
+
+#pch-fullPageMedia #pch-fullPagePreviewContainer {
+    max-height: 100%;
+    display: inline-flex;
+    flex: 1;
+}
+
+#pch-fullPagePreview {
+    max-height: 100%;
+    max-width: 100%;
+    object-fit: contain;
 }
 
 #pch-fullPageDetail {
@@ -180,17 +231,22 @@ body.filter-active #pch-navbar .bt-filter-inactive {
 
 .login-wrapper {
     position: fixed;
+    justify-content: center;
+    align-items: center;
+    text-align: center;
+    z-index: 1050;
     top: 0;
     bottom: 0;
     left: 0;
     right: 0;
-    background: rgba(0, 0, 0, 0.7);
-    z-index: 20;
+    max-height: fit-content;
+    max-width: fit-content;
+    margin: auto;
     display: none;
 }
 
 body.login-visible .login-wrapper {
-    display: initial;
+    display: flex;
 }
 
 .login-wrapper .modal {
@@ -198,6 +254,13 @@ body.login-visible .login-wrapper {
     flex-direction: column;
     justify-content: center;
     align-items: center;
+
+
+    position: static;
+    display: inline;
+    margin: 0;
+    width: auto;
+    height: auto;
 }
 
 .login-wrapper hr {

+ 3 - 2
static/public/js/common.js

@@ -27,12 +27,13 @@ $(() => {
                 let chronology = window.chronology.isInitialized() ? "" : "&chronology"
                 let oldest = (MediaStorage.Instance.oldest?.date?.getTime() || 0);
                 let oldestArg = oldest ? `&from=${oldest}` : "";
-                $.get(`/api/media/list?count=100${chronology}${oldestArg}`, data => {
+                let requestCount = 100;
+                $.get(`/api/media/list?count=${requestCount}${chronology}${oldestArg}`, data => {
                     MediaStorage.Instance.pushAll(data.data.map(i => new Media(i)));
                     if (data.first || data.last)
                         window.chronology.rebuildRange(data.first, data.last);
                     loadingMediaList = false;
-                    if ((data.data?.length || 0) === 0) {
+                    if ((data.data?.length || 0) < requestCount) {
                         loadingMediaList = true;
                         document.getElementById("pch-infiniteScrollLoading").classList.add("hidden");
                         window.ReloadFilters(MediaStorage.Instance);

+ 21 - 7
static/public/js/taskQueue.js

@@ -8,15 +8,29 @@ let LoadingTasks = (() => {
         if (activeTask || tasks.length === 0)
             return;
         activeTask = (tasks.shift());
-        let taskResult = activeTask.fnc();
+        let taskResult = null;
+        try {
+            activeTask.fnc();
+        }
+        catch (err) {
+            taskResult = Promise.reject(err);
+        }
         if (!(taskResult instanceof Promise))
             taskResult = Promise.resolve(activeTask);
-        taskResult.then(() => {
-            let ok = activeTask.ok;
-            activeTask = null;
-            ok(taskResult.result);
-            runNextTask();
-        });
+        taskResult
+            .then(() => {
+                let ok = activeTask.ok;
+                activeTask = null;
+                ok(taskResult.result);
+            })
+            .catch(() => {
+                let ko = activeTask.ko;
+                activeTask = null;
+                ko(taskResult.result);
+            })
+            .finally(() => {
+                runNextTask();
+            });
     };
 
     return {

+ 6 - 3
static/public/js/uiAccess.js

@@ -4,18 +4,21 @@ $(() => {
 document.getElementById("menu-login").addEventListener("click", e => {
     e.preventDefault();
     document.body.classList.add("login-visible")
+    document.body.classList.add("overlay-visible");
 });
 
 function closeLoginPopin() {
+    if (!document.body.classList.contains("login-visible"))
+        return;
     document.body.classList.remove("login-visible");
+    document.body.classList.remove("overlay-visible");
     let inputFields = document.querySelectorAll(".login-wrapper .input-group input");
     for (let i =0; i < inputFields.length; ++i)
         inputFields[i].value = "";
 }
 
-document.addEventListener("keydown", evt => {
-    if (evt.keyCode === 27)
-        closeLoginPopin();
+document.onClosePopinRequested(() => {
+    closeLoginPopin();
 });
 
 document.querySelector(".login-wrapper .modal-footer button").addEventListener("click", () => closeLoginPopin());

+ 24 - 0
static/public/js/uiCommon.js

@@ -0,0 +1,24 @@
+
+$(() => {
+    let closePopinsRequestedHandlers = [];
+    window.lastKeyboardEvent = null;
+
+    document.addEventListener("keyup", evt => {
+        window.lastKeyboardEvent = evt;
+    });
+
+    function triggerClosePopinsRequestHandlers() {
+        for (let i of closePopinsRequestedHandlers)
+            i();
+    }
+
+    document.addEventListener("keydown", evt => {
+        window.lastKeyboardEvent = evt;
+        if (evt.keyCode === 27)
+            triggerClosePopinsRequestHandlers();
+    });
+
+    document.getElementById("fullScreenOverlay").addEventListener("click", triggerClosePopinsRequestHandlers);
+    document.onClosePopinRequested = (hndl) => closePopinsRequestedHandlers.push(hndl);
+});
+

+ 2 - 3
static/public/js/uiFilter.js

@@ -50,9 +50,8 @@ $(() => {
             filterBarDom.style.display = "flex"
     });
 
-    document.addEventListener("keydown", evt => {
-        if (evt.keyCode === 27)
-            document.getElementById('pch-filterbarContainer').style.display = "";
+    document.onClosePopinRequested(() => {
+        document.getElementById('pch-filterbarContainer').style.display = "";
     });
 });
 

+ 9 - 6
static/public/js/uiMediaFullpage.js

@@ -164,7 +164,7 @@ $(() => {
             document.getElementById("pch-fullPagePreviewContainer").classList.add("loading");
             document.getElementById("pch-fullPageMedia-title").innerText = fileName;
             document.getElementById("pch-fullPagePreview").onceLoaded = ok;
-            document.getElementById("pch-fullPagePreview").src = imgUrl;
+            document.getElementById("pch-fullPagePreview").src = imgUrl ?? "";
             document.getElementById("pch-fullPageDetail").innerText = "";
             document.getElementById("pch-fullPageDetail").appendChild(displayMetas(Object.assign({}, metaData || {}), !writeAccess));
             document.getElementById("pch-fullPageDetail").appendChild(displayTags(metaData?.fixedTags || [], metaData?.tags || [], writeAccess));
@@ -198,6 +198,8 @@ $(() => {
     }
 
     function CloseFullpageMedia() {
+        if (fullPageMediaDisplayed !== false)
+            document.body.classList.remove("overlay-visible");
         document.getElementById("pch-fullPageMedia").classList.add("hidden");
         fullPageMediaDisplayed = false;
         history.pushState({}, '', '#');
@@ -205,9 +207,10 @@ $(() => {
 
     window.displayMediaFullPage = function(mediaItem) {
         document.getElementById("pch-fullPageMedia").classList.remove("hidden");
-        fullPageMediaDisplayed = mediaItem;
+        fullPageMediaDisplayed = mediaItem ?? null;
+        document.body.classList.add("overlay-visible");
         if (!mediaItem)
-            return _displayMediaFullPage("Error", null, {}, [], null, false);
+            return _displayMediaFullPage("Error", null, {}, null, false);
         let containerSize = document.getElementById("pch-fullPageMedia").getBoundingClientRect();
         let requestSize = mediaItem.resize(containerSize.width, containerSize.height);
         document.getElementById("pch-fullPagePreview").parentNode.style.maxWidth = "100%";
@@ -221,7 +224,8 @@ $(() => {
         };
         if (document.location.hash != `#${mediaItem.md5sum}`)
             history.pushState({}, '', `#${mediaItem.md5sum}`);
-        return _displayMediaFullPage(mediaItem.fileName, `${mediaItem.thumbnail}?w=${requestSize.width}&h=${requestSize.height}&q=6`, meta, mediaItem.original, mediaItem.writeAccess);
+        const requestSizeQuery = requestSize ? `&w=${requestSize.width}&h=${requestSize.height}` : "";
+        return _displayMediaFullPage(mediaItem.fileName, `${mediaItem.thumbnail}?q=6${requestSizeQuery}`, meta, mediaItem.original, mediaItem.writeAccess);
     }
 
     document.getElementById("pch-fullPageMedia-closeBt")
@@ -248,7 +252,6 @@ $(() => {
             LoadPreviousMedia();
         else if (evt.keyCode === 39 || evt.keyCode === 40)
             LoadNextMedia();
-        else if (evt.keyCode === 27)
-            CloseFullpageMedia();
     });
+    document.onClosePopinRequested(() => { CloseFullpageMedia(); });
 });

+ 1 - 1
templates/_footer.js

@@ -4,10 +4,10 @@ module.exports = `
 <script src="/public/bootstrap/bootstrap.bundle.min.js"></script>
 <script src="/public/js/popper.min.js"></script>
 <script src="/public/js/BsMultiSelect.min.js"></script>
-<script src="/public/js/keyboard.js"></script>
 <script src="/public/js/taskQueue.js"></script>
 <script src="/public/js/medias.js"></script>
 <script src="/public/js/filters.js"></script>
+<script src="/public/js/uiCommon.js"></script>
 <script src="/public/js/uiMedia.js"></script>
 <script src="/public/js/uiMediaFullpage.js"></script>
 <script src="/public/js/uiAccess.js"></script>

+ 1 - 0
templates/index.js

@@ -1,6 +1,7 @@
 
 module.exports = require('./_header.js') +require('./_menu.js')
     +`
+<div id="fullScreenOverlay"></div>
 <div id="pch-page">
     <ul id="pch-mediaList" class="container-fluid"></ul>
     <div class="spinner" id="pch-infiniteScrollLoading">