lazy loading of note list

This commit is contained in:
zadam 2020-12-27 22:19:27 +01:00
parent 95760f1d28
commit 1d64129572
12 changed files with 125 additions and 124 deletions

108
package-lock.json generated
View File

@ -54,6 +54,12 @@
}
}
},
"@discoveryjs/json-ext": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz",
"integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==",
"dev": true
},
"@electron/get": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.7.2.tgz",
@ -898,18 +904,18 @@
}
},
"@webpack-cli/info": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.1.0.tgz",
"integrity": "sha512-uNWSdaYHc+f3LdIZNwhdhkjjLDDl3jP2+XBqAq9H8DjrJUvlOKdP8TNruy1yEaDfgpAIgbSAN7pye4FEHg9tYQ==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.0.tgz",
"integrity": "sha512-+wA8lBKopgKmN76BSGJVJby5ZXDlsrO6p/nm7fUBsHznRNWB/ozotJP7Yfcz8JPfqeG2LxwYlTH2u6D9a/0XAw==",
"dev": true,
"requires": {
"envinfo": "^7.7.3"
}
},
"@webpack-cli/serve": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.1.0.tgz",
"integrity": "sha512-7RfnMXCpJ/NThrhq4gYQYILB18xWyoQcBey81oIyVbmgbc6m5ZHHyFK+DyH7pLHJf0p14MxL4mTsoPAgBSTpIg==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.2.0.tgz",
"integrity": "sha512-jI3P7jMp/AXDSPkM+ClwRcJZbxnlvNC8bVZBmyRr4scMMZ4p5WQcXkw3Q+Hc7RQekomJlBMN+UQGliT4hhG8Vw==",
"dev": true
},
"@xtuc/ieee754": {
@ -1145,12 +1151,6 @@
"sprintf-js": "~1.0.2"
}
},
"array-back": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz",
"integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==",
"dev": true
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@ -2009,18 +2009,6 @@
"delayed-stream": "~1.0.0"
}
},
"command-line-usage": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.1.tgz",
"integrity": "sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==",
"dev": true,
"requires": {
"array-back": "^4.0.1",
"chalk": "^2.4.2",
"table-layout": "^1.0.1",
"typical": "^5.2.0"
}
},
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
@ -2373,9 +2361,9 @@
}
},
"dayjs": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.7.tgz",
"integrity": "sha512-IC877KBdMhBrCfBfJXHQlo0G8keZ0Opy7YIIq5QKtUbCuHMzim8S4PyiVK4YmihI3iOF9lhfUBW4AQWHTR5WHA=="
"version": "1.9.8",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.8.tgz",
"integrity": "sha512-F42qBtJRa30FKF7XDnOQyNUTsaxDkuaZRj/i7BejSHC34LlLfPoIU4aeopvWfM+m1dJ6/DHKAWLg2ur+pLgq1w=="
},
"debug": {
"version": "4.1.1",
@ -3661,6 +3649,12 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fastest-levenshtein": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
"integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
"dev": true
},
"fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@ -4823,12 +4817,6 @@
"integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==",
"dev": true
},
"leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
"dev": true
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@ -6223,12 +6211,6 @@
"resolve": "^1.9.0"
}
},
"reduce-flatten": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz",
"integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==",
"dev": true
},
"regenerator-runtime": {
"version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
@ -7018,18 +7000,6 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
"table-layout": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz",
"integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==",
"dev": true,
"requires": {
"array-back": "^4.0.1",
"deep-extend": "~0.6.0",
"typical": "^5.2.0",
"wordwrapjs": "^4.0.0"
}
},
"taffydb": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
@ -7390,12 +7360,6 @@
"is-typedarray": "^1.0.0"
}
},
"typical": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
"integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
"dev": true
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
@ -7731,30 +7695,30 @@
}
},
"webpack-cli": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.2.0.tgz",
"integrity": "sha512-EIl3k88vaF4fSxWSgtAQR+VwicfLMTZ9amQtqS4o+TDPW9HGaEpbFBbAZ4A3ZOT5SOnMxNOzROsSTPiE8tBJPA==",
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.3.0.tgz",
"integrity": "sha512-gve+BBKrzMPTOYDjupzV8JchUznhVWMKtWM1hFIQWi6XoeLvGNoQwkrtMWVb+aJ437GgCKdta7sIn10v621pKA==",
"dev": true,
"requires": {
"@webpack-cli/info": "^1.1.0",
"@webpack-cli/serve": "^1.1.0",
"@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/info": "^1.2.0",
"@webpack-cli/serve": "^1.2.0",
"colorette": "^1.2.1",
"command-line-usage": "^6.1.0",
"commander": "^6.2.0",
"enquirer": "^2.3.6",
"execa": "^4.1.0",
"fastest-levenshtein": "^1.0.12",
"import-local": "^3.0.2",
"interpret": "^2.2.0",
"leven": "^3.1.0",
"rechoir": "^0.7.0",
"v8-compile-cache": "^2.2.0",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"commander": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"dev": true
}
}
@ -7883,16 +7847,6 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wordwrapjs": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz",
"integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==",
"dev": true,
"requires": {
"reduce-flatten": "^2.0.0",
"typical": "^5.0.0"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",

View File

@ -32,7 +32,7 @@
"commonmark": "0.29.3",
"cookie-parser": "1.4.5",
"csurf": "1.11.0",
"dayjs": "1.9.7",
"dayjs": "1.9.8",
"ejs": "3.1.5",
"electron-debug": "3.2.0",
"electron-dl": "3.0.2",
@ -87,7 +87,7 @@
"lorem-ipsum": "2.0.3",
"rcedit": "3.0.0",
"webpack": "5.11.0",
"webpack-cli": "4.2.0"
"webpack-cli": "4.3.0"
},
"optionalDependencies": {
"electron-installer-debian": "2.0.1"

View File

@ -26,6 +26,7 @@ import PromotedAttributesWidget from "../widgets/attribute_widgets/promoted_attr
import InheritedAttributesWidget from "../widgets/inherited_attribute_list.js";
import NoteListWidget from "../widgets/note_list.js";
import SearchDefinitionWidget from "../widgets/search_definition.js";
import Container from "../widgets/container.js";
const RIGHT_PANE_CSS = `
<style>
@ -160,8 +161,11 @@ export default class DesktopMainWindowLayout {
.child(new InheritedAttributesWidget())
)
)
.child(new TabCachingWidget(() => new NoteDetailWidget()))
.child(new TabCachingWidget(() => new NoteListWidget()))
.child(new Container()
.css('height: 100%; overflow: auto;')
.child(new TabCachingWidget(() => new NoteDetailWidget()))
.child(new TabCachingWidget(() => new NoteListWidget()))
)
.child(new TabCachingWidget(() => new SimilarNotesWidget()))
.child(...this.customWidgets.get('center-pane'))
)

View File

@ -59,7 +59,7 @@ async function createNote(parentNoteId, options = {}) {
appContext.triggerCommand('focusAndSelectTitle');
}
else if (options.focus === 'content') {
appContext.triggerCommand('focusOnDetail', {tabId: this.tabId});
appContext.triggerCommand('focusOnDetail', {tabId: activeTabContext.tabId});
}
}

View File

@ -148,8 +148,12 @@ class NoteListRenderer {
/*
* We're using noteIds so that it's not necessary to load all notes at once when paging
*/
constructor(parentNote, noteIds) {
constructor($parent, parentNote, noteIds) {
this.$noteList = $(TPL);
// note list must be added to the DOM immediatelly, otherwise some functionality scripting (canvas) won't work
$parent.empty().append(this.$noteList);
this.parentNote = parentNote;
this.noteIds = noteIds;
this.page = 1;

View File

@ -0,0 +1,38 @@
import BasicWidget from "./basic_widget.js";
export default class Container extends BasicWidget {
constructor() {
super();
this.children = [];
this.positionCounter = 10;
}
child(...components) {
if (!components) {
return this;
}
super.child(...components);
for (const component of components) {
if (!component.position) {
component.position = this.positionCounter;
this.positionCounter += 10;
}
}
this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1);
return this;
}
doRender() {
this.$widget = $(`<div>`);
for (const widget of this.children) {
this.$widget.append(widget.render());
}
}
}

View File

@ -1,6 +1,6 @@
import BasicWidget from "./basic_widget.js";
import Container from "./container.js";
export default class FlexContainer extends BasicWidget {
export default class FlexContainer extends Container {
constructor(direction) {
super();
@ -9,36 +9,5 @@ export default class FlexContainer extends BasicWidget {
}
this.attrs.style = `display: flex; flex-direction: ${direction};`;
this.children = [];
this.positionCounter = 10;
}
child(...components) {
if (!components) {
return this;
}
super.child(...components);
for (const component of components) {
if (!component.position) {
component.position = this.positionCounter;
this.positionCounter += 10;
}
}
this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1);
return this;
}
doRender() {
this.$widget = $(`<div>`);
for (const widget of this.children) {
this.$widget.append(widget.render());
}
}
}

View File

@ -25,8 +25,6 @@ const TPL = `
<div class="note-detail">
<style>
.note-detail {
min-height: 0;
flex-grow: 1;
font-family: var(--detail-font-family);
font-size: var(--detail-font-size);
}

View File

@ -32,12 +32,46 @@ export default class NoteListWidget extends TabAwareWidget {
this.$widget = $(TPL);
this.$content = this.$widget.find('.note-list-widget-content');
this.contentSized();
const observer = new IntersectionObserver(entries => {
this.isIntersecting = entries[0].isIntersecting;
this.checkRenderStatus();
}, {
rootMargin: '50px',
threshold: 0.1
});
observer.observe(this.$widget[0]);
}
async refreshWithNote(note) {
const noteListRenderer = new NoteListRenderer(note, note.getChildNoteIds());
checkRenderStatus() {
console.log("this.isIntersecting", this.isIntersecting);
console.log("this.noteIdRefreshed === this.noteId", this.noteIdRefreshed === this.noteId);
console.log("this.shownNoteId !== this.noteId", this.shownNoteId !== this.noteId);
this.$content.empty().append(await noteListRenderer.renderList());
if (this.isIntersecting
&& this.noteIdRefreshed === this.noteId
&& this.shownNoteId !== this.noteId) {
this.shownNoteId = this.noteId;
this.renderNoteList(this.note);
}
}
async renderNoteList(note) {
const noteListRenderer = new NoteListRenderer(this.$content, note, note.getChildNoteIds());
await noteListRenderer.renderList();
}
noteDetailRefreshedEvent({tabId}) {
if (!this.isTab(tabId)) {
return;
}
this.noteIdRefreshed = this.noteId;
setTimeout(() => this.checkRenderStatus(), 100);
}
autoBookDisabledEvent({tabContext}) {

View File

@ -124,7 +124,7 @@ export default class EditableCodeTypeWidget extends TypeWidget {
async doRefresh(note) {
const noteComplement = await this.tabContext.getNoteComplement();
this.spacedUpdate.allowUpdateWithoutChange(() => {
await this.spacedUpdate.allowUpdateWithoutChange(() => {
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
// we provide fallback
this.codeEditor.setValue(noteComplement.content || "");

View File

@ -54,8 +54,6 @@ const TPL = `
.note-detail-editable-text h6::before { content: "######\\00a0\\00a0"; color: var(--muted-text-color); }
.note-detail-editable-text {
overflow: auto;
height: 100%;
font-family: var(--detail-text-font-family);
padding-left: 12px;
}

View File

@ -22,6 +22,8 @@ export default class TypeWidget extends TabAwareWidget {
this.toggleInt(true);
await this.doRefresh(this.note);
this.triggerEvent('noteDetailRefreshed', {tabId: this.tabContext.tabId});
}
}