From c2c4799696322f56ecf26abe955314b75575049c Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sat, 5 Nov 2022 19:04:48 -0700 Subject: [PATCH] viewer: add sidebar --- src/App.vue | 8 +- src/components/SelectionManager.vue | 5 +- src/components/Viewer.vue | 143 ++++++++++++++++++++++++++-- 3 files changed, 141 insertions(+), 15 deletions(-) diff --git a/src/App.vue b/src/App.vue index ca4105ae..c8244f68 100644 --- a/src/App.vue +++ b/src/App.vue @@ -271,13 +271,13 @@ body { } // Top bar is above everything else on mobile -#content-vue.has-top-bar { +body.has-top-bar header { @media (max-width: 1024px) { - z-index: 3000; + z-index: 0 !important; } } -#content-vue.has-viewer { - z-index: 3000; +body.has-viewer header { + z-index: 0 !important; } // Patch viewer to remove the title and diff --git a/src/components/SelectionManager.vue b/src/components/SelectionManager.vue index f0ca9c43..62d13df0 100644 --- a/src/components/SelectionManager.vue +++ b/src/components/SelectionManager.vue @@ -183,12 +183,11 @@ export default class SelectionManager extends Mixins(GlobalMixin, UserConfig) { @Watch("show") onShowChange() { - const elem = document.getElementById("content-vue"); const klass = "has-top-bar"; if (this.show) { - elem.classList.add(klass); + document.body.classList.add(klass); } else { - elem.classList.remove(klass); + document.body.classList.remove(klass); } } diff --git a/src/components/Viewer.vue b/src/components/Viewer.vue index 3bb9d7c7..2918fad9 100644 --- a/src/components/Viewer.vue +++ b/src/components/Viewer.vue @@ -1,8 +1,13 @@ + + {{ t("memories", "Sidebar") }} + + { + const sidebarWidth = this.sidebarOpen ? this.sidebarWidth : 0; + this.outerWidth = `calc(100vw - ${sidebarWidth}px)`; + return { + x: window.innerWidth - sidebarWidth, + y: window.innerHeight, + }; + }, ...args, }); + // Debugging only + globalThis.photoswipe = this.photoswipe; + + // Monkey patch for focus trapping in sidebar + const _onFocusIn = this.photoswipe.keyboard._onFocusIn; + this.photoswipe.keyboard._onFocusIn = (e: FocusEvent) => { + if (e.target instanceof HTMLElement) { + if ( + e.target.closest("aside.app-sidebar") || + e.target.closest(".v-popper__popper") + ) { + return; + } + } + _onFocusIn.call(this.photoswipe.keyboard, e); + }; + + // Refresh sidebar on change + this.photoswipe.on("change", () => { + if (this.sidebarOpen) { + this.openSidebar(); + } + }); + // Make sure buttons are styled properly this.photoswipe.addFilter("uiElement", (element, data) => { // add button-vue class if button @@ -128,16 +191,18 @@ export default class Viewer extends Mixins(GlobalMixin) { }); // Put viewer over everything else - const contentElem = document.getElementById("content-vue"); const navElem = document.getElementById("app-navigation-vue"); const klass = "has-viewer"; this.photoswipe.on("beforeOpen", () => { - contentElem.classList.add(klass); + document.body.classList.add(klass); navElem.style.zIndex = "0"; }); this.photoswipe.on("openingAnimationStart", () => { this.fullyOpened = false; this.opened = true; + if (this.sidebarOpen) { + this.openSidebar(); + } }); this.photoswipe.on("openingAnimationEnd", () => { this.fullyOpened = true; @@ -145,9 +210,10 @@ export default class Viewer extends Mixins(GlobalMixin) { this.photoswipe.on("close", () => { this.fullyOpened = false; this.opened = false; + this.hideSidebar(); }); this.photoswipe.on("destroy", () => { - contentElem.classList.remove(klass); + document.body.classList.remove(klass); navElem.style.zIndex = ""; // reset everything @@ -398,6 +464,62 @@ export default class Viewer extends Mixins(GlobalMixin) { if (!photo) return; dav.downloadFilesByIds([photo]); } + + /** Open the sidebar */ + private async openSidebar(photo?: IPhoto) { + const fInfo = await dav.getFiles([photo || this.getCurrentPhoto()]); + globalThis.OCA?.Files?.Sidebar?.setFullScreenMode?.(true); + globalThis.OCA.Files.Sidebar.open(fInfo[0].filename); + } + + private async updateSizeWithoutAnim() { + const wasFullyOpened = this.fullyOpened; + this.fullyOpened = false; + this.photoswipe.updateSize(); + await new Promise((resolve) => setTimeout(resolve, 200)); + this.fullyOpened = wasFullyOpened; + } + + private handleAppSidebarOpen() { + if (this.show && this.photoswipe) { + const sidebar: HTMLElement = document.querySelector("aside.app-sidebar"); + if (sidebar) { + this.sidebarWidth = sidebar.offsetWidth - 2; + } + + this.sidebarOpen = true; + this.updateSizeWithoutAnim(); + } + } + + private handleAppSidebarClose() { + if (this.show && this.photoswipe && this.fullyOpened) { + this.sidebarOpen = false; + this.updateSizeWithoutAnim(); + } + } + + /** Hide the sidebar, without marking it as closed */ + private hideSidebar() { + globalThis.OCA?.Files?.Sidebar?.close(); + globalThis.OCA?.Files?.Sidebar?.setFullScreenMode?.(false); + } + + /** Close the sidebar */ + private closeSidebar() { + this.hideSidebar(); + this.sidebarOpen = false; + this.photoswipe.updateSize(); + } + + /** Toggle the sidebar visibility */ + private toggleSidebar() { + if (this.sidebarOpen) { + this.closeSidebar(); + } else { + this.openSidebar(); + } + } } @@ -405,8 +527,8 @@ export default class Viewer extends Mixins(GlobalMixin) { .outer { z-index: 3000; width: 100vw; - height: 30vh; - position: absolute; + height: 100vh; + position: fixed; top: 0; left: 0; overflow: hidden; @@ -415,7 +537,7 @@ export default class Viewer extends Mixins(GlobalMixin) { .top-bar { z-index: 100001; - position: fixed; + position: absolute; top: 8px; right: 50px; @@ -435,6 +557,11 @@ export default class Viewer extends Mixins(GlobalMixin) { transition: transform var(--pswp-transition-duration) ease !important; } +.inner, +.inner :deep .pswp { + width: inherit; +} + :deep .pswp { .pswp__button { color: white;