This commit is contained in:
Mo Bitar
2020-04-01 09:53:19 -05:00
parent 822d8553b7
commit 8835fd6ebf
7 changed files with 188 additions and 107 deletions

View File

@@ -143,6 +143,21 @@ class EditorCtrl extends PureCtrl {
} }
} }
/**
* Because note.locked accesses note.content.appData,
* we do not want to expose the template to direct access to note.locked,
* otherwise an exception will occur when trying to access note.locked if the note
* is deleted. There is potential for race conditions to occur with setState, where a
* previous setState call may have queued a digest cycle, and the digest cycle triggers
* on a deleted note.
*/
get noteLocked() {
if(!this.state.note || this.state.note.deleted) {
return false;
}
return this.state.note.locked;
}
streamItems() { streamItems() {
this.application.streamItems({ this.application.streamItems({
contentType: ContentTypes.Note, contentType: ContentTypes.Note,
@@ -150,7 +165,14 @@ class EditorCtrl extends PureCtrl {
if (!this.state.note) { if (!this.state.note) {
return; return;
} }
if (this.state.note.deleted || this.state.note.content.trashed) { if (this.state.note.deleted) {
await this.setState({
note: null,
noteReady: false
});
return;
}
if (this.state.note.content.trashed) {
return; return;
} }
if (!isPayloadSourceRetrieved(source)) { if (!isPayloadSourceRetrieved(source)) {
@@ -187,7 +209,7 @@ class EditorCtrl extends PureCtrl {
this.application.streamItems({ this.application.streamItems({
contentType: ContentTypes.Component, contentType: ContentTypes.Component,
stream: async ({ items, source }) => { stream: async ({ items }) => {
if (!this.state.note) { if (!this.state.note) {
return; return;
} }
@@ -213,6 +235,8 @@ class EditorCtrl extends PureCtrl {
} }
async handleNoteSelectionChange(note, previousNote) { async handleNoteSelectionChange(note, previousNote) {
console.log("SN: handleNoteSelectionChange -> note", note);
console.log(this.application.itemsKeyManager.allItemsKeys);
this.setState({ this.setState({
note: this.application.getAppState().getSelectedNote(), note: this.application.getAppState().getSelectedNote(),
showExtensions: false, showExtensions: false,

View File

@@ -171,6 +171,9 @@ class NotesCtrl extends PureCtrl {
/** Note has changed values, reset its flags */ /** Note has changed values, reset its flags */
const notes = items.filter((item) => item.content_type === ContentTypes.Note); const notes = items.filter((item) => item.content_type === ContentTypes.Note);
for (const note of notes) { for (const note of notes) {
if(note.deleted) {
continue;
}
this.loadFlagsForNote(note); this.loadFlagsForNote(note);
note.cachedCreatedAtString = note.createdAtString(); note.cachedCreatedAtString = note.createdAtString();
note.cachedUpdatedAtString = note.updatedAtString(); note.cachedUpdatedAtString = note.updatedAtString();
@@ -180,7 +183,7 @@ class NotesCtrl extends PureCtrl {
} }
async selectNote(note) { async selectNote(note) {
this.application.getAppState().setSelectedNote(note); return this.application.getAppState().setSelectedNote(note);
} }
async createNewNote() { async createNewNote() {

View File

@@ -3,12 +3,12 @@ import { SNAlertService } from 'snjs';
import { SKAlert } from 'sn-stylekit'; import { SKAlert } from 'sn-stylekit';
export class AlertService extends SNAlertService { export class AlertService extends SNAlertService {
async alert({ async alert(
title, title,
text, text,
closeButtonText = "OK", closeButtonText = "OK",
onClose onClose
} = {}) { ) {
return new Promise((resolve) => { return new Promise((resolve) => {
const buttons = [ const buttons = [
{ {
@@ -27,7 +27,7 @@ export class AlertService extends SNAlertService {
}); });
} }
async confirm({ async confirm(
title, title,
text, text,
confirmButtonText = "Confirm", confirmButtonText = "Confirm",
@@ -35,7 +35,7 @@ export class AlertService extends SNAlertService {
onConfirm, onConfirm,
onCancel, onCancel,
destructive = false destructive = false
} = {}) { ) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const buttons = [ const buttons = [
{ {

View File

@@ -40,7 +40,7 @@ export class AppState {
this.unsubApp(); this.unsubApp();
this.unsubApp = null; this.unsubApp = null;
this.observers.length = 0; this.observers.length = 0;
if(this.rootScopeCleanup1) { if (this.rootScopeCleanup1) {
this.rootScopeCleanup1(); this.rootScopeCleanup1();
this.rootScopeCleanup2(); this.rootScopeCleanup2();
this.rootScopeCleanup1 = null; this.rootScopeCleanup1 = null;
@@ -138,12 +138,16 @@ export class AppState {
await this.application.application.privilegesService.actionRequiresPrivilege( await this.application.application.privilegesService.actionRequiresPrivilege(
ProtectedActions.ViewProtectedNotes ProtectedActions.ViewProtectedNotes
)) { )) {
return new Promise((resolve) => {
this.application.presentPrivilegesModal( this.application.presentPrivilegesModal(
ProtectedActions.ViewProtectedNotes, ProtectedActions.ViewProtectedNotes,
run () => {
run().then(resolve);
}
); );
});
} else { } else {
run(); return run();
} }
} }

View File

@@ -1,7 +1,7 @@
#editor-column.section.editor.sn-component(aria-label='Note') #editor-column.section.editor.sn-component(aria-label='Note')
.sn-component .sn-component
.sk-app-bar.no-edges( .sk-app-bar.no-edges(
ng-if='self.state.note.locked', ng-if='self.noteLocked',
ng-init="self.lockText = 'Note Locked'", ng-init="self.lockText = 'Note Locked'",
ng-mouseleave="self.lockText = 'Note Locked'", ng-mouseleave="self.lockText = 'Note Locked'",
ng-mouseover="self.lockText = 'Unlock'" ng-mouseover="self.lockText = 'Unlock'"
@@ -12,14 +12,14 @@
i.icon.ion-locked i.icon.ion-locked
| {{self.lockText}} | {{self.lockText}}
#editor-title-bar.section-title-bar( #editor-title-bar.section-title-bar(
ng-class="{'locked' : self.state.note.locked}", ng-class="{'locked' : self.noteLocked}",
ng-show='self.state.note && !self.state.note.errorDecrypting' ng-show='self.state.note && !self.state.note.errorDecrypting'
) )
.title .title
input#note-title-editor.input( input#note-title-editor.input(
ng-blur='self.onNameBlur()', ng-blur='self.onNameBlur()',
ng-change='self.onTitleChange()', ng-change='self.onTitleChange()',
ng-disabled='self.state.note.locked', ng-disabled='self.noteLocked',
ng-focus='self.onNameFocus()', ng-focus='self.onNameFocus()',
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)', ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
ng-model='self.state.note.title', ng-model='self.state.note.title',
@@ -34,13 +34,13 @@
#note-tags-component-container(ng-if='self.state.tagsComponent') #note-tags-component-container(ng-if='self.state.tagsComponent')
component-view.component-view( component-view.component-view(
component='self.state.tagsComponent', component='self.state.tagsComponent',
ng-class="{'locked' : self.state.note.locked}", ng-class="{'locked' : self.noteLocked}",
ng-style="self.state.note.locked && {'pointer-events' : 'none'}", ng-style="self.noteLocked && {'pointer-events' : 'none'}",
application='self.application' application='self.application'
) )
input.tags-input( input.tags-input(
ng-blur='self.saveTags()', ng-blur='self.saveTags()',
ng-disabled='self.state.note.locked', ng-disabled='self.noteLocked',
ng-if='!(self.state.tagsComponent && self.state.tagsComponent.active)', ng-if='!(self.state.tagsComponent && self.state.tagsComponent.active)',
ng-keyup='$event.keyCode == 13 && $event.target.blur();', ng-keyup='$event.keyCode == 13 && $event.target.blur();',
ng-model='self.state.mutable.tagsString', ng-model='self.state.mutable.tagsString',
@@ -75,7 +75,7 @@
menu-row( menu-row(
action='self.selectedMenuItem(true); self.toggleLockNote()', action='self.selectedMenuItem(true); self.toggleLockNote()',
desc="'Locking notes prevents unintentional editing'", desc="'Locking notes prevents unintentional editing'",
label="self.state.note.locked ? 'Unlock' : 'Lock'" label="self.noteLocked ? 'Unlock' : 'Lock'"
) )
menu-row( menu-row(
action='self.selectedMenuItem(true); self.toggleProtectNote()', action='self.selectedMenuItem(true); self.toggleProtectNote()',
@@ -219,7 +219,7 @@
ng-if='!self.state.selectedEditor', ng-if='!self.state.selectedEditor',
ng-model='self.state.note.text', ng-model='self.state.note.text',
ng-model-options='{ debounce: self.state.editorDebounce}', ng-model-options='{ debounce: self.state.editorDebounce}',
ng-readonly='self.state.note.locked', ng-readonly='self.noteLocked',
ng-trim='false' ng-trim='false'
) )
| {{self.onSystemEditorLoad()}} | {{self.onSystemEditorLoad()}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long