From 7c07e42b55e9fe21f250574d74eafe55a1ce1dd7 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Thu, 2 Jul 2020 11:39:19 +0200 Subject: [PATCH] Frontend: Improve photo viewer loading #309 #370 Signed-off-by: Michael Mayer --- frontend/src/pages/album/photos.vue | 89 ++++++++++++++++---------- frontend/src/pages/photos.vue | 97 ++++++++++++++++++----------- frontend/src/share/photos.vue | 89 ++++++++++++++++---------- 3 files changed, 169 insertions(+), 106 deletions(-) diff --git a/frontend/src/pages/album/photos.vue b/frontend/src/pages/album/photos.vue index 3ef301c77..50d3891a4 100644 --- a/frontend/src/pages/album/photos.vue +++ b/frontend/src/pages/album/photos.vue @@ -88,6 +88,7 @@ subscriptions: [], listen: false, dirty: false, + complete: false, model: new Album(), uid: uid, results: [], @@ -164,9 +165,13 @@ this.$viewer.show(Thumb.fromFiles([selected]), 0) } else { this.viewerResults().then((results) => { - const thumbs = Thumb.fromPhotos(results); - const thumbsIndex = thumbs.findIndex(t => t.uid === selected.UID); - this.$viewer.show(thumbs, thumbsIndex ? thumbsIndex : 0); + const thumbsIndex = results.findIndex(result => result.UID === selected.UID); + + if(thumbsIndex < 0) { + this.$viewer.show(Thumb.fromPhotos(this.results), index); + } else { + this.$viewer.show(Thumb.fromPhotos(results), thumbsIndex); + } }); } @@ -177,11 +182,11 @@ return Promise.reject(); } - if (this.scrollDisabled) { + if (this.complete) { return Promise.resolve(this.results); } - if (this.viewer.results.length > 0) { + if (this.viewer.results.length >= this.results.length) { return Promise.resolve(this.viewer.results); } @@ -240,14 +245,10 @@ Photo.search(params).then(response => { this.results = Photo.mergeResponse(this.results, response); + this.complete = (response.count < count); + this.scrollDisabled = this.complete; - if(offset === 0) { - this.viewer.results = []; - } - - this.scrollDisabled = (response.count < count); - - if (this.scrollDisabled) { + if (this.complete) { this.offset = offset; if (this.results.length > 1) { @@ -256,6 +257,7 @@ } else if (this.results.length >= Photo.limit()) { this.offset = offset; this.scrollDisabled = true; + this.complete = true; this.$notify.warn(this.$gettext("Can't load more, limit reached")); } else { this.offset = offset + count; @@ -267,6 +269,10 @@ this.dirty = false; this.loading = false; this.listen = true; + + if(offset === 0) { + this.viewerResults(); + } }); }, updateQuery() { @@ -306,11 +312,16 @@ return params; }, refresh() { - if (this.loading) return; + if (this.loading) { + return; + } + this.loading = true; this.page = 0; this.dirty = true; + this.complete = false; this.scrollDisabled = false; + this.loadMore(); }, search() { @@ -328,18 +339,17 @@ this.page = 0; this.loading = true; this.listen = false; + this.complete = false; const params = this.searchParams(); Photo.search(params).then(response => { this.offset = this.pageSize; - this.results = response.models; - this.viewer.results = []; + this.complete = (response.count < this.pageSize); + this.scrollDisabled = this.complete; - this.scrollDisabled = (response.count < this.pageSize); - - if (this.scrollDisabled) { + if (this.complete) { if (!this.results.length) { this.$notify.warn(this.$gettext("No entries found")); } else if (this.results.length === 1) { @@ -356,6 +366,8 @@ this.dirty = false; this.loading = false; this.listen = true; + + this.viewerResults(); }); }, findAlbum() { @@ -388,6 +400,7 @@ window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}` this.dirty = true; + this.complete = false; this.scrollDisabled = false; if (this.filter.order !== this.model.Order) { @@ -401,6 +414,24 @@ } } }, + updateResult(results, values) { + const model = results.find((m) => m.UID === values.UID); + + if (model) { + for (let key in values) { + if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { + model[key] = values[key]; + } + } + } + }, + removeResult(results, uid) { + const index = results.findIndex((m) => m.UID === uid); + + if (index >= 0) { + results.splice(index, 1); + } + }, onUpdate(ev, data) { if (!this.listen) return; @@ -408,43 +439,33 @@ return } - this.viewer.results = []; - const type = ev.split('.')[1]; switch (type) { case 'updated': for (let i = 0; i < data.entities.length; i++) { const values = data.entities[i]; - const model = this.results.find((m) => m.UID === values.UID); - - if (model) { - for (let key in values) { - if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { - model[key] = values[key]; - } - } - } + this.updateResult(this.results, values); + this.updateResult(this.viewer.results, values); } break; case 'restored': this.dirty = true; this.scrollDisabled = false; + this.complete = false; this.loadMore(); break; case 'archived': this.dirty = true; + this.complete = false; for (let i = 0; i < data.entities.length; i++) { const uid = data.entities[i]; - const index = this.results.findIndex((m) => m.UID === uid); - - if (index >= 0) { - this.results.splice(index, 1); - } + this.removeResult(this.results, uid); + this.removeResult(this.viewer.results, uid); this.$clipboard.removeId(uid); } diff --git a/frontend/src/pages/photos.vue b/frontend/src/pages/photos.vue index eb67baa46..6e8706fff 100644 --- a/frontend/src/pages/photos.vue +++ b/frontend/src/pages/photos.vue @@ -105,6 +105,7 @@ subscriptions: [], listen: false, dirty: false, + complete: false, results: [], scrollDisabled: true, pageSize: 60, @@ -204,9 +205,13 @@ this.$viewer.show(Thumb.fromFiles([selected]), 0) } else { this.viewerResults().then((results) => { - const thumbs = Thumb.fromPhotos(results); - const thumbsIndex = thumbs.findIndex(t => t.uid === selected.UID); - this.$viewer.show(thumbs, thumbsIndex ? thumbsIndex : 0); + const thumbsIndex = results.findIndex(result => result.UID === selected.UID); + + if(thumbsIndex < 0) { + this.$viewer.show(Thumb.fromPhotos(this.results), index); + } else { + this.$viewer.show(Thumb.fromPhotos(results), thumbsIndex); + } }); } }, @@ -215,17 +220,17 @@ return Promise.reject(); } - if (this.scrollDisabled) { + if (this.complete) { return Promise.resolve(this.results); } - if (this.viewer.results.length > 0) { + if (this.viewer.results.length > (this.results.length + this.pageSize)) { return Promise.resolve(this.viewer.results); } this.viewer.loading = true; - const count = Photo.limit(); + const count = this.pageSize*(this.page + 6); const offset = 0; const params = { @@ -275,14 +280,10 @@ Photo.search(params).then(response => { this.results = Photo.mergeResponse(this.results, response); + this.complete = (response.count < count); + this.scrollDisabled = this.complete; - if(offset === 0) { - this.viewer.results = []; - } - - this.scrollDisabled = (response.count < count); - - if (this.scrollDisabled) { + if (this.complete) { this.offset = offset; if (this.results.length > 1) { @@ -290,6 +291,7 @@ } } else if (this.results.length >= Photo.limit()) { this.offset = offset; + this.complete = true; this.scrollDisabled = true; this.$notify.warn(this.$gettext("Can't load more, limit reached")); } else { @@ -302,6 +304,10 @@ this.dirty = false; this.loading = false; this.listen = true; + + if(offset === 0) { + this.viewerResults(); + } }); }, updateQuery() { @@ -339,11 +345,16 @@ return params; }, refresh() { - if (this.loading) return; + if (this.loading) { + return; + } + this.loading = true; this.page = 0; this.dirty = true; + this.complete = false; this.scrollDisabled = false; + this.loadMore(); }, search() { @@ -361,18 +372,17 @@ this.page = 0; this.loading = true; this.listen = false; + this.complete = false; const params = this.searchParams(); Photo.search(params).then(response => { this.offset = this.pageSize; - this.results = response.models; - this.viewer.results = []; + this.complete = (response.count < this.pageSize); + this.scrollDisabled = this.complete; - this.scrollDisabled = (response.count < this.pageSize); - - if (this.scrollDisabled) { + if (this.complete) { if (!this.results.length) { this.$notify.warn(this.$gettext("No photos found")); } else if (this.results.length === 1) { @@ -389,6 +399,8 @@ this.dirty = false; this.loading = false; this.listen = true; + + this.viewerResults(); }); }, onImportCompleted() { @@ -396,6 +408,24 @@ this.loadMore(); }, + updateResult(results, values) { + const model = results.find((m) => m.UID === values.UID); + + if (model) { + for (let key in values) { + if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { + model[key] = values[key]; + } + } + } + }, + removeResult(results, uid) { + const index = results.findIndex((m) => m.UID === uid); + + if (index >= 0) { + results.splice(index, 1); + } + }, onUpdate(ev, data) { if (!this.listen) return; @@ -403,52 +433,42 @@ return } - this.viewer.results = []; - const type = ev.split('.')[1]; switch (type) { case 'updated': for (let i = 0; i < data.entities.length; i++) { const values = data.entities[i]; - const model = this.results.find((m) => m.UID === values.UID); - if (model) { - for (let key in values) { - if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { - model[key] = values[key]; - } - } - } + this.updateResult(this.results, values); + this.updateResult(this.viewer.results, values); } break; case 'restored': this.dirty = true; + this.complete = false; if (this.context !== "archive") break; for (let i = 0; i < data.entities.length; i++) { const uid = data.entities[i]; - const index = this.results.findIndex((m) => m.UID === uid); - if (index >= 0) { - this.results.splice(index, 1); - } + + this.removeResult(this.results, uid); + this.removeResult(this.viewer.results, uid); } break; case 'archived': this.dirty = true; + this.complete = false; if (this.context === "archive") break; for (let i = 0; i < data.entities.length; i++) { const uid = data.entities[i]; - const index = this.results.findIndex((m) => m.UID === uid); - - if (index >= 0) { - this.results.splice(index, 1); - } + this.removeResult(this.results, uid); + this.removeResult(this.viewer.results, uid); this.$clipboard.removeId(uid); } @@ -456,6 +476,7 @@ case 'created': this.dirty = true; this.scrollDisabled = false; + this.complete = false; break; default: diff --git a/frontend/src/share/photos.vue b/frontend/src/share/photos.vue index 66520ffa0..1b45560d4 100644 --- a/frontend/src/share/photos.vue +++ b/frontend/src/share/photos.vue @@ -126,6 +126,7 @@ subscriptions: [], listen: false, dirty: false, + complete: false, model: new Album(), uid: uid, results: [], @@ -207,9 +208,13 @@ this.$viewer.show(Thumb.fromFiles([selected]), 0) } else { this.viewerResults().then((results) => { - const thumbs = Thumb.fromPhotos(results); - const thumbsIndex = thumbs.findIndex(t => t.uid === selected.UID); - this.$viewer.show(thumbs, thumbsIndex ? thumbsIndex : 0); + const thumbsIndex = results.findIndex(result => result.UID === selected.UID); + + if(thumbsIndex < 0) { + this.$viewer.show(Thumb.fromPhotos(this.results), index); + } else { + this.$viewer.show(Thumb.fromPhotos(results), thumbsIndex); + } }); } @@ -220,11 +225,11 @@ return Promise.reject(); } - if(this.scrollDisabled) { + if (this.complete) { return Promise.resolve(this.results); } - if (this.viewer.results.length > 0) { + if (this.viewer.results.length >= this.results.length) { return Promise.resolve(this.viewer.results); } @@ -283,14 +288,10 @@ Photo.search(params).then(response => { this.results = Photo.mergeResponse(this.results, response); + this.complete = (response.count < count); + this.scrollDisabled = this.complete; - if(offset === 0) { - this.viewer.results = []; - } - - this.scrollDisabled = (response.count < count); - - if (this.scrollDisabled) { + if (this.complete) { this.offset = offset; if (this.results.length > 1) { @@ -299,6 +300,7 @@ } else if (this.results.length >= Photo.limit()) { this.offset = offset; this.scrollDisabled = true; + this.complete = true; this.$notify.warn(this.$gettext("Can't load more, limit reached")); } else { this.offset = offset + count; @@ -310,6 +312,10 @@ this.dirty = false; this.loading = false; this.listen = true; + + if(offset === 0) { + this.viewerResults(); + } }); }, updateQuery() { @@ -349,11 +355,16 @@ return params; }, refresh() { - if (this.loading) return; + if (this.loading) { + return; + } + this.loading = true; this.page = 0; this.dirty = true; + this.complete = false; this.scrollDisabled = false; + this.loadMore(); }, search() { @@ -371,18 +382,17 @@ this.page = 0; this.loading = true; this.listen = false; + this.complete = false; const params = this.searchParams(); Photo.search(params).then(response => { this.offset = this.pageSize; - this.results = response.models; - this.viewer.results = []; + this.complete = (response.count < this.pageSize); + this.scrollDisabled = this.complete; - this.scrollDisabled = (response.count < this.pageSize); - - if (this.scrollDisabled) { + if (this.complete) { if (!this.results.length) { this.$notify.warn(this.$gettext("No entries found")); } else if (this.results.length === 1) { @@ -399,6 +409,8 @@ this.dirty = false; this.loading = false; this.listen = true; + + this.viewerResults(); }); }, findAlbum() { @@ -431,6 +443,7 @@ window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}` this.dirty = true; + this.complete = false; this.scrollDisabled = false; if (this.filter.order !== this.model.Order) { @@ -444,6 +457,24 @@ } } }, + updateResult(results, values) { + const model = results.find((m) => m.UID === values.UID); + + if (model) { + for (let key in values) { + if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { + model[key] = values[key]; + } + } + } + }, + removeResult(results, uid) { + const index = results.findIndex((m) => m.UID === uid); + + if (index >= 0) { + results.splice(index, 1); + } + }, onUpdate(ev, data) { if (!this.listen) return; @@ -451,43 +482,33 @@ return } - this.viewer.results = []; - const type = ev.split('.')[1]; switch (type) { case 'updated': for (let i = 0; i < data.entities.length; i++) { const values = data.entities[i]; - const model = this.results.find((m) => m.UID === values.UID); - - if (model) { - for (let key in values) { - if (values.hasOwnProperty(key) && values[key] != null && typeof values[key] !== "object") { - model[key] = values[key]; - } - } - } + this.updateResult(this.results, values); + this.updateResult(this.viewer.results, values); } break; case 'restored': this.dirty = true; this.scrollDisabled = false; + this.complete = false; this.loadMore(); break; case 'archived': this.dirty = true; + this.complete = false; for (let i = 0; i < data.entities.length; i++) { const uid = data.entities[i]; - const index = this.results.findIndex((m) => m.UID === uid); - - if (index >= 0) { - this.results.splice(index, 1); - } + this.removeResult(this.results, uid); + this.removeResult(this.viewer.results, uid); this.$clipboard.removeId(uid); }