Cache days (abandon)

cache
Varun Patil 2022-10-16 11:49:29 -07:00
parent 90f197549c
commit 71a10b7971
4 changed files with 120 additions and 24 deletions

43
package-lock.json generated
View File

@ -13,6 +13,7 @@
"@nextcloud/paths": "^2.1.0",
"@nextcloud/vue": "^7.0.0",
"justified-layout": "^4.1.0",
"localforage": "^1.10.0",
"moment": "^2.29.4",
"path-posix": "^1.0.0",
"reflect-metadata": "^0.1.13",
@ -6780,6 +6781,11 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"node_modules/immutable": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
@ -7482,6 +7488,14 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -7528,6 +7542,14 @@
"node": ">=8.9.0"
}
},
"node_modules/localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"dependencies": {
"lie": "3.1.1"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -17243,6 +17265,11 @@
"dev": true,
"peer": true
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"immutable": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
@ -17749,6 +17776,14 @@
"type-check": "~0.4.0"
}
},
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"requires": {
"immediate": "~3.0.5"
}
},
"lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -17787,6 +17822,14 @@
"json5": "^2.1.2"
}
},
"localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"requires": {
"lie": "3.1.1"
}
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",

View File

@ -37,6 +37,7 @@
"@nextcloud/paths": "^2.1.0",
"@nextcloud/vue": "^7.0.0",
"justified-layout": "^4.1.0",
"localforage": "^1.10.0",
"moment": "^2.29.4",
"path-posix": "^1.0.0",
"reflect-metadata": "^0.1.13",

View File

@ -102,6 +102,7 @@ import moment from 'moment';
import * as dav from "../services/DavRequests";
import * as utils from "../services/Utils";
import localforage from "localforage";
import justifiedLayout from "justified-layout";
import axios from '@nextcloud/axios'
import Folder from "./frame/Folder.vue";
@ -150,8 +151,6 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
private squareMode = false;
/** Header rows for dayId key */
private heads: { [dayid: number]: IHeadRow } = {};
/** Original days response */
private days: IDay[] = [];
/** Computed row height */
private rowHeight = 100;
@ -215,12 +214,11 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
// Fit to window
this.handleResize();
// Add scroll listener
(this.$refs.recycler as any).$el.addEventListener('scroll', this.scrollPositionChange, false);
// Get data
await this.fetchDays();
// Timeline recycler init
(this.$refs.recycler as any).$el.addEventListener('scroll', this.scrollPositionChange, false);
this.scrollPositionChange();
}
/** Reset all state */
@ -230,7 +228,6 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
this.list = [];
this.numRows = 0;
this.heads = {};
this.days = [];
this.currentStart = 0;
this.currentEnd = 0;
this.scrollerManager.reset();
@ -488,9 +485,11 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
let params: any = {};
try {
this.loading++;
// this.loading++;
const startState = this.state;
const furl = generateUrl(this.appendQuery(url), params);
let data: IDay[] = [];
if (this.$route.name === 'thisday') {
data = await dav.getOnThisDayData();
@ -499,7 +498,12 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
} else if (this.$route.name === 'people' && !this.$route.params.name) {
data = await dav.getPeopleData();
} else {
data = (await axios.get<IDay[]>(generateUrl(this.appendQuery(url), params))).data;
const foraged = await localforage.getItem<IDay[]>(furl);
if (foraged) {
await this.processDays(foraged);
}
data = (await axios.get<IDay[]>(furl)).data;
await localforage.setItem(furl, data);
}
if (this.state !== startState) return;
@ -508,7 +512,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
console.error(err);
showError(err?.response?.data?.message || err.message);
} finally {
this.loading--;
// this.loading--;
}
}
@ -590,9 +594,12 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
}
// Store globally
this.days = data;
if (this.list.length) {
this.replaceRows(list);
} else {
this.list = list;
this.heads = heads;
}
// Iterate the preload map
// Now the inner detail objects are reactive
@ -604,6 +611,57 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
// Fix view height variable
await this.scrollerManager.reflow();
this.scrollPositionChange();
}
/** Replace current rows with this one gracefully */
private replaceRows(rows: IRow[]) {
// Two pointers: match heads
let pOld = 0;
let pNew = 0;
let insert = false;
let remove = false
while (pOld < this.list.length && pNew < rows.length) {
const oldRow = this.list[pOld];
const newRow = rows[pNew];
// Insert new rows
if (insert) {
this.list.splice(pOld, 0, newRow);
pOld++;
pNew++;
if (rows[pNew].type === IRowType.HEAD) {
insert = false;
}
continue;
}
// Remove old rows
if (remove) {
this.list.splice(pOld, 1);
if (this.list[pOld].type === IRowType.HEAD) {
remove = false;
}
continue;
}
// Find the next heads
if (newRow.type !== IRowType.HEAD) { pNew++; continue; }
if (oldRow.type !== IRowType.HEAD) { pOld++; continue; }
if (oldRow.dayId < newRow.dayId) {
// newRow is a new head, start insertion
insert = true;
this.heads[newRow.dayId] = newRow as IHeadRow;
} else if (oldRow.dayId > newRow.dayId) {
// Different head, remove old
remove = true;
} else {
// Same head, continue
pOld++;
pNew++;
}
}
}
/** Fetch image data for one dayId */
@ -620,7 +678,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
const data = res.data;
if (this.state !== startState) return;
const day = this.days.find(d => d.dayid === dayId);
const day = this.heads[dayId].day;
day.detail = data;
day.count = data.length;
this.processDay(day);

View File

@ -2,7 +2,7 @@
<div class="p-outer fill-block"
:class="{
'selected': (data.flag & c.FLAG_SELECTED),
'p-loading': !(data.flag & c.FLAG_LOADED),
'placeholder': (data.flag & c.FLAG_PLACEHOLDER),
'leaving': (data.flag & c.FLAG_LEAVING),
'exit-left': (data.flag & c.FLAG_EXIT_LEFT),
'enter-right': (data.flag & c.FLAG_ENTER_RIGHT),
@ -28,8 +28,7 @@
:src="src()"
:key="data.fileid"
@error="error"
@load="load" />
@error="error" />
</div>
</div>
</template>
@ -89,14 +88,9 @@ export default class Photo extends Mixins(GlobalMixin) {
return getPreviewUrl(this.data.fileid, this.data.etag, false, size)
}
/** Image loaded successfully */
load() {
this.data.flag |= this.c.FLAG_LOADED;
}
/** Error in loading image */
error(e: any) {
this.data.flag |= (this.c.FLAG_LOADED | this.c.FLAG_LOAD_FAIL);
this.data.flag |= this.c.FLAG_LOAD_FAIL;
}
/** Clear timers */
@ -284,7 +278,7 @@ div.img-outer {
transition: box-shadow 0.1s ease;
.selected > & { box-shadow: 0 0 4px 2px var(--color-primary); }
.p-outer.p-loading > & { display: none; }
.p-outer.placeholder > & { display: none; }
.p-outer.error & { object-fit: contain; }
}
}