Add hash routes for viewer

pull/175/head
Varun Patil 2022-11-06 17:08:46 -08:00
parent f30cc23cd5
commit a93621d662
3 changed files with 83 additions and 13 deletions

View File

@ -227,12 +227,45 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
mounted() { mounted() {
this.selectionManager = this.$refs.selectionManager; this.selectionManager = this.$refs.selectionManager;
this.scrollerManager = this.$refs.scrollerManager; this.scrollerManager = this.$refs.scrollerManager;
this.createState(); this.routeChange(this.$route);
} }
@Watch("$route") @Watch("$route")
async routeChange(from: any, to: any) { async routeChange(to: any, from?: any) {
await this.refresh(); if (from?.path !== to.path) {
await this.refresh();
}
// Check if hash has changed
const viewerIsOpen = (this.$refs.viewer as any).isOpen;
if (from?.hash !== to.hash && to.hash?.startsWith("#v") && !viewerIsOpen) {
// Open viewer
const parts = to.hash.split("/");
if (parts.length !== 3) return;
const dayid = parseInt(parts[1]);
const fileid = parseInt(parts[2]);
if (isNaN(dayid) || isNaN(fileid)) return;
const day = this.heads[dayid]?.day;
if (day && !day.detail) {
const state = this.state;
await this.fetchDay(dayid, true);
if (state !== this.state) return;
}
const photo = day?.detail?.find((p) => p.fileid === fileid);
if (!photo) return;
(this.$refs.viewer as any).open(photo, this.list);
} else if (
from?.hash?.startsWith("#v") &&
!to.hash?.startsWith("#v") &&
viewerIsOpen
) {
// Close viewer
(this.$refs.viewer as any).close();
}
} }
beforeDestroy() { beforeDestroy() {
@ -784,7 +817,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
} }
/** Fetch image data for one dayId */ /** Fetch image data for one dayId */
async fetchDay(dayId: number) { async fetchDay(dayId: number, now = false) {
const head = this.heads[dayId]; const head = this.heads[dayId];
if (!head) return; if (!head) return;
@ -804,7 +837,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
this.fetchDayQueue.push(dayId); this.fetchDayQueue.push(dayId);
// Only single queries allowed for month vie // Only single queries allowed for month vie
if (this.isMonthView()) { if (now || this.isMonthView()) {
return this.fetchDayExpire(); return this.fetchDayExpire();
} }
@ -1146,7 +1179,10 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
// selection mode // selection mode
this.selectionManager.selectPhoto(photo); this.selectionManager.selectPhoto(photo);
} else { } else {
(<any>this.$refs.viewer).open(photo, this.list); this.$router.push({
...this.$route,
hash: utils.getViewerHash(photo),
});
} }
} }

View File

@ -6,7 +6,7 @@
:style="{ width: outerWidth }" :style="{ width: outerWidth }"
> >
<div class="inner" ref="inner"> <div class="inner" ref="inner">
<div class="top-bar" v-if="photoswipe" :class="{ opened }"> <div class="top-bar" v-if="photoswipe" :class="{ showControls }">
<NcActions :inline="3" container=".memories_viewer .pswp"> <NcActions :inline="3" container=".memories_viewer .pswp">
<NcActionButton <NcActionButton
:aria-label="t('memories', 'Delete')" :aria-label="t('memories', 'Delete')"
@ -108,8 +108,10 @@ export default class Viewer extends Mixins(GlobalMixin) {
@Emit("fetchDay") fetchDay(dayId: number) {} @Emit("fetchDay") fetchDay(dayId: number) {}
@Emit("updateLoading") updateLoading(delta: number) {} @Emit("updateLoading") updateLoading(delta: number) {}
public isOpen = false;
private show = false; private show = false;
private opened = false; private showControls = false;
private fullyOpened = false; private fullyOpened = false;
private sidebarOpen = false; private sidebarOpen = false;
private sidebarWidth = 400; private sidebarWidth = 400;
@ -216,8 +218,9 @@ export default class Viewer extends Mixins(GlobalMixin) {
if (navElem) navElem.style.zIndex = "0"; if (navElem) navElem.style.zIndex = "0";
}); });
this.photoswipe.on("openingAnimationStart", () => { this.photoswipe.on("openingAnimationStart", () => {
this.isOpen = true;
this.fullyOpened = false; this.fullyOpened = false;
this.opened = true; this.showControls = true;
if (this.sidebarOpen) { if (this.sidebarOpen) {
this.openSidebar(); this.openSidebar();
} }
@ -226,9 +229,11 @@ export default class Viewer extends Mixins(GlobalMixin) {
this.fullyOpened = true; this.fullyOpened = true;
}); });
this.photoswipe.on("close", () => { this.photoswipe.on("close", () => {
this.isOpen = false;
this.fullyOpened = false; this.fullyOpened = false;
this.opened = false; this.showControls = false;
this.hideSidebar(); this.hideSidebar();
this.setRouteHash(undefined);
}); });
this.photoswipe.on("destroy", () => { this.photoswipe.on("destroy", () => {
document.body.classList.remove(klass); document.body.classList.remove(klass);
@ -236,8 +241,9 @@ export default class Viewer extends Mixins(GlobalMixin) {
// reset everything // reset everything
this.show = false; this.show = false;
this.opened = false; this.isOpen = false;
this.fullyOpened = false; this.fullyOpened = false;
this.showControls = false;
this.photoswipe = null; this.photoswipe = null;
this.list = []; this.list = [];
this.days.clear(); this.days.clear();
@ -248,7 +254,12 @@ export default class Viewer extends Mixins(GlobalMixin) {
// toggle-controls // toggle-controls
this.photoswipe.on("tapAction", () => { this.photoswipe.on("tapAction", () => {
this.opened = !this.opened; this.showControls = !this.showControls;
});
// Update vue route for deep linking
this.photoswipe.on("slideActivate", (e) => {
this.setRouteHash(e.slide?.data?.photo);
}); });
// Video support // Video support
@ -442,6 +453,11 @@ export default class Viewer extends Mixins(GlobalMixin) {
this.photoswipe.init(); this.photoswipe.init();
} }
/** Close the viewer */
public close() {
this.photoswipe?.close();
}
/** Open with a static list of photos */ /** Open with a static list of photos */
public async openStatic(photo: IPhoto, list: IPhoto[]) { public async openStatic(photo: IPhoto, list: IPhoto[]) {
this.list = list; this.list = list;
@ -492,6 +508,17 @@ export default class Viewer extends Mixins(GlobalMixin) {
return elem; return elem;
} }
/** Set the route hash to the given photo */
private setRouteHash(photo: IPhoto | undefined) {
const hash = photo ? utils.getViewerHash(photo) : "";
if (hash !== this.$route.hash) {
this.$router.replace({
...this.$route,
hash,
});
}
}
/** Delete this photo and refresh */ /** Delete this photo and refresh */
private async deleteCurrent() { private async deleteCurrent() {
const idx = this.photoswipe.currIndex - this.globalAnchor; const idx = this.photoswipe.currIndex - this.globalAnchor;
@ -641,7 +668,7 @@ export default class Viewer extends Mixins(GlobalMixin) {
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
opacity: 0; opacity: 0;
&.opened { &.showControls {
opacity: 1; opacity: 1;
} }
} }

View File

@ -216,6 +216,13 @@ export function getFolderRoutePath(basePath: string) {
return path; return path;
} }
/**
* Get route hash for viewer for photo
*/
export function getViewerHash(photo: IPhoto) {
return `#v/${photo.dayid}/${photo.fileid}`;
}
/** Set a timer that renews if existing */ /** Set a timer that renews if existing */
export function setRenewingTimeout( export function setRenewingTimeout(
ctx: any, ctx: any,