Merge branch 'release/10.5.0'
This commit is contained in:
@@ -30,8 +30,8 @@ import { AccountSwitcher } from './views/account_switcher/account_switcher';
|
|||||||
import {
|
import {
|
||||||
ApplicationGroupView,
|
ApplicationGroupView,
|
||||||
ApplicationView,
|
ApplicationView,
|
||||||
EditorGroupView,
|
NoteGroupViewDirective,
|
||||||
EditorView,
|
NoteViewDirective,
|
||||||
TagsView,
|
TagsView,
|
||||||
FooterView,
|
FooterView,
|
||||||
ChallengeModal,
|
ChallengeModal,
|
||||||
@@ -141,8 +141,8 @@ const startApplication: StartApplication = async function startApplication(
|
|||||||
.module('app')
|
.module('app')
|
||||||
.directive('applicationGroupView', () => new ApplicationGroupView())
|
.directive('applicationGroupView', () => new ApplicationGroupView())
|
||||||
.directive('applicationView', () => new ApplicationView())
|
.directive('applicationView', () => new ApplicationView())
|
||||||
.directive('editorGroupView', () => new EditorGroupView())
|
.directive('noteGroupView', () => new NoteGroupViewDirective())
|
||||||
.directive('editorView', () => new EditorView())
|
.directive('noteView', () => new NoteViewDirective())
|
||||||
.directive('tagsView', () => new TagsView())
|
.directive('tagsView', () => new TagsView())
|
||||||
.directive('footerView', () => new FooterView());
|
.directive('footerView', () => new FooterView());
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Bridge } from '@/services/bridge';
|
|||||||
import { storage, StorageKey } from '@/services/localStorage';
|
import { storage, StorageKey } from '@/services/localStorage';
|
||||||
import { WebApplication } from '@/ui_models/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { AccountMenuState } from '@/ui_models/app_state/account_menu_state';
|
import { AccountMenuState } from '@/ui_models/app_state/account_menu_state';
|
||||||
import { Editor } from '@/ui_models/editor';
|
import { NoteViewController } from '@/views/note_view/note_view_controller';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import {
|
import {
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
@@ -226,9 +226,9 @@ export class AppState {
|
|||||||
storage.set(StorageKey.ShowBetaWarning, true);
|
storage.set(StorageKey.ShowBetaWarning, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createEditor(title?: string) {
|
async openNewNote(title?: string) {
|
||||||
if (!this.multiEditorSupport) {
|
if (!this.multiEditorSupport) {
|
||||||
this.closeActiveEditor();
|
this.closeActiveNoteController();
|
||||||
}
|
}
|
||||||
const activeTagUuid = this.selectedTag
|
const activeTagUuid = this.selectedTag
|
||||||
? this.selectedTag.isSmartTag
|
? this.selectedTag.isSmartTag
|
||||||
@@ -236,37 +236,37 @@ export class AppState {
|
|||||||
: this.selectedTag.uuid
|
: this.selectedTag.uuid
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
await this.application.editorGroup.createEditor(
|
await this.application.noteControllerGroup.createNoteView(
|
||||||
undefined,
|
undefined,
|
||||||
title,
|
title,
|
||||||
activeTagUuid
|
activeTagUuid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getActiveEditor() {
|
getActiveNoteController() {
|
||||||
return this.application.editorGroup.editors[0];
|
return this.application.noteControllerGroup.noteControllers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditors() {
|
getNoteControllers() {
|
||||||
return this.application.editorGroup.editors;
|
return this.application.noteControllerGroup.noteControllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeEditor(editor: Editor) {
|
closeNoteController(controller: NoteViewController) {
|
||||||
this.application.editorGroup.closeEditor(editor);
|
this.application.noteControllerGroup.closeNoteView(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeActiveEditor() {
|
closeActiveNoteController() {
|
||||||
this.application.editorGroup.closeActiveEditor();
|
this.application.noteControllerGroup.closeActiveNoteView();
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAllEditors() {
|
closeAllNoteControllers() {
|
||||||
this.application.editorGroup.closeAllEditors();
|
this.application.noteControllerGroup.closeAllNoteViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
editorForNote(note: SNNote) {
|
noteControllerForNote(note: SNNote) {
|
||||||
for (const editor of this.getEditors()) {
|
for (const controller of this.getNoteControllers()) {
|
||||||
if (editor.note.uuid === note.uuid) {
|
if (controller.note.uuid === note.uuid) {
|
||||||
return editor;
|
return controller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,31 +275,31 @@ export class AppState {
|
|||||||
this.application.streamItems(
|
this.application.streamItems(
|
||||||
[ContentType.Note, ContentType.Tag],
|
[ContentType.Note, ContentType.Tag],
|
||||||
async (items, source) => {
|
async (items, source) => {
|
||||||
/** Close any editors for deleted/trashed/archived notes */
|
/** Close any note controllers for deleted/trashed/archived notes */
|
||||||
if (source === PayloadSource.PreSyncSave) {
|
if (source === PayloadSource.PreSyncSave) {
|
||||||
const notes = items.filter(
|
const notes = items.filter(
|
||||||
(candidate) => candidate.content_type === ContentType.Note
|
(candidate) => candidate.content_type === ContentType.Note
|
||||||
) as SNNote[];
|
) as SNNote[];
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
const editor = this.editorForNote(note);
|
const noteController = this.noteControllerForNote(note);
|
||||||
if (!editor) {
|
if (!noteController) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (note.deleted) {
|
if (note.deleted) {
|
||||||
this.closeEditor(editor);
|
this.closeNoteController(noteController);
|
||||||
} else if (
|
} else if (
|
||||||
note.trashed &&
|
note.trashed &&
|
||||||
!this.selectedTag?.isTrashTag &&
|
!this.selectedTag?.isTrashTag &&
|
||||||
!this.searchOptions.includeTrashed
|
!this.searchOptions.includeTrashed
|
||||||
) {
|
) {
|
||||||
this.closeEditor(editor);
|
this.closeNoteController(noteController);
|
||||||
} else if (
|
} else if (
|
||||||
note.archived &&
|
note.archived &&
|
||||||
!this.selectedTag?.isArchiveTag &&
|
!this.selectedTag?.isArchiveTag &&
|
||||||
!this.searchOptions.includeArchived &&
|
!this.searchOptions.includeArchived &&
|
||||||
!this.application.getPreference(PrefKey.NotesShowArchived, false)
|
!this.application.getPreference(PrefKey.NotesShowArchived, false)
|
||||||
) {
|
) {
|
||||||
this.closeEditor(editor);
|
this.closeNoteController(noteController);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export class NoteTagsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get activeNote(): SNNote | undefined {
|
get activeNote(): SNNote | undefined {
|
||||||
return this.appState.notes.activeEditor?.note;
|
return this.appState.notes.activeNoteController?.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
get autocompleteTagHintVisible(): boolean {
|
get autocompleteTagHintVisible(): boolean {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
runInAction,
|
runInAction,
|
||||||
} from 'mobx';
|
} from 'mobx';
|
||||||
import { WebApplication } from '../application';
|
import { WebApplication } from '../application';
|
||||||
import { Editor } from '../editor';
|
import { NoteViewController } from '@/views/note_view/note_view_controller';
|
||||||
import { AppState } from './app_state';
|
import { AppState } from './app_state';
|
||||||
|
|
||||||
export class NotesState {
|
export class NotesState {
|
||||||
@@ -68,8 +68,8 @@ export class NotesState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get activeEditor(): Editor | undefined {
|
get activeNoteController(): NoteViewController | undefined {
|
||||||
return this.application.editorGroup.editors[0];
|
return this.application.noteControllerGroup.noteControllers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedNotesCount(): number {
|
get selectedNotesCount(): number {
|
||||||
@@ -151,13 +151,13 @@ export class NotesState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedNotesCount === 1) {
|
if (this.selectedNotesCount === 1) {
|
||||||
await this.openEditor(Object.keys(this.selectedNotes)[0]);
|
await this.openNote(Object.keys(this.selectedNotes)[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async openEditor(noteUuid: string): Promise<void> {
|
private async openNote(noteUuid: string): Promise<void> {
|
||||||
if (this.activeEditor?.note?.uuid === noteUuid) {
|
if (this.activeNoteController?.note?.uuid === noteUuid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ export class NotesState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.activeEditor) {
|
if (this.activeNoteController) {
|
||||||
this.application.editorGroup.closeActiveEditor();
|
this.application.noteControllerGroup.closeActiveNoteView();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.application.editorGroup.createEditor(noteUuid);
|
await this.application.noteControllerGroup.createNoteView(noteUuid);
|
||||||
|
|
||||||
this.appState.noteTags.reloadTags();
|
this.appState.noteTags.reloadTags();
|
||||||
await this.onActiveEditorChanged();
|
await this.onActiveEditorChanged();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class NotesViewState {
|
|||||||
appObservers.push(
|
appObservers.push(
|
||||||
application.streamItems(ContentType.Note, () => {
|
application.streamItems(ContentType.Note, () => {
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
const activeNote = this.appState.notes.activeEditor?.note;
|
const activeNote = this.appState.notes.activeNoteController?.note;
|
||||||
if (this.application.getAppState().notes.selectedNotesCount < 2) {
|
if (this.application.getAppState().notes.selectedNotesCount < 2) {
|
||||||
if (activeNote) {
|
if (activeNote) {
|
||||||
const discarded = activeNote.deleted || activeNote.trashed;
|
const discarded = activeNote.deleted || activeNote.trashed;
|
||||||
@@ -102,7 +102,7 @@ export class NotesViewState {
|
|||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
}, ApplicationEvent.PreferencesChanged),
|
}, ApplicationEvent.PreferencesChanged),
|
||||||
application.addEventObserver(async () => {
|
application.addEventObserver(async () => {
|
||||||
this.appState.closeAllEditors();
|
this.appState.closeAllNoteControllers();
|
||||||
this.selectFirstNote();
|
this.selectFirstNote();
|
||||||
this.setCompletedFullSync(false);
|
this.setCompletedFullSync(false);
|
||||||
}, ApplicationEvent.SignedIn),
|
}, ApplicationEvent.SignedIn),
|
||||||
@@ -111,7 +111,8 @@ export class NotesViewState {
|
|||||||
if (
|
if (
|
||||||
this.notes.length === 0 &&
|
this.notes.length === 0 &&
|
||||||
this.appState.selectedTag?.isAllTag &&
|
this.appState.selectedTag?.isAllTag &&
|
||||||
this.noteFilterText === ''
|
this.noteFilterText === '' &&
|
||||||
|
!this.appState.notes.activeNoteController
|
||||||
) {
|
) {
|
||||||
this.createPlaceholderNote();
|
this.createPlaceholderNote();
|
||||||
}
|
}
|
||||||
@@ -191,7 +192,7 @@ export class NotesViewState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get activeEditorNote() {
|
get activeEditorNote() {
|
||||||
return this.appState.notes.activeEditor?.note;
|
return this.appState.notes.activeNoteController?.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPanelTitle = () => {
|
reloadPanelTitle = () => {
|
||||||
@@ -318,19 +319,15 @@ export class NotesViewState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
createNewNote = async (focusNewNote = true) => {
|
createNewNote = async () => {
|
||||||
this.appState.notes.unselectNotes();
|
this.appState.notes.unselectNotes();
|
||||||
let title = `Note ${this.notes.length + 1}`;
|
let title = `Note ${this.notes.length + 1}`;
|
||||||
if (this.isFiltering) {
|
if (this.isFiltering) {
|
||||||
title = this.noteFilterText;
|
title = this.noteFilterText;
|
||||||
}
|
}
|
||||||
await this.appState.createEditor(title);
|
await this.appState.openNewNote(title);
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
this.appState.noteTags.reloadTags();
|
this.appState.noteTags.reloadTags();
|
||||||
const noteTitleEditorElement = document.getElementById('note-title-editor');
|
|
||||||
if (focusNewNote) {
|
|
||||||
noteTitleEditorElement?.focus();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
createPlaceholderNote = () => {
|
createPlaceholderNote = () => {
|
||||||
@@ -338,7 +335,7 @@ export class NotesViewState {
|
|||||||
if (selectedTag && selectedTag.isSmartTag && !selectedTag.isAllTag) {
|
if (selectedTag && selectedTag.isSmartTag && !selectedTag.isAllTag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.createNewNote(false);
|
return this.createNewNote();
|
||||||
};
|
};
|
||||||
|
|
||||||
get optionsSubtitle(): string {
|
get optionsSubtitle(): string {
|
||||||
@@ -436,7 +433,7 @@ export class NotesViewState {
|
|||||||
if (note) {
|
if (note) {
|
||||||
this.selectNote(note, false, false);
|
this.selectNote(note, false, false);
|
||||||
} else {
|
} else {
|
||||||
this.appState.closeActiveEditor();
|
this.appState.closeActiveNoteController();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -467,7 +464,7 @@ export class NotesViewState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleEditorChange = async () => {
|
handleEditorChange = async () => {
|
||||||
const activeNote = this.appState.getActiveEditor()?.note;
|
const activeNote = this.appState.getActiveNoteController()?.note;
|
||||||
if (activeNote && activeNote.conflictOf) {
|
if (activeNote && activeNote.conflictOf) {
|
||||||
this.application.changeAndSaveItem(activeNote.uuid, (mutator) => {
|
this.application.changeAndSaveItem(activeNote.uuid, (mutator) => {
|
||||||
mutator.conflictOf = undefined;
|
mutator.conflictOf = undefined;
|
||||||
@@ -505,7 +502,7 @@ export class NotesViewState {
|
|||||||
this.activeEditorNote &&
|
this.activeEditorNote &&
|
||||||
!this.notes.includes(this.activeEditorNote)
|
!this.notes.includes(this.activeEditorNote)
|
||||||
) {
|
) {
|
||||||
this.appState.closeActiveEditor();
|
this.appState.closeActiveNoteController();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { StatusManager } from '@/services/statusManager';
|
|||||||
import { ThemeManager } from '@/services/themeManager';
|
import { ThemeManager } from '@/services/themeManager';
|
||||||
import { PasswordWizardScope, PasswordWizardType } from '@/types';
|
import { PasswordWizardScope, PasswordWizardType } from '@/types';
|
||||||
import { AppState } from '@/ui_models/app_state';
|
import { AppState } from '@/ui_models/app_state';
|
||||||
import { EditorGroup } from '@/ui_models/editor_group';
|
import { NoteGroupController } from '@/views/note_group_view/note_group_controller';
|
||||||
import { AppVersion } from '@/version';
|
import { AppVersion } from '@/version';
|
||||||
import { WebDeviceInterface } from '@/web_device_interface';
|
import { WebDeviceInterface } from '@/web_device_interface';
|
||||||
import {
|
import {
|
||||||
@@ -36,7 +36,7 @@ export class WebApplication extends SNApplication {
|
|||||||
private scope?: angular.IScope;
|
private scope?: angular.IScope;
|
||||||
private webServices!: WebServices;
|
private webServices!: WebServices;
|
||||||
private currentAuthenticationElement?: angular.IRootElementService;
|
private currentAuthenticationElement?: angular.IRootElementService;
|
||||||
public editorGroup: EditorGroup;
|
public noteControllerGroup: NoteGroupController;
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
@@ -66,7 +66,7 @@ export class WebApplication extends SNApplication {
|
|||||||
this.$compile = $compile;
|
this.$compile = $compile;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
deviceInterface.setApplication(this);
|
deviceInterface.setApplication(this);
|
||||||
this.editorGroup = new EditorGroup(this);
|
this.noteControllerGroup = new NoteGroupController(this);
|
||||||
this.presentPermissionsDialog = this.presentPermissionsDialog.bind(this);
|
this.presentPermissionsDialog = this.presentPermissionsDialog.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ export class WebApplication extends SNApplication {
|
|||||||
}
|
}
|
||||||
this.webServices = {} as WebServices;
|
this.webServices = {} as WebServices;
|
||||||
(this.$compile as unknown) = undefined;
|
(this.$compile as unknown) = undefined;
|
||||||
this.editorGroup.deinit();
|
this.noteControllerGroup.deinit();
|
||||||
(this.scope as any).application = undefined;
|
(this.scope as any).application = undefined;
|
||||||
this.scope!.$destroy();
|
this.scope!.$destroy();
|
||||||
this.scope = undefined;
|
this.scope = undefined;
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
import { removeFromArray, UuidString } from '@standardnotes/snjs';
|
|
||||||
import { Editor } from './editor';
|
|
||||||
import { WebApplication } from './application';
|
|
||||||
|
|
||||||
type EditorGroupChangeCallback = () => void;
|
|
||||||
|
|
||||||
export class EditorGroup {
|
|
||||||
public editors: Editor[] = [];
|
|
||||||
private application: WebApplication;
|
|
||||||
changeObservers: EditorGroupChangeCallback[] = [];
|
|
||||||
|
|
||||||
constructor(application: WebApplication) {
|
|
||||||
this.application = application;
|
|
||||||
}
|
|
||||||
|
|
||||||
public deinit() {
|
|
||||||
(this.application as unknown) = undefined;
|
|
||||||
for (const editor of this.editors) {
|
|
||||||
this.deleteEditor(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async createEditor(
|
|
||||||
noteUuid?: string,
|
|
||||||
noteTitle?: string,
|
|
||||||
noteTag?: UuidString
|
|
||||||
) {
|
|
||||||
const editor = new Editor(this.application, noteUuid, noteTitle, noteTag);
|
|
||||||
await editor.initialize();
|
|
||||||
this.editors.push(editor);
|
|
||||||
this.notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteEditor(editor: Editor) {
|
|
||||||
editor.deinit();
|
|
||||||
removeFromArray(this.editors, editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
closeEditor(editor: Editor) {
|
|
||||||
this.deleteEditor(editor);
|
|
||||||
this.notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
closeActiveEditor() {
|
|
||||||
const activeEditor = this.activeEditor;
|
|
||||||
if (activeEditor) {
|
|
||||||
this.deleteEditor(activeEditor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closeAllEditors() {
|
|
||||||
for (const editor of this.editors) {
|
|
||||||
this.deleteEditor(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get activeEditor() {
|
|
||||||
return this.editors[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies observer when the active editor has changed.
|
|
||||||
*/
|
|
||||||
public addChangeObserver(callback: EditorGroupChangeCallback) {
|
|
||||||
this.changeObservers.push(callback);
|
|
||||||
if (this.activeEditor) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
removeFromArray(this.changeObservers, callback);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private notifyObservers() {
|
|
||||||
for (const observer of this.changeObservers) {
|
|
||||||
observer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
application='self.application'
|
application='self.application'
|
||||||
app-state='self.appState'
|
app-state='self.appState'
|
||||||
)
|
)
|
||||||
editor-group-view.flex-grow(application='self.application')
|
note-group-view.flex-grow(application='self.application')
|
||||||
|
|
||||||
footer-view(
|
footer-view(
|
||||||
ng-if='!self.state.needsUnlock && self.state.launched'
|
ng-if='!self.state.needsUnlock && self.state.launched'
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { WebDirective } from './../../types';
|
|
||||||
import template from './editor-group-view.pug';
|
|
||||||
import { Editor } from '@/ui_models/editor';
|
|
||||||
import { PureViewCtrl } from '../abstract/pure_view_ctrl';
|
|
||||||
|
|
||||||
class EditorGroupViewCtrl extends PureViewCtrl<unknown, {
|
|
||||||
showMultipleSelectedNotes: boolean
|
|
||||||
}> {
|
|
||||||
|
|
||||||
public editors: Editor[] = []
|
|
||||||
|
|
||||||
/* @ngInject */
|
|
||||||
constructor($timeout: ng.ITimeoutService,) {
|
|
||||||
super($timeout);
|
|
||||||
this.state = {
|
|
||||||
showMultipleSelectedNotes: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this.application.editorGroup.addChangeObserver(() => {
|
|
||||||
this.editors = this.application.editorGroup.editors;
|
|
||||||
});
|
|
||||||
this.autorun(() => {
|
|
||||||
this.setState({
|
|
||||||
showMultipleSelectedNotes: this.appState.notes.selectedNotesCount > 1
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EditorGroupView extends WebDirective {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.template = template;
|
|
||||||
this.controller = EditorGroupViewCtrl;
|
|
||||||
this.controllerAs = 'self';
|
|
||||||
this.bindToController = true;
|
|
||||||
this.scope = {
|
|
||||||
application: '='
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
export { PureViewCtrl } from './abstract/pure_view_ctrl';
|
export { PureViewCtrl } from './abstract/pure_view_ctrl';
|
||||||
export { ApplicationGroupView } from './application_group/application_group_view';
|
export { ApplicationGroupView } from './application_group/application_group_view';
|
||||||
export { ApplicationView } from './application/application_view';
|
export { ApplicationView } from './application/application_view';
|
||||||
export { EditorGroupView } from './editor_group/editor_group_view';
|
export { NoteGroupViewDirective } from './note_group_view/note_group_view';
|
||||||
export { EditorView } from './editor/editor_view';
|
export { NoteViewDirective } from './note_view/note_view';
|
||||||
export { FooterView } from './footer/footer_view';
|
export { FooterView } from './footer/footer_view';
|
||||||
export { TagsView } from './tags/tags_view';
|
export { TagsView } from './tags/tags_view';
|
||||||
export { ChallengeModal } from './challenge_modal/challenge_modal';
|
export { ChallengeModal } from './challenge_modal/challenge_modal';
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
)
|
)
|
||||||
.flex-grow.h-full(
|
.flex-grow.h-full(
|
||||||
ng-if='!self.state.showMultipleSelectedNotes'
|
ng-if='!self.state.showMultipleSelectedNotes'
|
||||||
ng-repeat='editor in self.editors'
|
ng-repeat='controller in self.controllers'
|
||||||
)
|
)
|
||||||
editor-view(
|
note-view(
|
||||||
application='self.application'
|
application='self.application'
|
||||||
editor='editor'
|
controller='controller'
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { removeFromArray, UuidString } from '@standardnotes/snjs';
|
||||||
|
import { NoteViewController } from '@/views/note_view/note_view_controller';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
|
||||||
|
type NoteControllerGroupChangeCallback = () => void;
|
||||||
|
|
||||||
|
export class NoteGroupController {
|
||||||
|
public noteControllers: NoteViewController[] = [];
|
||||||
|
private application: WebApplication;
|
||||||
|
changeObservers: NoteControllerGroupChangeCallback[] = [];
|
||||||
|
|
||||||
|
constructor(application: WebApplication) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
|
||||||
|
public deinit() {
|
||||||
|
(this.application as unknown) = undefined;
|
||||||
|
for (const controller of this.noteControllers) {
|
||||||
|
this.deleteNoteView(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createNoteView(
|
||||||
|
noteUuid?: string,
|
||||||
|
noteTitle?: string,
|
||||||
|
noteTag?: UuidString
|
||||||
|
) {
|
||||||
|
const controller = new NoteViewController(
|
||||||
|
this.application,
|
||||||
|
noteUuid,
|
||||||
|
noteTitle,
|
||||||
|
noteTag
|
||||||
|
);
|
||||||
|
await controller.initialize();
|
||||||
|
this.noteControllers.push(controller);
|
||||||
|
this.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNoteView(controller: NoteViewController) {
|
||||||
|
controller.deinit();
|
||||||
|
removeFromArray(this.noteControllers, controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeNoteView(controller: NoteViewController) {
|
||||||
|
this.deleteNoteView(controller);
|
||||||
|
this.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeActiveNoteView() {
|
||||||
|
const activeController = this.activeNoteViewController;
|
||||||
|
if (activeController) {
|
||||||
|
this.deleteNoteView(activeController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAllNoteViews() {
|
||||||
|
for (const controller of this.noteControllers) {
|
||||||
|
this.deleteNoteView(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeNoteViewController() {
|
||||||
|
return this.noteControllers[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies observer when the active controller has changed.
|
||||||
|
*/
|
||||||
|
public addChangeObserver(callback: NoteControllerGroupChangeCallback) {
|
||||||
|
this.changeObservers.push(callback);
|
||||||
|
if (this.activeNoteViewController) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
removeFromArray(this.changeObservers, callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifyObservers() {
|
||||||
|
for (const observer of this.changeObservers) {
|
||||||
|
observer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { WebDirective } from './../../types';
|
||||||
|
import template from './note-group-view.pug';
|
||||||
|
import { NoteViewController } from '@/views/note_view/note_view_controller';
|
||||||
|
import { PureViewCtrl } from '../abstract/pure_view_ctrl';
|
||||||
|
|
||||||
|
class NoteGroupView extends PureViewCtrl<
|
||||||
|
unknown,
|
||||||
|
{
|
||||||
|
showMultipleSelectedNotes: boolean;
|
||||||
|
}
|
||||||
|
> {
|
||||||
|
public controllers: NoteViewController[] = [];
|
||||||
|
|
||||||
|
/* @ngInject */
|
||||||
|
constructor($timeout: ng.ITimeoutService) {
|
||||||
|
super($timeout);
|
||||||
|
this.state = {
|
||||||
|
showMultipleSelectedNotes: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.application.noteControllerGroup.addChangeObserver(() => {
|
||||||
|
this.controllers = this.application.noteControllerGroup.noteControllers;
|
||||||
|
});
|
||||||
|
this.autorun(() => {
|
||||||
|
this.setState({
|
||||||
|
showMultipleSelectedNotes: this.appState.notes.selectedNotesCount > 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NoteGroupViewDirective extends WebDirective {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = template;
|
||||||
|
this.controller = NoteGroupView;
|
||||||
|
this.controllerAs = 'self';
|
||||||
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
|
application: '=',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
component-view.component-view(
|
component-view.component-view(
|
||||||
component-viewer='self.state.editorComponentViewer',
|
component-viewer='self.state.editorComponentViewer',
|
||||||
ng-if='self.state.editorComponentViewer',
|
ng-if='self.state.editorComponentViewer',
|
||||||
on-load='self.onEditorLoad',
|
on-load='self.onEditorComponentLoad',
|
||||||
request-reload='self.editorComponentViewerRequestsReload'
|
request-reload='self.editorComponentViewerRequestsReload'
|
||||||
application='self.application'
|
application='self.application'
|
||||||
app-state='self.appState'
|
app-state='self.appState'
|
||||||
@@ -2,19 +2,19 @@
|
|||||||
* @jest-environment jsdom
|
* @jest-environment jsdom
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EditorViewCtrl } from '@Views/editor/editor_view';
|
import { NoteView } from '@Views/note_view/note_view';
|
||||||
import {
|
import {
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction,
|
ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction,
|
||||||
} from '@standardnotes/snjs/';
|
} from '@standardnotes/snjs/';
|
||||||
|
|
||||||
describe('editor-view', () => {
|
describe('editor-view', () => {
|
||||||
let ctrl: EditorViewCtrl;
|
let ctrl: NoteView;
|
||||||
let setShowProtectedWarningSpy: jest.SpyInstance;
|
let setShowProtectedWarningSpy: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const $timeout = {} as jest.Mocked<ng.ITimeoutService>;
|
const $timeout = {} as jest.Mocked<ng.ITimeoutService>;
|
||||||
ctrl = new EditorViewCtrl($timeout);
|
ctrl = new NoteView($timeout);
|
||||||
|
|
||||||
setShowProtectedWarningSpy = jest.spyOn(ctrl, 'setShowProtectedOverlay');
|
setShowProtectedWarningSpy = jest.spyOn(ctrl, 'setShowProtectedOverlay');
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { STRING_SAVING_WHILE_DOCUMENT_HIDDEN } from './../../strings';
|
import { STRING_SAVING_WHILE_DOCUMENT_HIDDEN } from './../../strings';
|
||||||
import { Editor } from '@/ui_models/editor';
|
import { NoteViewController } from '@/views/note_view/note_view_controller';
|
||||||
import { WebApplication } from '@/ui_models/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { PanelPuppet, WebDirective } from '@/types';
|
import { PanelPuppet, WebDirective } from '@/types';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
@@ -21,9 +21,9 @@ import {
|
|||||||
ItemMutator,
|
ItemMutator,
|
||||||
ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction,
|
ProposedSecondsToDeferUILevelSessionExpirationDuringActiveInteraction,
|
||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { debounce, isDesktopApplication } from '@/utils';
|
||||||
import { KeyboardModifier, KeyboardKey } from '@/services/ioService';
|
import { KeyboardModifier, KeyboardKey } from '@/services/ioService';
|
||||||
import template from './editor-view.pug';
|
import template from './note-view.pug';
|
||||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { EventSource } from '@/ui_models/app_state';
|
import { EventSource } from '@/ui_models/app_state';
|
||||||
import {
|
import {
|
||||||
@@ -90,10 +90,10 @@ function sortAlphabetically(array: SNComponent[]): SNComponent[] {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
export class NoteView extends PureViewCtrl<unknown, EditorState> {
|
||||||
/** Passed through template */
|
/** Passed through template */
|
||||||
readonly application!: WebApplication;
|
readonly application!: WebApplication;
|
||||||
readonly editor!: Editor;
|
readonly controller!: NoteViewController;
|
||||||
|
|
||||||
private leftPanelPuppet?: PanelPuppet;
|
private leftPanelPuppet?: PanelPuppet;
|
||||||
private rightPanelPuppet?: PanelPuppet;
|
private rightPanelPuppet?: PanelPuppet;
|
||||||
@@ -101,7 +101,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
private statusTimeout?: ng.IPromise<void>;
|
private statusTimeout?: ng.IPromise<void>;
|
||||||
private lastEditorFocusEventSource?: EventSource;
|
private lastEditorFocusEventSource?: EventSource;
|
||||||
public editorValues: EditorValues = { title: '', text: '' };
|
public editorValues: EditorValues = { title: '', text: '' };
|
||||||
onEditorLoad?: () => void;
|
onEditorComponentLoad?: () => void;
|
||||||
|
|
||||||
private scrollPosition = 0;
|
private scrollPosition = 0;
|
||||||
private removeTrashKeyObserver?: () => void;
|
private removeTrashKeyObserver?: () => void;
|
||||||
@@ -127,9 +127,13 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
this.resetScrollPosition = this.resetScrollPosition.bind(this);
|
this.resetScrollPosition = this.resetScrollPosition.bind(this);
|
||||||
this.editorComponentViewerRequestsReload =
|
this.editorComponentViewerRequestsReload =
|
||||||
this.editorComponentViewerRequestsReload.bind(this);
|
this.editorComponentViewerRequestsReload.bind(this);
|
||||||
this.onEditorLoad = () => {
|
this.onEditorComponentLoad = () => {
|
||||||
this.application.getDesktopService().redoSearch();
|
this.application.getDesktopService().redoSearch();
|
||||||
};
|
};
|
||||||
|
this.debounceReloadEditorComponent = debounce(
|
||||||
|
this.debounceReloadEditorComponent.bind(this),
|
||||||
|
25
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
@@ -144,7 +148,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
this.removeTabObserver = undefined;
|
this.removeTabObserver = undefined;
|
||||||
this.leftPanelPuppet = undefined;
|
this.leftPanelPuppet = undefined;
|
||||||
this.rightPanelPuppet = undefined;
|
this.rightPanelPuppet = undefined;
|
||||||
this.onEditorLoad = undefined;
|
this.onEditorComponentLoad = undefined;
|
||||||
this.saveTimeout = undefined;
|
this.saveTimeout = undefined;
|
||||||
this.statusTimeout = undefined;
|
this.statusTimeout = undefined;
|
||||||
(this.onPanelResizeFinish as unknown) = undefined;
|
(this.onPanelResizeFinish as unknown) = undefined;
|
||||||
@@ -157,14 +161,14 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get note() {
|
get note() {
|
||||||
return this.editor.note;
|
return this.controller.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
super.$onInit();
|
super.$onInit();
|
||||||
this.registerKeyboardShortcuts();
|
this.registerKeyboardShortcuts();
|
||||||
this.editor.setOnNoteValueChange((note, source) => {
|
this.controller.setOnNoteInnerValueChange((note, source) => {
|
||||||
this.onNoteChanges(note, source);
|
this.onNoteInnerChange(note, source);
|
||||||
});
|
});
|
||||||
this.autorun(() => {
|
this.autorun(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -180,12 +184,14 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
|
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
|
|
||||||
if (this.note.dirty) {
|
if (this.controller.isTemplateNote) {
|
||||||
this.showSavingStatus();
|
this.$timeout(() => {
|
||||||
|
this.focusTitle();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onNoteChanges(note: SNNote, source: PayloadSource): void {
|
private onNoteInnerChange(note: SNNote, source: PayloadSource): void {
|
||||||
if (note.uuid !== this.note.uuid) {
|
if (note.uuid !== this.note.uuid) {
|
||||||
throw Error('Editor received changes for non-current note');
|
throw Error('Editor received changes for non-current note');
|
||||||
}
|
}
|
||||||
@@ -214,6 +220,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
) {
|
) {
|
||||||
this.showSavingStatus();
|
this.showSavingStatus();
|
||||||
} else if (
|
} else if (
|
||||||
|
this.state.noteStatus &&
|
||||||
note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()
|
note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()
|
||||||
) {
|
) {
|
||||||
this.showAllChangesSavedStatus();
|
this.showAllChangesSavedStatus();
|
||||||
@@ -376,7 +383,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
}
|
}
|
||||||
if (!this.note) return;
|
if (!this.note) return;
|
||||||
await this.reloadStackComponents();
|
await this.reloadStackComponents();
|
||||||
await this.reloadEditorComponent();
|
this.debounceReloadEditorComponent();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -403,13 +410,22 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling reloadEditorComponent successively without waiting for state to settle
|
||||||
|
* can result in componentViewers being dealloced twice
|
||||||
|
*/
|
||||||
|
debounceReloadEditorComponent() {
|
||||||
|
this.reloadEditorComponent();
|
||||||
|
}
|
||||||
|
|
||||||
private async reloadEditorComponent() {
|
private async reloadEditorComponent() {
|
||||||
const newEditor = this.application.componentManager.editorForNote(
|
const newEditor = this.application.componentManager.editorForNote(
|
||||||
this.note
|
this.note
|
||||||
);
|
);
|
||||||
/** Editors cannot interact with template notes so the note must be inserted */
|
/** Editors cannot interact with template notes so the note must be inserted */
|
||||||
if (newEditor && this.editor.isTemplateNote) {
|
if (newEditor && this.controller.isTemplateNote) {
|
||||||
await this.editor.insertTemplatedNote();
|
await this.controller.insertTemplatedNote();
|
||||||
|
this.associateComponentWithCurrentNote(newEditor);
|
||||||
}
|
}
|
||||||
const currentComponentViewer = this.state.editorComponentViewer;
|
const currentComponentViewer = this.state.editorComponentViewer;
|
||||||
|
|
||||||
@@ -463,8 +479,8 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
const transactions: TransactionalMutation[] = [];
|
const transactions: TransactionalMutation[] = [];
|
||||||
|
|
||||||
this.setMenuState('showEditorMenu', false);
|
this.setMenuState('showEditorMenu', false);
|
||||||
if (this.appState.getActiveEditor()?.isTemplateNote) {
|
if (this.appState.getActiveNoteController()?.isTemplateNote) {
|
||||||
await this.appState.getActiveEditor().insertTemplatedNote();
|
await this.appState.getActiveNoteController().insertTemplatedNote();
|
||||||
}
|
}
|
||||||
if (this.note.locked) {
|
if (this.note.locked) {
|
||||||
this.application.alertService.alert(STRING_EDIT_LOCKED_ATTEMPT);
|
this.application.alertService.alert(STRING_EDIT_LOCKED_ATTEMPT);
|
||||||
@@ -550,7 +566,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
) {
|
) {
|
||||||
const title = editorValues.title;
|
const title = editorValues.title;
|
||||||
const text = editorValues.text;
|
const text = editorValues.text;
|
||||||
const isTemplate = this.editor.isTemplateNote;
|
const isTemplate = this.controller.isTemplateNote;
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
this.application.alertService.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
|
this.application.alertService.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
|
||||||
return;
|
return;
|
||||||
@@ -560,7 +576,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isTemplate) {
|
if (isTemplate) {
|
||||||
await this.editor.insertTemplatedNote();
|
await this.controller.insertTemplatedNote();
|
||||||
}
|
}
|
||||||
if (!this.application.findItem(note.uuid)) {
|
if (!this.application.findItem(note.uuid)) {
|
||||||
this.application.alertService.alert(STRING_INVALID_NOTE);
|
this.application.alertService.alert(STRING_INVALID_NOTE);
|
||||||
@@ -598,7 +614,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
this.saveTimeout = this.$timeout(() => {
|
this.saveTimeout = this.$timeout(() => {
|
||||||
this.application.sync();
|
this.application.sync();
|
||||||
if (closeAfterSync) {
|
if (closeAfterSync) {
|
||||||
this.appState.closeEditor(this.editor);
|
this.appState.closeNoteController(this.controller);
|
||||||
}
|
}
|
||||||
}, syncDebouceMs);
|
}, syncDebouceMs);
|
||||||
}
|
}
|
||||||
@@ -703,7 +719,7 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteNote(permanently: boolean) {
|
async deleteNote(permanently: boolean) {
|
||||||
if (this.editor.isTemplateNote) {
|
if (this.controller.isTemplateNote) {
|
||||||
this.application.alertService.alert(STRING_DELETE_PLACEHOLDER_ATTEMPT);
|
this.application.alertService.alert(STRING_DELETE_PLACEHOLDER_ATTEMPT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1023,17 +1039,17 @@ export class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorView extends WebDirective {
|
export class NoteViewDirective extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.scope = {
|
this.scope = {
|
||||||
editor: '=',
|
controller: '=',
|
||||||
application: '=',
|
application: '=',
|
||||||
};
|
};
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = EditorViewCtrl;
|
this.controller = NoteView;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
UuidString,
|
UuidString,
|
||||||
SNTag,
|
SNTag,
|
||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
import { WebApplication } from './application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
|
||||||
export class Editor {
|
export class NoteViewController {
|
||||||
public note!: SNNote;
|
public note!: SNNote;
|
||||||
private application: WebApplication;
|
private application: WebApplication;
|
||||||
private onNoteValueChange?: (note: SNNote, source: PayloadSource) => void;
|
private onNoteValueChange?: (note: SNNote, source: PayloadSource) => void;
|
||||||
@@ -28,7 +28,21 @@ export class Editor {
|
|||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
if (!this.note) {
|
if (!this.note) {
|
||||||
await this.createTemplateNote(this.defaultTitle, this.defaultTag);
|
const note = (await this.application.createTemplateItem(
|
||||||
|
ContentType.Note,
|
||||||
|
{
|
||||||
|
text: '',
|
||||||
|
title: this.defaultTitle,
|
||||||
|
references: [],
|
||||||
|
}
|
||||||
|
)) as SNNote;
|
||||||
|
if (this.defaultTag) {
|
||||||
|
const tag = this.application.findItem(this.defaultTag) as SNTag;
|
||||||
|
await this.application.addTagHierarchyToNote(note, tag);
|
||||||
|
}
|
||||||
|
this.isTemplateNote = true;
|
||||||
|
this.note = note;
|
||||||
|
this.onNoteValueChange?.(this.note, this.note.payload.source);
|
||||||
}
|
}
|
||||||
this.streamItems();
|
this.streamItems();
|
||||||
}
|
}
|
||||||
@@ -67,29 +81,10 @@ export class Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts the editor to a blank state, removing any existing note from view,
|
* Register to be notified when the controller's note's inner values change
|
||||||
* and creating a placeholder note.
|
|
||||||
*/
|
|
||||||
async createTemplateNote(defaultTitle?: string, noteTag?: UuidString) {
|
|
||||||
const note = (await this.application.createTemplateItem(ContentType.Note, {
|
|
||||||
text: '',
|
|
||||||
title: defaultTitle,
|
|
||||||
references: [],
|
|
||||||
})) as SNNote;
|
|
||||||
if (noteTag) {
|
|
||||||
const tag = this.application.findItem(noteTag) as SNTag;
|
|
||||||
await this.application.addTagHierarchyToNote(note, tag);
|
|
||||||
}
|
|
||||||
this.isTemplateNote = true;
|
|
||||||
this.note = note;
|
|
||||||
this.onNoteValueChange?.(this.note, this.note.payload.source);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register to be notified when the editor's note's values change
|
|
||||||
* (and thus a new object reference is created)
|
* (and thus a new object reference is created)
|
||||||
*/
|
*/
|
||||||
public setOnNoteValueChange(
|
public setOnNoteInnerValueChange(
|
||||||
callback: (note: SNNote, source: PayloadSource) => void
|
callback: (note: SNNote, source: PayloadSource) => void
|
||||||
) {
|
) {
|
||||||
this.onNoteValueChange = callback;
|
this.onNoteValueChange = callback;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "standard-notes-web",
|
"name": "standard-notes-web",
|
||||||
"version": "3.9.10",
|
"version": "3.9.11",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -84,10 +84,10 @@
|
|||||||
"@reach/checkbox": "^0.16.0",
|
"@reach/checkbox": "^0.16.0",
|
||||||
"@reach/dialog": "^0.16.2",
|
"@reach/dialog": "^0.16.2",
|
||||||
"@reach/listbox": "^0.16.2",
|
"@reach/listbox": "^0.16.2",
|
||||||
"@standardnotes/features": "1.10.2",
|
"@standardnotes/features": "1.15.1",
|
||||||
"@reach/tooltip": "^0.16.2",
|
"@reach/tooltip": "^0.16.2",
|
||||||
"@standardnotes/sncrypto-web": "1.5.3",
|
"@standardnotes/sncrypto-web": "1.5.3",
|
||||||
"@standardnotes/snjs": "2.29.0",
|
"@standardnotes/snjs": "2.30.0",
|
||||||
"mobx": "^6.3.5",
|
"mobx": "^6.3.5",
|
||||||
"mobx-react-lite": "^3.2.2",
|
"mobx-react-lite": "^3.2.2",
|
||||||
"preact": "^10.5.15",
|
"preact": "^10.5.15",
|
||||||
|
|||||||
24
yarn.lock
24
yarn.lock
@@ -2623,14 +2623,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@standardnotes/auth" "^3.8.1"
|
"@standardnotes/auth" "^3.8.1"
|
||||||
|
|
||||||
"@standardnotes/features@1.10.2":
|
|
||||||
version "1.10.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.10.2.tgz#a0783f66c00e21cb7692edc0cea95ec25a0253a5"
|
|
||||||
integrity sha512-Zh6EMjli4mL6jlXEhMyU3qYIKFJj5kuhbxtHXiErUGIDy+s1hHY+THFFO53Jdga2+8wgcATWlmSBY7dieVA8uA==
|
|
||||||
dependencies:
|
|
||||||
"@standardnotes/auth" "3.8.3"
|
|
||||||
"@standardnotes/common" "^1.2.1"
|
|
||||||
|
|
||||||
"@standardnotes/features@1.11.0":
|
"@standardnotes/features@1.11.0":
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.11.0.tgz#66e960a20358c5f58b6be4e19226b34df6f4efbf"
|
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.11.0.tgz#66e960a20358c5f58b6be4e19226b34df6f4efbf"
|
||||||
@@ -2639,6 +2631,14 @@
|
|||||||
"@standardnotes/auth" "3.8.3"
|
"@standardnotes/auth" "3.8.3"
|
||||||
"@standardnotes/common" "^1.2.1"
|
"@standardnotes/common" "^1.2.1"
|
||||||
|
|
||||||
|
"@standardnotes/features@1.15.1":
|
||||||
|
version "1.15.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.15.1.tgz#3880d73fb32ab952359e70fb313abfdf14023c7d"
|
||||||
|
integrity sha512-QurBvYwfNrcAKLwE7Z/1EsFpZ6Vuwp8E9O7jlMlzf0GyMXY/djCooeXjmoCWed+B/qJ4sdDdtptGyMsjKVeJCw==
|
||||||
|
dependencies:
|
||||||
|
"@standardnotes/auth" "3.8.3"
|
||||||
|
"@standardnotes/common" "1.2.1"
|
||||||
|
|
||||||
"@standardnotes/settings@^1.8.0":
|
"@standardnotes/settings@^1.8.0":
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.8.0.tgz#d7bd1f35c3b500d12ba73f5f385b1019baae3efc"
|
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.8.0.tgz#d7bd1f35c3b500d12ba73f5f385b1019baae3efc"
|
||||||
@@ -2658,10 +2658,10 @@
|
|||||||
buffer "^6.0.3"
|
buffer "^6.0.3"
|
||||||
libsodium-wrappers "^0.7.9"
|
libsodium-wrappers "^0.7.9"
|
||||||
|
|
||||||
"@standardnotes/snjs@2.29.0":
|
"@standardnotes/snjs@2.30.0":
|
||||||
version "2.29.0"
|
version "2.30.0"
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.29.0.tgz#6c7c6ccd983df4a1a5e2063647eb731304002fd9"
|
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.30.0.tgz#12abda65e8069273347bbf6786d6a99203260023"
|
||||||
integrity sha512-Y+GpNiFyJtVr2W3nVbC2zljtXpBlqe3cB4+R1REE0V4hnQBaq/HE6PaUd80TnFj99Kl8lowyH/o4bNV3+CjGgg==
|
integrity sha512-0s7NYtO8edvY3/MNwx/Ic+fIDXiSnaVhdBWlaIOreVHwUl15LkHyN8mptR8QLtHOjOhvaguew+KCvmXXmkNjTA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@standardnotes/auth" "3.8.1"
|
"@standardnotes/auth" "3.8.1"
|
||||||
"@standardnotes/common" "1.2.1"
|
"@standardnotes/common" "1.2.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user