fix: enable, disable, sync editor stack per note
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
#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.noteLocked',
|
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'"
|
||||||
)
|
)
|
||||||
.left
|
.left
|
||||||
@@ -12,17 +12,17 @@
|
|||||||
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.noteLocked}",
|
ng-class="{'locked' : self.noteLocked}",
|
||||||
ng-show='self.note && !self.note.errorDecrypting'
|
ng-show='self.note && !self.note.errorDecrypting'
|
||||||
)
|
)
|
||||||
.title
|
.title
|
||||||
input#note-title-editor.input(
|
input#note-title-editor.input(
|
||||||
ng-blur='self.onTitleBlur()',
|
ng-blur='self.onTitleBlur()',
|
||||||
ng-change='self.onTitleChange()',
|
ng-change='self.onTitleChange()',
|
||||||
ng-disabled='self.noteLocked',
|
ng-disabled='self.noteLocked',
|
||||||
ng-focus='self.onTitleFocus()',
|
ng-focus='self.onTitleFocus()',
|
||||||
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
|
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
|
||||||
ng-model='self.editorValues.title',
|
ng-model='self.editorValues.title',
|
||||||
select-on-focus='true',
|
select-on-focus='true',
|
||||||
spellcheck='false'
|
spellcheck='false'
|
||||||
)
|
)
|
||||||
@@ -34,28 +34,28 @@
|
|||||||
.editor-tags
|
.editor-tags
|
||||||
#note-tags-component-container(ng-if='self.activeTagsComponent')
|
#note-tags-component-container(ng-if='self.activeTagsComponent')
|
||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component-uuid='self.activeTagsComponent.uuid',
|
component-uuid='self.activeTagsComponent.uuid',
|
||||||
ng-class="{'locked' : self.noteLocked}",
|
ng-class="{'locked' : self.noteLocked}",
|
||||||
ng-style="self.noteLocked && {'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.onTagsInputBlur()',
|
ng-blur='self.onTagsInputBlur()',
|
||||||
ng-disabled='self.noteLocked',
|
ng-disabled='self.noteLocked',
|
||||||
ng-if='!self.activeTagsComponent',
|
ng-if='!self.activeTagsComponent',
|
||||||
ng-keyup='$event.keyCode == 13 && $event.target.blur();',
|
ng-keyup='$event.keyCode == 13 && $event.target.blur();',
|
||||||
ng-model='self.editorValues.tagsInputValue',
|
ng-model='self.editorValues.tagsInputValue',
|
||||||
placeholder='#tags',
|
placeholder='#tags',
|
||||||
spellcheck='false',
|
spellcheck='false',
|
||||||
type='text'
|
type='text'
|
||||||
)
|
)
|
||||||
.sn-component(ng-if='self.note')
|
.sn-component(ng-if='self.note')
|
||||||
#editor-menu-bar.sk-app-bar.no-edges
|
#editor-menu-bar.sk-app-bar.no-edges
|
||||||
.left
|
.left
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showOptionsMenu', false)`,
|
click-outside=`self.setMenuState('showOptionsMenu', false)`,
|
||||||
is-open='self.state.showOptionsMenu',
|
is-open='self.state.showOptionsMenu',
|
||||||
ng-class="{'selected' : self.state.showOptionsMenu}",
|
ng-class="{'selected' : self.state.showOptionsMenu}",
|
||||||
ng-click="self.toggleMenu('showOptionsMenu')"
|
ng-click="self.toggleMenu('showOptionsMenu')"
|
||||||
)
|
)
|
||||||
.sk-label Options
|
.sk-label Options
|
||||||
@@ -64,182 +64,182 @@
|
|||||||
.sk-menu-panel-header
|
.sk-menu-panel-header
|
||||||
.sk-menu-panel-header-title Note Options
|
.sk-menu-panel-header-title Note Options
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.togglePin()'
|
action='self.selectedMenuItem(true); self.togglePin()'
|
||||||
desc="'Pin or unpin a note from the top of your list'",
|
desc="'Pin or unpin a note from the top of your list'",
|
||||||
label="self.note.pinned ? 'Unpin' : 'Pin'"
|
label="self.note.pinned ? 'Unpin' : 'Pin'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.toggleArchiveNote()'
|
action='self.selectedMenuItem(true); self.toggleArchiveNote()'
|
||||||
desc="'Archive or unarchive a note from your Archived system tag'",
|
desc="'Archive or unarchive a note from your Archived system tag'",
|
||||||
label="self.note.archived ? 'Unarchive' : 'Archive'"
|
label="self.note.archived ? 'Unarchive' : 'Archive'"
|
||||||
)
|
)
|
||||||
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.noteLocked ? 'Unlock' : 'Lock'"
|
label="self.noteLocked ? 'Unlock' : 'Lock'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.toggleProtectNote()'
|
action='self.selectedMenuItem(true); self.toggleProtectNote()'
|
||||||
desc=`'Protecting a note will require credentials to view
|
desc=`'Protecting a note will require credentials to view
|
||||||
it (Manage Privileges via Account menu)'`,
|
it (Manage Privileges via Account menu)'`,
|
||||||
label="self.note.protected ? 'Unprotect' : 'Protect'"
|
label="self.note.protected ? 'Unprotect' : 'Protect'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.toggleNotePreview()'
|
action='self.selectedMenuItem(true); self.toggleNotePreview()'
|
||||||
circle="self.note.hidePreview ? 'danger' : 'success'",
|
circle="self.note.hidePreview ? 'danger' : 'success'",
|
||||||
circle-align="'right'",
|
circle-align="'right'",
|
||||||
desc="'Hide or unhide the note preview from the list of notes'",
|
desc="'Hide or unhide the note preview from the list of notes'",
|
||||||
label="'Preview'"
|
label="'Preview'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(); self.deleteNote()'
|
action='self.selectedMenuItem(); self.deleteNote()'
|
||||||
desc="'Send this note to the trash'",
|
desc="'Send this note to the trash'",
|
||||||
label="'Move to Trash'",
|
label="'Move to Trash'",
|
||||||
ng-show='!self.state.altKeyDown && !self.note.trashed && !self.note.errorDecrypting',
|
ng-show='!self.state.altKeyDown && !self.note.trashed && !self.note.errorDecrypting',
|
||||||
stylekit-class="'warning'"
|
stylekit-class="'warning'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(); self.deleteNotePermanantely()'
|
action='self.selectedMenuItem(); self.deleteNotePermanantely()'
|
||||||
desc="'Delete this note permanently from all your devices'",
|
desc="'Delete this note permanently from all your devices'",
|
||||||
label="'Delete Permanently'",
|
label="'Delete Permanently'",
|
||||||
ng-show='!self.note.trashed && self.note.errorDecrypting',
|
ng-show='!self.note.trashed && self.note.errorDecrypting',
|
||||||
stylekit-class="'danger'"
|
stylekit-class="'danger'"
|
||||||
)
|
)
|
||||||
div(ng-if='self.note.trashed || self.state.altKeyDown')
|
div(ng-if='self.note.trashed || self.state.altKeyDown')
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.restoreTrashedNote()'
|
action='self.selectedMenuItem(true); self.restoreTrashedNote()'
|
||||||
desc="'Undelete this note and restore it back into your notes'",
|
desc="'Undelete this note and restore it back into your notes'",
|
||||||
label="'Restore'",
|
label="'Restore'",
|
||||||
ng-show='self.note.trashed',
|
ng-show='self.note.trashed',
|
||||||
stylekit-class="'info'"
|
stylekit-class="'info'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.deleteNotePermanantely()'
|
action='self.selectedMenuItem(true); self.deleteNotePermanantely()'
|
||||||
desc="'Delete this note permanently from all your devices'",
|
desc="'Delete this note permanently from all your devices'",
|
||||||
label="'Delete Permanently'",
|
label="'Delete Permanently'",
|
||||||
stylekit-class="'danger'"
|
stylekit-class="'danger'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action='self.selectedMenuItem(true); self.emptyTrash()'
|
action='self.selectedMenuItem(true); self.emptyTrash()'
|
||||||
desc="'Permanently delete all notes in the trash'",
|
desc="'Permanently delete all notes in the trash'",
|
||||||
label="'Empty Trash'",
|
label="'Empty Trash'",
|
||||||
ng-show='self.note.trashed || !self.state.altKeyDown',
|
ng-show='self.note.trashed || !self.state.altKeyDown',
|
||||||
stylekit-class="'danger'",
|
stylekit-class="'danger'",
|
||||||
subtitle="self.getTrashCount() + ' notes in trash'"
|
subtitle="self.getTrashCount() + ' notes in trash'"
|
||||||
)
|
)
|
||||||
.sk-menu-panel-section
|
.sk-menu-panel-section
|
||||||
.sk-menu-panel-header
|
.sk-menu-panel-header
|
||||||
.sk-menu-panel-header-title Global Display
|
.sk-menu-panel-header-title Global Display
|
||||||
menu-row(
|
menu-row(
|
||||||
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMonospace)"
|
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMonospace)"
|
||||||
circle="self.state.monospaceFont ? 'success' : 'neutral'",
|
circle="self.state.monospaceFont ? 'success' : 'neutral'",
|
||||||
desc="'Toggles the font style for the default editor'",
|
desc="'Toggles the font style for the default editor'",
|
||||||
disabled='self.activeEditorComponent',
|
disabled='self.activeEditorComponent',
|
||||||
label="'Monospace Font'",
|
label="'Monospace Font'",
|
||||||
subtitle="self.activeEditorComponent ? 'Not available with editor extensions' : null"
|
subtitle="self.activeEditorComponent ? 'Not available with editor extensions' : null"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeySpellcheck)"
|
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeySpellcheck)"
|
||||||
circle="self.state.spellcheck ? 'success' : 'neutral'",
|
circle="self.state.spellcheck ? 'success' : 'neutral'",
|
||||||
desc="'Toggles spellcheck for the default editor'",
|
desc="'Toggles spellcheck for the default editor'",
|
||||||
disabled='self.activeEditorComponent',
|
disabled='self.activeEditorComponent',
|
||||||
label="'Spellcheck'",
|
label="'Spellcheck'",
|
||||||
subtitle=`
|
subtitle=`
|
||||||
self.activeEditorComponent
|
self.activeEditorComponent
|
||||||
? 'Not available with editor extensions'
|
? 'Not available with editor extensions'
|
||||||
: (self.state.isDesktop ? 'May degrade editor performance' : null)
|
: (self.state.isDesktop ? 'May degrade editor performance' : null)
|
||||||
`)
|
`)
|
||||||
menu-row(
|
menu-row(
|
||||||
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMarginResizers)"
|
action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMarginResizers)"
|
||||||
circle="self.state.marginResizersEnabled ? 'success' : 'neutral'",
|
circle="self.state.marginResizersEnabled ? 'success' : 'neutral'",
|
||||||
desc="'Allows for editor left and right margins to be resized'",
|
desc="'Allows for editor left and right margins to be resized'",
|
||||||
faded='!self.state.marginResizersEnabled',
|
faded='!self.state.marginResizersEnabled',
|
||||||
label="'Margin Resizers'"
|
label="'Margin Resizers'"
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showEditorMenu', false)`
|
click-outside=`self.setMenuState('showEditorMenu', false)`
|
||||||
is-open='self.state.showEditorMenu',
|
is-open='self.state.showEditorMenu',
|
||||||
ng-class="{'selected' : self.state.showEditorMenu}",
|
ng-class="{'selected' : self.state.showEditorMenu}",
|
||||||
ng-click="self.toggleMenu('showEditorMenu')"
|
ng-click="self.toggleMenu('showEditorMenu')"
|
||||||
)
|
)
|
||||||
.sk-label Editor
|
.sk-label Editor
|
||||||
editor-menu(
|
editor-menu(
|
||||||
callback='self.editorMenuOnSelect',
|
callback='self.editorMenuOnSelect',
|
||||||
current-item='self.note',
|
current-item='self.note',
|
||||||
ng-if='self.state.showEditorMenu',
|
ng-if='self.state.showEditorMenu',
|
||||||
selected-editor-uuid='self.activeEditorComponent && self.activeEditorComponent.uuid',
|
selected-editor-uuid='self.activeEditorComponent && self.activeEditorComponent.uuid',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showExtensions', false)`,
|
click-outside=`self.setMenuState('showExtensions', false)`,
|
||||||
is-open='self.state.showExtensions',
|
is-open='self.state.showExtensions',
|
||||||
ng-class="{'selected' : self.state.showExtensions}",
|
ng-class="{'selected' : self.state.showExtensions}",
|
||||||
ng-click="self.toggleMenu('showExtensions')"
|
ng-click="self.toggleMenu('showExtensions')"
|
||||||
)
|
)
|
||||||
.sk-label Actions
|
.sk-label Actions
|
||||||
actions-menu(
|
actions-menu(
|
||||||
item='self.note',
|
item='self.note',
|
||||||
ng-if='self.state.showExtensions',
|
ng-if='self.state.showExtensions',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
click-outside=`self.setMenuState('showSessionHistory', false)`,
|
click-outside=`self.setMenuState('showSessionHistory', false)`,
|
||||||
is-open='self.state.showSessionHistory',
|
is-open='self.state.showSessionHistory',
|
||||||
ng-click="self.toggleMenu('showSessionHistory')"
|
ng-click="self.toggleMenu('showSessionHistory')"
|
||||||
)
|
)
|
||||||
.sk-label Session History
|
.sk-label Session History
|
||||||
session-history-menu(
|
session-history-menu(
|
||||||
item='self.note',
|
item='self.note',
|
||||||
ng-if='self.state.showSessionHistory',
|
ng-if='self.state.showSessionHistory',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
#editor-content.editor-content(ng-if='!self.note.errorDecrypting')
|
#editor-content.editor-content(ng-if='!self.note.errorDecrypting')
|
||||||
panel-resizer.left(
|
panel-resizer.left(
|
||||||
control='self.leftPanelPuppet',
|
control='self.leftPanelPuppet',
|
||||||
hoverable='true',
|
hoverable='true',
|
||||||
min-width='300',
|
min-width='300',
|
||||||
ng-if='self.state.marginResizersEnabled',
|
ng-if='self.state.marginResizersEnabled',
|
||||||
on-resize-finish='self.onPanelResizeFinish',
|
on-resize-finish='self.onPanelResizeFinish',
|
||||||
panel-id="'editor-content'",
|
panel-id="'editor-content'",
|
||||||
property="'left'"
|
property="'left'"
|
||||||
)
|
)
|
||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component-uuid='self.activeEditorComponent.uuid',
|
component-uuid='self.activeEditorComponent.uuid',
|
||||||
ng-if='self.activeEditorComponent && !self.state.editorComponentUnloading',
|
ng-if='self.activeEditorComponent && !self.state.editorComponentUnloading',
|
||||||
on-load='self.onEditorLoad',
|
on-load='self.onEditorLoad',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
textarea#note-text-editor.editable(
|
textarea#note-text-editor.editable(
|
||||||
dir='auto',
|
dir='auto',
|
||||||
ng-attr-spellcheck='{{self.state.spellcheck}}',
|
ng-attr-spellcheck='{{self.state.spellcheck}}',
|
||||||
ng-change='self.contentChanged()',
|
ng-change='self.contentChanged()',
|
||||||
ng-click='self.clickedTextArea()',
|
ng-click='self.clickedTextArea()',
|
||||||
ng-focus='self.onContentFocus()',
|
ng-focus='self.onContentFocus()',
|
||||||
ng-if='!self.activeEditorComponent && !self.state.textareaUnloading',
|
ng-if='!self.activeEditorComponent && !self.state.textareaUnloading',
|
||||||
ng-model='self.editorValues.text',
|
ng-model='self.editorValues.text',
|
||||||
ng-model-options='{ debounce: self.state.editorDebounce}',
|
ng-model-options='{ debounce: self.state.editorDebounce}',
|
||||||
ng-readonly='self.noteLocked',
|
ng-readonly='self.noteLocked',
|
||||||
ng-trim='false'
|
ng-trim='false'
|
||||||
)
|
)
|
||||||
| {{self.onSystemEditorLoad()}}
|
| {{self.onSystemEditorLoad()}}
|
||||||
panel-resizer(
|
panel-resizer(
|
||||||
control='self.rightPanelPuppet',
|
control='self.rightPanelPuppet',
|
||||||
hoverable='true', min-width='300',
|
hoverable='true', min-width='300',
|
||||||
ng-if='self.state.marginResizersEnabled',
|
ng-if='self.state.marginResizersEnabled',
|
||||||
on-resize-finish='self.onPanelResizeFinish',
|
on-resize-finish='self.onPanelResizeFinish',
|
||||||
panel-id="'editor-content'",
|
panel-id="'editor-content'",
|
||||||
property="'right'"
|
property="'right'"
|
||||||
)
|
)
|
||||||
.section(ng-show='self.note.errorDecrypting')
|
.section(ng-show='self.note.errorDecrypting')
|
||||||
p.medium-padding(style='padding-top: 0 !important;')
|
p.medium-padding(style='padding-top: 0 !important;')
|
||||||
| There was an error decrypting this item. Ensure you are running the
|
| There was an error decrypting this item. Ensure you are running the
|
||||||
| latest version of this app, then sign out and sign back in to try again.
|
| latest version of this app, then sign out and sign back in to try again.
|
||||||
#editor-pane-component-stack(ng-show='self.note')
|
#editor-pane-component-stack(ng-show='self.note')
|
||||||
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='self.state.allStackComponents.length')
|
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='self.state.allStackComponents.length')
|
||||||
.left
|
.left
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
ng-repeat='component in self.state.allStackComponents track by component.uuid'
|
ng-repeat='component in self.state.allStackComponents track by component.uuid'
|
||||||
ng-click='self.toggleStackComponentForCurrentItem(component)',
|
ng-click='self.toggleStackComponentForCurrentItem(component)',
|
||||||
)
|
)
|
||||||
.sk-app-bar-item-column
|
.sk-app-bar-item-column
|
||||||
.sk-circle.small(
|
.sk-circle.small(
|
||||||
@@ -249,9 +249,9 @@
|
|||||||
.sk-label {{component.name}}
|
.sk-label {{component.name}}
|
||||||
.sn-component
|
.sn-component
|
||||||
component-view.component-view.component-stack-item(
|
component-view.component-view.component-stack-item(
|
||||||
ng-repeat='component in self.state.activeStackComponents track by component.uuid',
|
ng-repeat='component in self.state.allStackComponents track by component.uuid',
|
||||||
component-uuid='component.uuid',
|
component-uuid='component.uuid',
|
||||||
manual-dealloc='true',
|
manual-dealloc='true',
|
||||||
ng-show='!self.stackComponentHidden(component)',
|
ng-show='!self.stackComponentHidden(component)',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
ComponentArea,
|
ComponentArea,
|
||||||
ComponentAction,
|
ComponentAction,
|
||||||
WebPrefKey,
|
WebPrefKey,
|
||||||
ComponentMutator
|
ComponentMutator,
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import find from 'lodash/find';
|
import find from 'lodash/find';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
@@ -90,12 +90,11 @@ type EditorValues = {
|
|||||||
tagsInputValue?: string
|
tagsInputValue?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EditorViewScope {
|
function sortAlphabetically(array: SNComponent[]): SNComponent[] {
|
||||||
application: WebApplication
|
return array.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1);
|
||||||
editor: Editor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
class EditorViewCtrl extends PureViewCtrl<{}, EditorState> {
|
||||||
/** Passed through template */
|
/** Passed through template */
|
||||||
readonly application!: WebApplication
|
readonly application!: WebApplication
|
||||||
readonly editor!: Editor
|
readonly editor!: Editor
|
||||||
@@ -210,19 +209,16 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
const currentEditor = this.activeEditorComponent;
|
const currentEditor = this.activeEditorComponent;
|
||||||
const newEditor = this.componentGroup.activeComponentForArea(ComponentArea.Editor);
|
const newEditor = this.componentGroup.activeComponentForArea(ComponentArea.Editor);
|
||||||
if (currentEditor && newEditor && currentEditor.uuid !== newEditor.uuid) {
|
if (currentEditor && newEditor && currentEditor.uuid !== newEditor.uuid) {
|
||||||
/** Unload current component view so that we create a new one,
|
/** Unload current component view so that we create a new one,
|
||||||
* then change the active editor */
|
* then change the active editor */
|
||||||
await this.setEditorState({
|
await this.setState({
|
||||||
editorComponentUnloading: true
|
editorComponentUnloading: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await this.setEditorState({
|
this.setState({
|
||||||
activeEditorComponent: newEditor,
|
activeEditorComponent: newEditor,
|
||||||
activeTagsComponent: this.componentGroup.activeComponentForArea(ComponentArea.NoteTags),
|
activeTagsComponent: this.componentGroup.activeComponentForArea(ComponentArea.NoteTags),
|
||||||
activeStackComponents: this.componentGroup.activeComponentsForArea(ComponentArea.EditorStack)
|
/** Stop unloading, if we were already unloading */
|
||||||
})
|
|
||||||
/** Stop unloading, if we were already unloading */
|
|
||||||
await this.setEditorState({
|
|
||||||
editorComponentUnloading: false
|
editorComponentUnloading: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -237,14 +233,19 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
editorDebounce: EDITOR_DEBOUNCE,
|
editorDebounce: EDITOR_DEBOUNCE,
|
||||||
isDesktop: isDesktopApplication(),
|
isDesktop: isDesktopApplication(),
|
||||||
spellcheck: true,
|
spellcheck: true,
|
||||||
|
syncTakingTooLong: false,
|
||||||
|
showExtensions: false,
|
||||||
|
showOptionsMenu: false,
|
||||||
|
showEditorMenu: false,
|
||||||
|
showSessionHistory: false,
|
||||||
|
altKeyDown: false,
|
||||||
|
noteStatus: undefined,
|
||||||
|
editorComponentUnloading: false,
|
||||||
|
textareaUnloading: false,
|
||||||
mutable: {
|
mutable: {
|
||||||
tagsString: ''
|
tagsString: ''
|
||||||
}
|
}
|
||||||
} as Partial<EditorState>;
|
} as EditorState;
|
||||||
}
|
|
||||||
|
|
||||||
async setEditorState(state: Partial<EditorState>) {
|
|
||||||
return this.setState(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAppLaunch() {
|
async onAppLaunch() {
|
||||||
@@ -263,10 +264,10 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
/** @override */
|
/** @override */
|
||||||
onAppEvent(eventName: ApplicationEvent) {
|
onAppEvent(eventName: ApplicationEvent) {
|
||||||
if (eventName === ApplicationEvent.HighLatencySync) {
|
if (eventName === ApplicationEvent.HighLatencySync) {
|
||||||
this.setEditorState({ syncTakingTooLong: true });
|
this.setState({ syncTakingTooLong: true });
|
||||||
} else if (eventName === ApplicationEvent.CompletedFullSync) {
|
} else if (eventName === ApplicationEvent.CompletedFullSync) {
|
||||||
this.setEditorState({ syncTakingTooLong: false });
|
this.setState({ syncTakingTooLong: false });
|
||||||
const isInErrorState = this.getState().saveError;
|
const isInErrorState = this.state.saveError;
|
||||||
/** if we're still dirty, don't change status, a sync is likely upcoming. */
|
/** if we're still dirty, don't change status, a sync is likely upcoming. */
|
||||||
if (!this.note.dirty && isInErrorState) {
|
if (!this.note.dirty && isInErrorState) {
|
||||||
this.showAllChangesSavedStatus();
|
this.showAllChangesSavedStatus();
|
||||||
@@ -289,11 +290,11 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get activeEditorComponent() {
|
get activeEditorComponent() {
|
||||||
return this.getState().activeEditorComponent;
|
return this.state.activeEditorComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
get activeTagsComponent() {
|
get activeTagsComponent() {
|
||||||
return this.getState().activeTagsComponent;
|
return this.state.activeTagsComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
get componentGroup() {
|
get componentGroup() {
|
||||||
@@ -302,7 +303,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
|
|
||||||
async handleEditorNoteChange() {
|
async handleEditorNoteChange() {
|
||||||
this.cancelPendingSetStatus();
|
this.cancelPendingSetStatus();
|
||||||
await this.setEditorState({
|
await this.setState({
|
||||||
showExtensions: false,
|
showExtensions: false,
|
||||||
showOptionsMenu: false,
|
showOptionsMenu: false,
|
||||||
showEditorMenu: false,
|
showEditorMenu: false,
|
||||||
@@ -322,31 +323,32 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async reloadComponentEditorState() {
|
async reloadComponentEditorState(): Promise<{ editor?: SNComponent, changed: boolean }> {
|
||||||
const associatedEditor = this.application.componentManager!.editorForNote(this.note);
|
const editor = this.application.componentManager!.editorForNote(this.note);
|
||||||
if (!associatedEditor) {
|
if (!editor) {
|
||||||
/** No editor */
|
let changed: boolean;
|
||||||
let changed = false;
|
|
||||||
if (this.activeEditorComponent) {
|
if (this.activeEditorComponent) {
|
||||||
await this.componentGroup.deactivateComponentForArea(ComponentArea.Editor);
|
await this.componentGroup.deactivateComponentForArea(ComponentArea.Editor);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
} else {
|
||||||
|
changed = false;
|
||||||
}
|
}
|
||||||
return { editor: undefined, changed };
|
return { editor, changed };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (associatedEditor.uuid === this.activeEditorComponent?.uuid) {
|
if (editor.uuid === this.activeEditorComponent?.uuid) {
|
||||||
/** Same editor, no change */
|
/** Same editor, no change */
|
||||||
return { editor: associatedEditor, changed: false };
|
return { editor, changed: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.componentGroup.activateComponent(associatedEditor);
|
await this.componentGroup.activateComponent(editor);
|
||||||
return { editor: associatedEditor, changed: true };
|
return { editor, changed: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because note.locked accesses note.content.appData,
|
* Because note.locked accesses note.content.appData,
|
||||||
* we do not want to expose the template to direct access to note.locked,
|
* 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
|
* 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
|
* 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
|
* previous setState call may have queued a digest cycle, and the digest cycle triggers
|
||||||
* on a deleted note.
|
* on a deleted note.
|
||||||
@@ -381,38 +383,39 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
this.removeComponentsObserver = this.application.streamItems(
|
this.removeComponentsObserver = this.application.streamItems(
|
||||||
ContentType.Component,
|
ContentType.Component,
|
||||||
async (items) => {
|
async (items) => {
|
||||||
const components = items as SNComponent[];
|
if (!this.note) return;
|
||||||
if (!this.note) {
|
this.setState({
|
||||||
return;
|
allStackComponents: sortAlphabetically(
|
||||||
}
|
this.application.componentManager!.componentsForArea(ComponentArea.EditorStack)
|
||||||
/** Reload componentStack in case new ones were added or removed */
|
.filter(component => component.active)
|
||||||
await this.reloadComponentStack();
|
)
|
||||||
|
});
|
||||||
|
this.reloadComponentContext();
|
||||||
this.reloadNoteTagsComponent();
|
this.reloadNoteTagsComponent();
|
||||||
/** Observe editor changes to see if the current note should update its editor */
|
/** Observe editor changes to see if the current note should update its editor */
|
||||||
|
const components = items as SNComponent[];
|
||||||
const editors = components.filter((component) => {
|
const editors = components.filter((component) => {
|
||||||
return component.isEditor();
|
return component.isEditor();
|
||||||
});
|
});
|
||||||
if (editors.length === 0) {
|
if (editors.length) {
|
||||||
return;
|
/** Find the most recent editor for note */
|
||||||
}
|
const { editor, changed } = await this.reloadComponentEditorState();
|
||||||
/** Find the most recent editor for note */
|
|
||||||
this.reloadComponentEditorState().then(({ editor, changed }) => {
|
|
||||||
if (!editor && changed) {
|
if (!editor && changed) {
|
||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMenuState(menu: string, state: boolean) {
|
setMenuState(menu: string, state: boolean) {
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
[menu]: state
|
[menu]: state
|
||||||
});
|
});
|
||||||
this.closeAllMenus(menu);
|
this.closeAllMenus(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMenu(menu: string) {
|
toggleMenu(menu: keyof EditorState) {
|
||||||
this.setMenuState(menu, !this.state[menu]);
|
this.setMenuState(menu, !this.state[menu]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +432,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
menuState[candidate] = false;
|
menuState[candidate] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setEditorState(menuState);
|
this.setState(menuState);
|
||||||
}
|
}
|
||||||
|
|
||||||
async editorMenuOnSelect(component?: SNComponent) {
|
async editorMenuOnSelect(component?: SNComponent) {
|
||||||
@@ -490,7 +493,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
* immediately.
|
* immediately.
|
||||||
* @param isUserModified This field determines if the item will be saved as a user
|
* @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
|
* modification, thus updating the user modified date displayed in the UI
|
||||||
* @param dontUpdatePreviews Whether this change should update the note's plain and HTML
|
* @param dontUpdatePreviews Whether this change should update the note's plain and HTML
|
||||||
* preview.
|
* preview.
|
||||||
* @param customMutate A custom mutator function.
|
* @param customMutate A custom mutator function.
|
||||||
* @param closeAfterSync Whether this editor should be closed after the sync starts.
|
* @param closeAfterSync Whether this editor should be closed after the sync starts.
|
||||||
@@ -569,7 +572,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showAllChangesSavedStatus() {
|
showAllChangesSavedStatus() {
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
saveError: false,
|
saveError: false,
|
||||||
syncTakingTooLong: false
|
syncTakingTooLong: false
|
||||||
});
|
});
|
||||||
@@ -585,7 +588,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
desc: "Changes saved offline"
|
desc: "Changes saved offline"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
saveError: true,
|
saveError: true,
|
||||||
syncTakingTooLong: false
|
syncTakingTooLong: false
|
||||||
});
|
});
|
||||||
@@ -609,7 +612,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
this.statusTimeout = this.$timeout(() => {
|
this.statusTimeout = this.$timeout(() => {
|
||||||
status.date = new Date();
|
status.date = new Date();
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
noteStatus: status
|
noteStatus: status
|
||||||
});
|
});
|
||||||
}, waitForMs);
|
}, waitForMs);
|
||||||
@@ -876,7 +879,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
public async saveTagsFromStrings(strings?: string[]) {
|
public async saveTagsFromStrings(strings?: string[]) {
|
||||||
if (
|
if (
|
||||||
!strings
|
!strings
|
||||||
&& this.editorValues.tagsInputValue === this.getState().tagsAsStrings
|
&& this.editorValues.tagsInputValue === this.state.tagsAsStrings
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -965,7 +968,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
WebPrefKey.EditorResizersEnabled,
|
WebPrefKey.EditorResizersEnabled,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
await this.setEditorState({
|
await this.setState({
|
||||||
monospaceFont,
|
monospaceFont,
|
||||||
spellcheck,
|
spellcheck,
|
||||||
marginResizersEnabled
|
marginResizersEnabled
|
||||||
@@ -979,7 +982,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.getState().marginResizersEnabled &&
|
this.state.marginResizersEnabled &&
|
||||||
this.leftPanelPuppet!.ready &&
|
this.leftPanelPuppet!.ready &&
|
||||||
this.rightPanelPuppet!.ready
|
this.rightPanelPuppet!.ready
|
||||||
) {
|
) {
|
||||||
@@ -1009,8 +1012,8 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
if (!editor) {
|
if (!editor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.getState().monospaceFont) {
|
if (this.state.monospaceFont) {
|
||||||
if (this.getState().isDesktop) {
|
if (this.state.isDesktop) {
|
||||||
editor.style.fontFamily = Fonts.DesktopMonospaceFamily;
|
editor.style.fontFamily = Fonts.DesktopMonospaceFamily;
|
||||||
} else {
|
} else {
|
||||||
editor.style.fontFamily = Fonts.WebMonospaceFamily;
|
editor.style.fontFamily = Fonts.WebMonospaceFamily;
|
||||||
@@ -1021,21 +1024,21 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async toggleWebPrefKey(key: WebPrefKey) {
|
async toggleWebPrefKey(key: WebPrefKey) {
|
||||||
const currentValue = this.state[key];
|
const currentValue = (this.state as any)[key];
|
||||||
await this.application.getPrefsService().setUserPrefValue(
|
await this.application.getPrefsService().setUserPrefValue(
|
||||||
key,
|
key,
|
||||||
!currentValue,
|
!currentValue,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
await this.setEditorState({
|
await this.setState({
|
||||||
[key]: !currentValue
|
[key]: !currentValue
|
||||||
})
|
})
|
||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
|
|
||||||
if (key === WebPrefKey.EditorSpellcheck) {
|
if (key === WebPrefKey.EditorSpellcheck) {
|
||||||
/** Allows textarea to reload */
|
/** Allows textarea to reload */
|
||||||
await this.setEditorState({ textareaUnloading: true });
|
await this.setState({ textareaUnloading: true });
|
||||||
await this.setEditorState({ textareaUnloading: false });
|
await this.setState({ textareaUnloading: false });
|
||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
} else if (key === WebPrefKey.EditorResizersEnabled && this.state[key] === true) {
|
} else if (key === WebPrefKey.EditorResizersEnabled && this.state[key] === true) {
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
@@ -1060,7 +1063,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
if (
|
if (
|
||||||
componentUuid === currentEditor?.uuid ||
|
componentUuid === currentEditor?.uuid ||
|
||||||
componentUuid === this.activeTagsComponent?.uuid ||
|
componentUuid === this.activeTagsComponent?.uuid ||
|
||||||
Uuids(this.getState().activeStackComponents).includes(componentUuid)
|
Uuids(this.state.allStackComponents).includes(componentUuid)
|
||||||
) {
|
) {
|
||||||
return this.note;
|
return this.note;
|
||||||
}
|
}
|
||||||
@@ -1128,12 +1131,12 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||||
});
|
});
|
||||||
await this.setEditorState({
|
await this.setState({
|
||||||
allStackComponents: components
|
allStackComponents: components
|
||||||
});
|
});
|
||||||
this.reloadComponentContext();
|
this.reloadComponentContext();
|
||||||
/** component.active is a persisted state. So if we download a stack component
|
/** component.active is a persisted state. So if we download a stack component
|
||||||
* whose .active is true, it doesn't mean it was explicitely activated by us. So
|
* whose .active is true, it doesn't mean it was explicitely activated by us. So
|
||||||
* we need to do that here. */
|
* we need to do that here. */
|
||||||
for (const component of components) {
|
for (const component of components) {
|
||||||
if (component.active) {
|
if (component.active) {
|
||||||
@@ -1144,7 +1147,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
|
|
||||||
reloadComponentContext() {
|
reloadComponentContext() {
|
||||||
if (this.note) {
|
if (this.note) {
|
||||||
for (const component of this.getState().allStackComponents!) {
|
for (const component of this.state.allStackComponents!) {
|
||||||
if (component.active) {
|
if (component.active) {
|
||||||
this.application.componentManager!.setComponentHidden(
|
this.application.componentManager!.setComponentHidden(
|
||||||
component,
|
component,
|
||||||
@@ -1203,12 +1206,12 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
KeyboardModifier.Alt
|
KeyboardModifier.Alt
|
||||||
],
|
],
|
||||||
onKeyDown: () => {
|
onKeyDown: () => {
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
altKeyDown: true
|
altKeyDown: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onKeyUp: () => {
|
onKeyUp: () => {
|
||||||
this.setEditorState({
|
this.setState({
|
||||||
altKeyDown: false
|
altKeyDown: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user