From c1b7f60e358cb54978cd430f1bc2106cb4d8754d Mon Sep 17 00:00:00 2001 From: Mo Date: Mon, 10 Jan 2022 22:04:57 -0600 Subject: [PATCH] feat: move save method into snjs controller (#809) * feat: move editor save method to snjs note controller --- app/assets/javascripts/strings.ts | 7 - .../javascripts/views/note_view/note_view.ts | 128 ++++-------------- package.json | 6 +- public/components/checksums.json | 6 +- .../dist/dist.css | 6 +- .../dist/dist.css.map | 2 +- .../package.json | 2 +- yarn.lock | 26 ++-- 8 files changed, 49 insertions(+), 134 deletions(-) diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index 75a099619..6fd220126 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -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 = diff --git a/app/assets/javascripts/views/note_view/note_view.ts b/app/assets/javascripts/views/note_view/note_view.ts index 9bba09f67..e1a2a22f6 100644 --- a/app/assets/javascripts/views/note_view/note_view.ts +++ b/app/assets/javascripts/views/note_view/note_view.ts @@ -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 { private leftPanelPuppet?: PanelPuppet; private rightPanelPuppet?: PanelPuppet; - private saveTimeout?: ng.IPromise; private statusTimeout?: ng.IPromise; private lastEditorFocusEventSource?: EventSource; public editorValues: EditorValues = { title: '', text: '' }; @@ -152,7 +144,6 @@ export class NoteView extends PureViewCtrl { 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 { 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 { ); } - /** - * @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 { } 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 { } 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 { 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 { 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, + }); }, }); diff --git a/package.json b/package.json index afcd9575a..9d695953a 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/public/components/checksums.json b/public/components/checksums.json index a3e03c005..ae808a384 100644 --- a/public/components/checksums.json +++ b/public/components/checksums.json @@ -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", diff --git a/public/components/org.standardnotes.theme-dynamic/dist/dist.css b/public/components/org.standardnotes.theme-dynamic/dist/dist.css index 568fcdd78..f943962c4 100644 --- a/public/components/org.standardnotes.theme-dynamic/dist/dist.css +++ b/public/components/org.standardnotes.theme-dynamic/dist/dist.css @@ -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; diff --git a/public/components/org.standardnotes.theme-dynamic/dist/dist.css.map b/public/components/org.standardnotes.theme-dynamic/dist/dist.css.map index e32d7e9f1..657138b14 100644 --- a/public/components/org.standardnotes.theme-dynamic/dist/dist.css.map +++ b/public/components/org.standardnotes.theme-dynamic/dist/dist.css.map @@ -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" diff --git a/public/components/org.standardnotes.theme-dynamic/package.json b/public/components/org.standardnotes.theme-dynamic/package.json index 154242d0d..3bbb618dc 100644 --- a/public/components/org.standardnotes.theme-dynamic/package.json +++ b/public/components/org.standardnotes.theme-dynamic/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index 939a236fd..fcb330e53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"