feat: move save method into snjs controller (#809)

* feat: move editor save method to snjs note controller
This commit is contained in:
Mo
2022-01-10 22:04:57 -06:00
committed by GitHub
parent 660f74c8ba
commit c1b7f60e35
8 changed files with 49 additions and 134 deletions

View File

@@ -25,13 +25,6 @@ export const STRING_DELETE_TAG =
export const STRING_MISSING_SYSTEM_TAG = 'We are missing a System Tag.';
/** @editor */
export const STRING_SAVING_WHILE_DOCUMENT_HIDDEN =
'Attempting to save an item while the application is hidden. To protect data integrity, please refresh the application window and try again.';
export const STRING_DELETED_NOTE =
'The note you are attempting to edit has been deleted, and is awaiting sync. Changes you make will be disregarded.';
export const STRING_INVALID_NOTE =
"The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note.";
export const STRING_ELLIPSES = '...';
export const STRING_GENERIC_SAVE_ERROR =
'There was an error saving your note. Please try again.';
export const STRING_DELETE_PLACEHOLDER_ATTEMPT =

View File

@@ -1,4 +1,3 @@
import { STRING_SAVING_WHILE_DOCUMENT_HIDDEN } from './../../strings';
import { WebApplication } from '@/ui_models/application';
import { PanelPuppet, WebDirective } from '@/types';
import angular from 'angular';
@@ -27,9 +26,6 @@ import template from './note-view.pug';
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
import { EventSource } from '@/ui_models/app_state';
import {
STRING_DELETED_NOTE,
STRING_INVALID_NOTE,
STRING_ELLIPSES,
STRING_DELETE_PLACEHOLDER_ATTEMPT,
STRING_DELETE_LOCKED_ATTEMPT,
STRING_EDIT_LOCKED_ATTEMPT,
@@ -37,10 +33,7 @@ import {
} from '@/strings';
import { confirmDialog } from '@/services/alertService';
const NOTE_PREVIEW_CHAR_LIMIT = 80;
const MINIMUM_STATUS_DURATION = 400;
const SAVE_TIMEOUT_DEBOUNCE = 350;
const SAVE_TIMEOUT_NO_DEBOUNCE = 100;
const EDITOR_DEBOUNCE = 100;
const ElementIds = {
@@ -97,7 +90,6 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
private leftPanelPuppet?: PanelPuppet;
private rightPanelPuppet?: PanelPuppet;
private saveTimeout?: ng.IPromise<void>;
private statusTimeout?: ng.IPromise<void>;
private lastEditorFocusEventSource?: EventSource;
public editorValues: EditorValues = { title: '', text: '' };
@@ -152,7 +144,6 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
this.leftPanelPuppet = undefined;
this.rightPanelPuppet = undefined;
this.onEditorComponentLoad = undefined;
this.saveTimeout = undefined;
this.statusTimeout = undefined;
(this.onPanelResizeFinish as unknown) = undefined;
(this.editorMenuOnSelect as unknown) = undefined;
@@ -483,13 +474,16 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
const transactions: TransactionalMutation[] = [];
this.setMenuState('showEditorMenu', false);
if (this.appState.getActiveNoteController()?.isTemplateNote) {
await this.appState.getActiveNoteController().insertTemplatedNote();
}
if (this.note.locked) {
this.application.alertService.alert(STRING_EDIT_LOCKED_ATTEMPT);
return;
}
if (!component) {
if (!this.note.prefersPlainEditor) {
transactions.push({
@@ -546,83 +540,6 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
);
}
/**
* @param bypassDebouncer Calling save will debounce by default. You can pass true to save
* immediately.
* @param isUserModified This field determines if the item will be saved as a user
* modification, thus updating the user modified date displayed in the UI
* @param dontUpdatePreviews Whether this change should update the note's plain and HTML
* preview.
* @param customMutate A custom mutator function.
* @param closeAfterSync Whether this editor should be closed after the sync starts.
* This allows us to make a destructive change, wait for sync to be triggered, then
* close the editor (if we closed the editor before sync began, we'd get an exception,
* since the debouncer will be triggered on a non-existent editor)
*/
async save(
note: SNNote,
editorValues: EditorValues,
bypassDebouncer = false,
isUserModified = false,
dontUpdatePreviews = false,
customMutate?: (mutator: NoteMutator) => void,
closeAfterSync = false
) {
const title = editorValues.title;
const text = editorValues.text;
const isTemplate = this.controller.isTemplateNote;
if (document.hidden) {
this.application.alertService.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
return;
}
if (note.deleted) {
this.application.alertService.alert(STRING_DELETED_NOTE);
return;
}
if (isTemplate) {
await this.controller.insertTemplatedNote();
}
if (!this.application.findItem(note.uuid)) {
this.application.alertService.alert(STRING_INVALID_NOTE);
return;
}
await this.application.changeItem(
note.uuid,
(mutator) => {
const noteMutator = mutator as NoteMutator;
if (customMutate) {
customMutate(noteMutator);
}
noteMutator.title = title;
noteMutator.text = text;
if (!dontUpdatePreviews) {
const noteText = text || '';
const truncate = noteText.length > NOTE_PREVIEW_CHAR_LIMIT;
const substring = noteText.substring(0, NOTE_PREVIEW_CHAR_LIMIT);
const previewPlain = substring + (truncate ? STRING_ELLIPSES : '');
// eslint-disable-next-line camelcase
noteMutator.preview_plain = previewPlain;
// eslint-disable-next-line camelcase
noteMutator.preview_html = undefined;
}
},
isUserModified
);
if (this.saveTimeout) {
this.$timeout.cancel(this.saveTimeout);
}
const noDebounce = bypassDebouncer || this.application.noAccount();
const syncDebouceMs = noDebounce
? SAVE_TIMEOUT_NO_DEBOUNCE
: SAVE_TIMEOUT_DEBOUNCE;
this.saveTimeout = this.$timeout(() => {
this.application.sync();
if (closeAfterSync) {
this.appState.closeNoteController(this.controller);
}
}, syncDebouceMs);
}
showSavingStatus() {
this.setStatus({ message: 'Saving…' }, false);
}
@@ -676,7 +593,10 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
}
contentChanged() {
this.save(this.note, copyEditorValues(this.editorValues), false, true);
this.controller.save({
editorValues: copyEditorValues(this.editorValues),
isUserModified: true,
});
}
onTitleEnter($event: Event) {
@@ -686,13 +606,11 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
}
onTitleChange() {
this.save(
this.note,
copyEditorValues(this.editorValues),
false,
true,
true
);
this.controller.save({
editorValues: copyEditorValues(this.editorValues),
isUserModified: true,
dontUpdatePreviews: true,
});
}
focusEditor() {
@@ -744,16 +662,14 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
if (permanently) {
this.performNoteDeletion(this.note);
} else {
this.save(
this.note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
this.controller.save({
editorValues: copyEditorValues(this.editorValues),
bypassDebouncer: true,
dontUpdatePreviews: true,
customMutate: (mutator) => {
mutator.trashed = true;
}
);
},
});
}
}
}
@@ -1022,7 +938,11 @@ export class NoteView extends PureViewCtrl<unknown, EditorState> {
editor.selectionStart = editor.selectionEnd = start + 4;
}
this.editorValues.text = editor.value;
this.save(this.note, copyEditorValues(this.editorValues), true);
this.controller.save({
editorValues: copyEditorValues(this.editorValues),
bypassDebouncer: true,
});
},
});

View File

@@ -28,7 +28,7 @@
"@babel/preset-typescript": "^7.15.0",
"@reach/disclosure": "^0.16.2",
"@reach/visually-hidden": "^0.16.0",
"@standardnotes/components": "^1.2.4",
"@standardnotes/components": "^1.2.5",
"@svgr/webpack": "^5.5.0",
"@types/angular": "^1.8.3",
"@types/jest": "^27.0.3",
@@ -87,9 +87,9 @@
"@reach/dialog": "^0.16.2",
"@reach/listbox": "^0.16.2",
"@reach/tooltip": "^0.16.2",
"@standardnotes/features": "1.20.5",
"@standardnotes/features": "1.20.6",
"@standardnotes/sncrypto-web": "1.5.3",
"@standardnotes/snjs": "2.34.2",
"@standardnotes/snjs": "2.35.0",
"mobx": "^6.3.5",
"mobx-react-lite": "^3.2.2",
"preact": "^10.5.15",

View File

@@ -30,9 +30,9 @@
"binary": "1928aa349a04471afd273725cc4befe711eeda91aca70aee00c7ad356241c252"
},
"org.standardnotes.theme-dynamic": {
"version": "1.0.1",
"base64": "ead03c37f6cb3b1858793db4433331143f916aebb3a13ab07637c27dcf310034",
"binary": "fb93157b0249f577e7a5e58f8bb562e68435f683cc66f7adace12b935fa3eee1"
"version": "1.0.2",
"base64": "7a5075a265e67ae54cb7c49bad6aa8b6f84f8fb4883ca859327e8e794cbfff0c",
"binary": "01a1356c879aa1ef38e856ee0028e6afbff1fa40544e24e3297af863d6cac669"
},
"org.standardnotes.code-editor": {
"version": "1.3.8",

View File

@@ -1,10 +1,12 @@
.section.tags {
.section.tags,
navigation {
flex: none !important;
width: 120px !important;
transition: width 0.25s;
}
.section.tags:hover {
.section.tags:hover,
navigation:hover {
flex: initial;
width: 180px !important;
transition: width 0.25s;

View File

@@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "AAAA,aAAc;EACZ,IAAI,EAAE,eAAe;EACrB,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB,mBAAoB;EAClB,IAAI,EAAE,OAAO;EACb,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB;UACW;EACT,IAAI,EAAE,eAAe;EACrB,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB;gBACiB;EACf,IAAI,EAAE,OAAO;EACb,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW",
"mappings": "AAAA;UACW;EACT,IAAI,EAAE,eAAe;EACrB,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB;gBACiB;EACf,IAAI,EAAE,OAAO;EACb,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB;UACW;EACT,IAAI,EAAE,eAAe;EACrB,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW;;;AAGzB;gBACiB;EACf,IAAI,EAAE,OAAO;EACb,KAAK,EAAE,gBAAgB;EACvB,UAAU,EAAE,WAAW",
"sources": ["../src/main.scss"],
"names": [],
"file": "dist.css"

View File

@@ -1,6 +1,6 @@
{
"name": "sn-theme-dynamic",
"version": "1.0.1",
"version": "1.0.2",
"main": "dist/dist.css",
"devDependencies": {
"grunt": "^1.0.1",

View File

@@ -2616,10 +2616,10 @@
resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.2.1.tgz#9db212db86ccbf08b347da02549b3dbe4bedbb02"
integrity sha512-HilBxS50CBlC6TJvy1mrnhGVDzOH63M/Jf+hyMxQ0Vt1nYzpd0iyxVEUrgMh7ZiyO1b9CLnCDED99Jy9rnZWVQ==
"@standardnotes/components@^1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.2.4.tgz#29cab333551e91d8c88c920a7d5e3bd863d55f17"
integrity sha512-Ous0tCCnzIH4IHN/3y0C03XYlpTfxP+mfsPNJN/kPhC0Z+91OV+z6Y/qK1zxe6khsegUEO6k01qyPu5EJLhorg==
"@standardnotes/components@^1.2.5":
version "1.2.5"
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.2.5.tgz#3e1e959bc40e5e0d34a0a44ac68fda4b29807f8e"
integrity sha512-/E87R6wpMK0nLeS6ugCyjHht3M5hqZUH4lWA179jE9N4A6WXYvlqcFYO4t2RiG6yErRPZOHfpUFFsL1agXVuwA==
"@standardnotes/domain-events@2.5.1":
version "2.5.1"
@@ -2628,10 +2628,10 @@
dependencies:
"@standardnotes/auth" "^3.8.1"
"@standardnotes/features@1.20.5", "@standardnotes/features@^1.20.5":
version "1.20.5"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.20.5.tgz#443e3ae84d13f0aaa35708c5c237dac8041cb50d"
integrity sha512-4QQeWLk2frEF9UYOfnuQoulkUJ3PooVLasPUA+zva+KIokBiyPmVPsi3HAYXlHqowu+lDhKU2pUklLhm1ePvJw==
"@standardnotes/features@1.20.6", "@standardnotes/features@^1.20.6":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.20.6.tgz#94d397892dd12f76a10c89c70092933627a9c457"
integrity sha512-/w8+/8J8UNJ+DAsOud8XbWkeUBN6eb+5+Ic4NgkXYkx/wv6sTDk9XVc+mOhxOkYlb2iy85JDmoLAwu+GW/3Gtg==
dependencies:
"@standardnotes/auth" "3.8.3"
"@standardnotes/common" "1.2.1"
@@ -2655,15 +2655,15 @@
buffer "^6.0.3"
libsodium-wrappers "^0.7.9"
"@standardnotes/snjs@2.34.2":
version "2.34.2"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.34.2.tgz#540f32252083f99ee635b900cc70aa19ed68e1f2"
integrity sha512-JhhjAQ66sSHTnGSgTY5VSJU7Lv9fnX0X+SR/pPPi0Kv3gk+aqVi2Zmgf8htmigJSFtrmn2pXGSaJk1v92LFckw==
"@standardnotes/snjs@2.35.0":
version "2.35.0"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.35.0.tgz#c24d13d7be68767b865b9f3e728d21b473bbe006"
integrity sha512-dbjFMlEShsgo8sjaiwEFtbvm6vZHIgylZEtzqcJxl0TzEEIO1q4baomzUFj0ayzmM7g7S38o7zBfj+2AoXxPeA==
dependencies:
"@standardnotes/auth" "3.8.1"
"@standardnotes/common" "1.2.1"
"@standardnotes/domain-events" "2.5.1"
"@standardnotes/features" "^1.20.5"
"@standardnotes/features" "^1.20.6"
"@standardnotes/settings" "^1.9.0"
"@standardnotes/sncrypto-common" "1.5.2"