Optimize digest cycle by reloading state only upon explicit data change
This commit is contained in:
@@ -35,15 +35,19 @@ angular.module('app')
|
||||
syncManager.addEventHandler((syncEvent, data) => {
|
||||
if(syncEvent == "local-data-loaded") {
|
||||
this.localDataLoaded = true;
|
||||
if(this.tag && this.tag.notes.length == 0) {
|
||||
if(this.tag && this.notes.length == 0) {
|
||||
this.createNewNote();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modelManager.addItemSyncObserver("note-list", "Note", (allItems, validItems, deletedItems, source, sourceKey) => {
|
||||
modelManager.addItemSyncObserver("note-list", "*", (allItems, validItems, deletedItems, source, sourceKey) => {
|
||||
// reload our notes
|
||||
this.setNotes(this.tag.notes);
|
||||
|
||||
// Note has changed values, reset its flags
|
||||
for(var note of allItems) {
|
||||
let notes = allItems.filter((item) => item.content_type == "Note");
|
||||
for(let note of notes) {
|
||||
note.flags = null;
|
||||
}
|
||||
|
||||
@@ -53,6 +57,14 @@ angular.module('app')
|
||||
}
|
||||
});
|
||||
|
||||
this.setNotes = function(notes) {
|
||||
this.notes = this.sortNotes(notes, this.sortBy, this.sortReverse);
|
||||
}
|
||||
|
||||
this.reorderNotes = function() {
|
||||
this.setNotes(this.notes);
|
||||
}
|
||||
|
||||
this.loadPreferences = function() {
|
||||
let prevSortValue = this.sortBy;
|
||||
|
||||
@@ -147,7 +159,7 @@ angular.module('app')
|
||||
|
||||
this.panelTitle = function() {
|
||||
if(this.isFiltering()) {
|
||||
return `${this.tag.notes.filter((i) => {return i.visible;}).length} search results`;
|
||||
return `${this.notes.filter((i) => {return i.visible;}).length} search results`;
|
||||
} else if(this.tag) {
|
||||
return `${this.tag.title}`;
|
||||
}
|
||||
@@ -245,16 +257,21 @@ angular.module('app')
|
||||
|
||||
this.noteFilter.text = "";
|
||||
|
||||
if(tag.notes.length > 0) {
|
||||
tag.notes.forEach((note) => { note.visible = true; })
|
||||
this.selectFirstNote();
|
||||
} else if(this.localDataLoaded) {
|
||||
this.createNewNote();
|
||||
}
|
||||
this.setNotes(tag.notes);
|
||||
|
||||
// perform in timeout since visibleNotes relies on renderedNotes which relies on render to complete
|
||||
$timeout(() => {
|
||||
if(this.notes.length > 0) {
|
||||
this.notes.forEach((note) => { note.visible = true; })
|
||||
this.selectFirstNote();
|
||||
} else if(this.localDataLoaded) {
|
||||
this.createNewNote();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.visibleNotes = function() {
|
||||
return this.sortedNotes.filter(function(note){
|
||||
return this.renderedNotes.filter(function(note){
|
||||
return note.visible;
|
||||
});
|
||||
}
|
||||
@@ -298,9 +315,9 @@ angular.module('app')
|
||||
}
|
||||
|
||||
this.createNewNote = function() {
|
||||
// The "Note X" counter is based off this.tag.notes.length, but sometimes, what you see in the list is only a subset.
|
||||
// The "Note X" counter is based off this.notes.length, but sometimes, what you see in the list is only a subset.
|
||||
// We can use this.visibleNotes().length, but that only accounts for non-paginated results, so first 15 or so.
|
||||
var title = "Note" + (this.tag.notes ? (" " + (this.tag.notes.length + 1)) : "");
|
||||
var title = "Note" + (this.notes ? (" " + (this.notes.length + 1)) : "");
|
||||
let newNote = modelManager.createItem({content_type: "Note", content: {text: "", title: title}});
|
||||
newNote.dummy = true;
|
||||
this.newNote = newNote;
|
||||
@@ -389,12 +406,14 @@ angular.module('app')
|
||||
this.toggleReverseSort = function() {
|
||||
this.selectedMenuItem();
|
||||
this.sortReverse = !this.sortReverse;
|
||||
this.reorderNotes();
|
||||
authManager.setUserPrefValue("sortReverse", this.sortReverse);
|
||||
authManager.syncUserPreferences();
|
||||
}
|
||||
|
||||
this.setSortBy = function(type) {
|
||||
this.sortBy = type;
|
||||
this.reorderNotes();
|
||||
authManager.setUserPrefValue("sortBy", this.sortBy);
|
||||
authManager.syncUserPreferences();
|
||||
}
|
||||
@@ -416,4 +435,50 @@ angular.module('app')
|
||||
return note.tags && note.tags.length > 1;
|
||||
}
|
||||
|
||||
this.sortNotes = function(items, sortBy, reverse) {
|
||||
let sortValueFn = (a, b, pinCheck = false) => {
|
||||
if(!pinCheck) {
|
||||
if(a.pinned && b.pinned) {
|
||||
return sortValueFn(a, b, true);
|
||||
}
|
||||
if(a.pinned) { return -1; }
|
||||
if(b.pinned) { return 1; }
|
||||
}
|
||||
|
||||
var aValue = a[sortBy] || "";
|
||||
var bValue = b[sortBy] || "";
|
||||
|
||||
let vector = 1;
|
||||
|
||||
if(reverse) {
|
||||
vector *= -1;
|
||||
}
|
||||
|
||||
if(sortBy == "title") {
|
||||
aValue = aValue.toLowerCase();
|
||||
bValue = bValue.toLowerCase();
|
||||
|
||||
if(aValue.length == 0 && bValue.length == 0) {
|
||||
return 0;
|
||||
} else if(aValue.length == 0 && bValue.length != 0) {
|
||||
return 1 * vector;
|
||||
} else if(aValue.length != 0 && bValue.length == 0) {
|
||||
return -1 * vector;
|
||||
} else {
|
||||
vector *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(aValue > bValue) { return -1 * vector;}
|
||||
else if(aValue < bValue) { return 1 * vector;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
items = items || [];
|
||||
var result = items.sort(function(a, b){
|
||||
return sortValueFn(a, b);
|
||||
})
|
||||
return result;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -33,6 +33,26 @@ angular.module('app')
|
||||
}
|
||||
});
|
||||
|
||||
modelManager.addItemSyncObserver("note-list", "*", (allItems, validItems, deletedItems, source, sourceKey) => {
|
||||
// recompute note counts
|
||||
let tags = [];
|
||||
if(this.tags) {
|
||||
tags = tags.concat(this.tags);
|
||||
}
|
||||
if(this.smartTags) {
|
||||
tags = tags.concat(this.smartTags);
|
||||
}
|
||||
|
||||
for(let tag of tags) {
|
||||
var validNotes = SNNote.filterDummyNotes(tag.notes).filter(function(note){
|
||||
return !note.archived && !note.content.trashed;
|
||||
});
|
||||
|
||||
tag.cachedNoteCount = validNotes.length;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.panelController = {};
|
||||
|
||||
$rootScope.$on("user-preferences-changed", () => {
|
||||
@@ -146,12 +166,4 @@ angular.module('app')
|
||||
this.removeTag()(tag);
|
||||
this.selectTag(this.smartTags[0]);
|
||||
}
|
||||
|
||||
this.noteCount = function(tag) {
|
||||
var validNotes = SNNote.filterDummyNotes(tag.notes).filter(function(note){
|
||||
return !note.archived && !note.content.trashed;
|
||||
});
|
||||
return validNotes.length;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
angular.module('app')
|
||||
.filter('sortBy', function ($filter) {
|
||||
return function(items, sortBy, reverse) {
|
||||
let sortValueFn = (a, b, pinCheck = false) => {
|
||||
if(!pinCheck) {
|
||||
if(a.pinned && b.pinned) {
|
||||
return sortValueFn(a, b, true);
|
||||
}
|
||||
if(a.pinned) { return -1; }
|
||||
if(b.pinned) { return 1; }
|
||||
}
|
||||
|
||||
var aValue = a[sortBy] || "";
|
||||
var bValue = b[sortBy] || "";
|
||||
|
||||
let vector = 1;
|
||||
|
||||
if(reverse) {
|
||||
vector *= -1;
|
||||
}
|
||||
|
||||
if(sortBy == "title") {
|
||||
aValue = aValue.toLowerCase();
|
||||
bValue = bValue.toLowerCase();
|
||||
|
||||
if(aValue.length == 0 && bValue.length == 0) {
|
||||
return 0;
|
||||
} else if(aValue.length == 0 && bValue.length != 0) {
|
||||
return 1 * vector;
|
||||
} else if(aValue.length != 0 && bValue.length == 0) {
|
||||
return -1 * vector;
|
||||
} else {
|
||||
vector *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(aValue > bValue) { return -1 * vector;}
|
||||
else if(aValue < bValue) { return 1 * vector;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
items = items || [];
|
||||
var result = items.sort(function(a, b){
|
||||
return sortValueFn(a, b);
|
||||
})
|
||||
return result;
|
||||
};
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
angular.module('app').filter('startFrom', function() {
|
||||
return function(input, start) {
|
||||
return input.slice(start);
|
||||
};
|
||||
});
|
||||
@@ -123,7 +123,8 @@ class ModelManager extends SFModelManager {
|
||||
let notTrashedPredicate = new SFPredicate("content.trashed", "=", false);
|
||||
predicates.push(notTrashedPredicate);
|
||||
}
|
||||
return this.itemsMatchingPredicates(predicates);
|
||||
let results = this.itemsMatchingPredicates(predicates);
|
||||
return results;
|
||||
}
|
||||
|
||||
trashSmartTag() {
|
||||
|
||||
Reference in New Issue
Block a user