Frontend: Fixed infinite scroll and reload
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
f57c6688a5
commit
491751f4fc
5 changed files with 182 additions and 47 deletions
|
@ -3,7 +3,7 @@
|
||||||
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
|
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
|
||||||
|
|
||||||
<p-album-toolbar :album="model" :settings="settings" :filter="filter" :filter-change="updateQuery"
|
<p-album-toolbar :album="model" :settings="settings" :filter="filter" :filter-change="updateQuery"
|
||||||
:refresh="refresh"></p-album-toolbar>
|
:refresh="refresh"></p-album-toolbar>
|
||||||
|
|
||||||
<v-container fluid class="pa-4" v-if="loading">
|
<v-container fluid class="pa-4" v-if="loading">
|
||||||
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
|
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
|
||||||
|
@ -43,6 +43,7 @@
|
||||||
<script>
|
<script>
|
||||||
import Photo from "model/photo";
|
import Photo from "model/photo";
|
||||||
import Album from "model/album";
|
import Album from "model/album";
|
||||||
|
import Event from "pubsub-js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'p-page-album-photos',
|
name: 'p-page-album-photos',
|
||||||
|
@ -77,12 +78,16 @@
|
||||||
const settings = {view: view};
|
const settings = {view: view};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
model: new Album({AlbumName:""}),
|
subscriptions: [],
|
||||||
|
listen: false,
|
||||||
|
dirty: false,
|
||||||
|
model: new Album(),
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
results: [],
|
results: [],
|
||||||
scrollDisabled: true,
|
scrollDisabled: true,
|
||||||
pageSize: 60,
|
pageSize: 60,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
page: 0,
|
||||||
selection: this.$clipboard.selection,
|
selection: this.$clipboard.selection,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
|
@ -128,25 +133,44 @@
|
||||||
if (this.scrollDisabled) return;
|
if (this.scrollDisabled) return;
|
||||||
|
|
||||||
this.scrollDisabled = true;
|
this.scrollDisabled = true;
|
||||||
|
this.listen = false;
|
||||||
|
|
||||||
this.offset += this.pageSize;
|
const count = this.dirty ? (this.page + 2) * this.pageSize : this.pageSize;
|
||||||
|
const offset = this.dirty ? 0 : this.offset;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
count: this.pageSize,
|
count: count,
|
||||||
offset: this.offset,
|
offset: offset,
|
||||||
album: this.uuid,
|
album: this.uuid,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(params, this.lastFilter);
|
Object.assign(params, this.lastFilter);
|
||||||
|
|
||||||
Photo.search(params).then(response => {
|
if (this.staticFilter) {
|
||||||
this.results = this.results.concat(response.models);
|
Object.assign(params, this.staticFilter);
|
||||||
|
}
|
||||||
|
|
||||||
this.scrollDisabled = (response.models.length < this.pageSize);
|
Photo.search(params).then(response => {
|
||||||
|
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
||||||
|
|
||||||
|
this.scrollDisabled = (response.models.length < count);
|
||||||
|
|
||||||
if (this.scrollDisabled) {
|
if (this.scrollDisabled) {
|
||||||
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' photos loaded'));
|
this.offset = offset;
|
||||||
|
|
||||||
|
if(this.results.length > 1) {
|
||||||
|
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' photos loaded'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.offset = offset + count;
|
||||||
|
this.page++;
|
||||||
}
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.scrollDisabled = false;
|
||||||
|
}).finally(() => {
|
||||||
|
this.dirty = false;
|
||||||
|
this.loading = false;
|
||||||
|
this.listen = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateQuery() {
|
updateQuery() {
|
||||||
|
@ -184,12 +208,12 @@
|
||||||
return params;
|
return params;
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.lastFilter = {};
|
if(this.loading) return;
|
||||||
const pageSize = this.pageSize;
|
this.loading = true;
|
||||||
this.pageSize = this.offset + pageSize;
|
this.page = 0;
|
||||||
this.search();
|
this.dirty = true;
|
||||||
this.offset = this.pageSize;
|
this.scrollDisabled = false;
|
||||||
this.pageSize = pageSize;
|
this.loadMore();
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
this.scrollDisabled = true;
|
this.scrollDisabled = true;
|
||||||
|
@ -203,12 +227,15 @@
|
||||||
Object.assign(this.lastFilter, this.filter);
|
Object.assign(this.lastFilter, this.filter);
|
||||||
|
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
|
this.page = 0;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.listen = false;
|
||||||
|
|
||||||
const params = this.searchParams();
|
const params = this.searchParams();
|
||||||
|
|
||||||
Photo.search(params).then(response => {
|
Photo.search(params).then(response => {
|
||||||
this.loading = false;
|
this.offset = this.pageSize;
|
||||||
|
|
||||||
this.results = response.models;
|
this.results = response.models;
|
||||||
|
|
||||||
this.scrollDisabled = (response.models.length < this.pageSize);
|
this.scrollDisabled = (response.models.length < this.pageSize);
|
||||||
|
@ -226,7 +253,11 @@
|
||||||
|
|
||||||
this.$nextTick(() => this.$emit("scrollRefresh"));
|
this.$nextTick(() => this.$emit("scrollRefresh"));
|
||||||
}
|
}
|
||||||
}).catch(() => this.loading = false);
|
}).finally(() => {
|
||||||
|
this.dirty = false;
|
||||||
|
this.loading = false;
|
||||||
|
this.listen = true;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
findAlbum() {
|
findAlbum() {
|
||||||
this.model.find(this.uuid).then(m => {
|
this.model.find(this.uuid).then(m => {
|
||||||
|
@ -234,10 +265,87 @@
|
||||||
window.document.title = `PhotoPrism: ${this.model.AlbumName}`;
|
window.document.title = `PhotoPrism: ${this.model.AlbumName}`;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
onAlbumsUpdated(ev, data) {
|
||||||
|
if (!this.listen) return;
|
||||||
|
|
||||||
|
if (!data || !data.entities) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < data.entities.length; i++) {
|
||||||
|
const values = data.entities[i];
|
||||||
|
|
||||||
|
if (this.model.AlbumUUID === data.entities[i].AlbumUUID) {
|
||||||
|
for (let key in values) {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
this.model[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dirty = true;
|
||||||
|
this.scrollDisabled = false;
|
||||||
|
|
||||||
|
this.loadMore();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onUpdate(ev, data) {
|
||||||
|
if (!this.listen) return;
|
||||||
|
|
||||||
|
if (!data || !data.entities) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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.ID === values.ID);
|
||||||
|
|
||||||
|
for (let key in values) {
|
||||||
|
if (values.hasOwnProperty(key)) {
|
||||||
|
model[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'restored':
|
||||||
|
this.dirty = true;
|
||||||
|
this.scrollDisabled = false;
|
||||||
|
|
||||||
|
this.loadMore();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'archived':
|
||||||
|
this.dirty = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < data.entities.length; i++) {
|
||||||
|
const uuid = data.entities[i];
|
||||||
|
const index = this.results.findIndex((m) => m.PhotoUUID === uuid);
|
||||||
|
if (index >= 0) {
|
||||||
|
this.results.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.findAlbum();
|
this.findAlbum();
|
||||||
this.search();
|
this.search();
|
||||||
|
|
||||||
|
this.subscriptions.push(Event.subscribe("albums.updated", (ev, data) => this.onAlbumsUpdated(ev, data)));
|
||||||
|
this.subscriptions.push(Event.subscribe("photos", (ev, data) => this.onUpdate(ev, data)));
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
for (let i = 0; i < this.subscriptions.length; i++) {
|
||||||
|
Event.unsubscribe(this.subscriptions[i]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -201,16 +201,24 @@
|
||||||
|
|
||||||
Object.assign(params, this.lastFilter);
|
Object.assign(params, this.lastFilter);
|
||||||
|
|
||||||
Album.search(params).then(response => {
|
if (this.staticFilter) {
|
||||||
this.page++;
|
Object.assign(params, this.staticFilter);
|
||||||
this.offset += this.pageSize;
|
}
|
||||||
|
|
||||||
|
Album.search(params).then(response => {
|
||||||
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
||||||
|
|
||||||
this.scrollDisabled = (response.models.length < count);
|
this.scrollDisabled = (response.models.length < count);
|
||||||
|
|
||||||
if (this.scrollDisabled) {
|
if (this.scrollDisabled) {
|
||||||
this.$notify.info(this.$gettext("All ") + this.results.length + this.$gettext(" albums loaded"));
|
this.offset = offset;
|
||||||
|
|
||||||
|
if(this.results.length > 1) {
|
||||||
|
this.$notify.info(this.$gettext("All ") + this.results.length + this.$gettext(" albums loaded"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.offset = offset + count;
|
||||||
|
this.page++;
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.scrollDisabled = false;
|
this.scrollDisabled = false;
|
||||||
|
@ -298,12 +306,12 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.lastFilter = {};
|
if(this.loading) return;
|
||||||
const pageSize = this.pageSize;
|
this.loading = true;
|
||||||
this.pageSize = this.offset + pageSize;
|
this.page = 0;
|
||||||
this.search();
|
this.dirty = true;
|
||||||
this.offset = this.pageSize;
|
this.scrollDisabled = false;
|
||||||
this.pageSize = pageSize;
|
this.loadMore();
|
||||||
},
|
},
|
||||||
create() {
|
create() {
|
||||||
let name = DateTime.local().toFormat("LLLL yyyy");
|
let name = DateTime.local().toFormat("LLLL yyyy");
|
||||||
|
|
|
@ -230,16 +230,23 @@
|
||||||
|
|
||||||
Object.assign(params, this.lastFilter);
|
Object.assign(params, this.lastFilter);
|
||||||
|
|
||||||
Label.search(params).then(response => {
|
if (this.staticFilter) {
|
||||||
this.page++;
|
Object.assign(params, this.staticFilter);
|
||||||
this.offset += this.pageSize;
|
}
|
||||||
|
|
||||||
|
Label.search(params).then(response => {
|
||||||
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
||||||
|
|
||||||
this.scrollDisabled = (response.models.length < count);
|
this.scrollDisabled = (response.models.length < count);
|
||||||
|
|
||||||
if (this.scrollDisabled) {
|
if (this.scrollDisabled) {
|
||||||
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' labels loaded'));
|
this.offset = offset;
|
||||||
|
if(this.results.length > 1) {
|
||||||
|
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' labels loaded'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.offset = offset + count;
|
||||||
|
this.page++;
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.scrollDisabled = false;
|
this.scrollDisabled = false;
|
||||||
|
@ -283,12 +290,12 @@
|
||||||
return params;
|
return params;
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.lastFilter = {};
|
if(this.loading) return;
|
||||||
const pageSize = this.pageSize;
|
this.loading = true;
|
||||||
this.pageSize = this.offset + pageSize;
|
this.page = 0;
|
||||||
this.search();
|
this.dirty = true;
|
||||||
this.offset = this.pageSize;
|
this.scrollDisabled = false;
|
||||||
this.pageSize = pageSize;
|
this.loadMore();
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
this.scrollDisabled = true;
|
this.scrollDisabled = true;
|
||||||
|
|
|
@ -157,16 +157,24 @@
|
||||||
|
|
||||||
Object.assign(params, this.lastFilter);
|
Object.assign(params, this.lastFilter);
|
||||||
|
|
||||||
Photo.search(params).then(response => {
|
if (this.staticFilter) {
|
||||||
this.page++;
|
Object.assign(params, this.staticFilter);
|
||||||
this.offset += this.pageSize;
|
}
|
||||||
|
|
||||||
|
Photo.search(params).then(response => {
|
||||||
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
this.results = this.dirty ? response.models : this.results.concat(response.models);
|
||||||
|
|
||||||
this.scrollDisabled = (response.models.length < count);
|
this.scrollDisabled = (response.models.length < count);
|
||||||
|
|
||||||
if (this.scrollDisabled) {
|
if (this.scrollDisabled) {
|
||||||
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' photos loaded'));
|
this.offset = offset;
|
||||||
|
|
||||||
|
if(this.results.length > 1) {
|
||||||
|
this.$notify.info(this.$gettext('All ') + this.results.length + this.$gettext(' photos loaded'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.offset = offset + count;
|
||||||
|
this.page++;
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.scrollDisabled = false;
|
this.scrollDisabled = false;
|
||||||
|
@ -210,12 +218,12 @@
|
||||||
return params;
|
return params;
|
||||||
},
|
},
|
||||||
refresh() {
|
refresh() {
|
||||||
this.lastFilter = {};
|
if(this.loading) return;
|
||||||
const pageSize = this.pageSize;
|
this.loading = true;
|
||||||
this.pageSize = this.offset + pageSize;
|
this.page = 0;
|
||||||
this.search();
|
this.dirty = true;
|
||||||
this.offset = this.pageSize;
|
this.scrollDisabled = false;
|
||||||
this.pageSize = pageSize;
|
this.loadMore();
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
this.scrollDisabled = true;
|
this.scrollDisabled = true;
|
||||||
|
|
|
@ -281,6 +281,8 @@ func AddPhotosToAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||||
event.Success(fmt.Sprintf("%d photos added to %s", len(added), a.AlbumName))
|
event.Success(fmt.Sprintf("%d photos added to %s", len(added), a.AlbumName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PublishAlbumEvent(EntityUpdated, a.AlbumUUID, c, q)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "photos added to album", "album": a, "added": added})
|
c.JSON(http.StatusOK, gin.H{"message": "photos added to album", "album": a, "added": added})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -320,6 +322,8 @@ func RemovePhotosFromAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||||
|
|
||||||
event.Success(fmt.Sprintf("photos removed from %s", a.AlbumName))
|
event.Success(fmt.Sprintf("photos removed from %s", a.AlbumName))
|
||||||
|
|
||||||
|
PublishAlbumEvent(EntityUpdated, a.AlbumUUID, c, q)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "photos removed from album", "album": a, "photos": f.Photos})
|
c.JSON(http.StatusOK, gin.H{"message": "photos removed from album", "album": a, "photos": f.Photos})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue