Remove dummy concept in favor of editor group and editors
This commit is contained in:
@@ -5,18 +5,17 @@ declare const __VERSION__: string
|
|||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import { configRoutes } from './routes';
|
import { configRoutes } from './routes';
|
||||||
|
|
||||||
import {
|
import { ApplicationGroup } from './ui_models/application_group';
|
||||||
ApplicationManager
|
|
||||||
} from './applicationManager';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Root,
|
ApplicationGroupView,
|
||||||
ApplicationView,
|
ApplicationView,
|
||||||
TagsPanel,
|
EditorGroupView,
|
||||||
NotesPanel,
|
EditorView,
|
||||||
EditorPanel,
|
TagsView,
|
||||||
Footer
|
NotesView,
|
||||||
} from './controllers';
|
FooterView
|
||||||
|
} from '@/views';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
autofocus,
|
autofocus,
|
||||||
@@ -62,13 +61,13 @@ angular
|
|||||||
// Controllers
|
// Controllers
|
||||||
angular
|
angular
|
||||||
.module('app')
|
.module('app')
|
||||||
.directive('root', () => new Root())
|
.directive('applicationGroupView', () => new ApplicationGroupView())
|
||||||
.directive('applicationView', () => new ApplicationView())
|
.directive('applicationView', () => new ApplicationView())
|
||||||
.directive('tagsPanel', () => new TagsPanel())
|
.directive('editorGroupView', () => new EditorGroupView())
|
||||||
.directive('notesPanel', () => new NotesPanel())
|
.directive('editorView', () => new EditorView())
|
||||||
.directive('editorPanel', () => new EditorPanel())
|
.directive('tagsView', () => new TagsView())
|
||||||
.directive('footer', () => new Footer())
|
.directive('notesView', () => new NotesView())
|
||||||
// .directive('lockScreen', () => new LockScreen());
|
.directive('footerView', () => new FooterView())
|
||||||
|
|
||||||
// Directives - Functional
|
// Directives - Functional
|
||||||
angular
|
angular
|
||||||
@@ -78,9 +77,7 @@ angular
|
|||||||
.directive('delayHide', delayHide)
|
.directive('delayHide', delayHide)
|
||||||
.directive('elemReady', elemReady)
|
.directive('elemReady', elemReady)
|
||||||
.directive('fileChange', fileChange)
|
.directive('fileChange', fileChange)
|
||||||
.directive('infiniteScroll', [
|
.directive('infiniteScroll', [infiniteScroll])
|
||||||
infiniteScroll
|
|
||||||
])
|
|
||||||
.directive('lowercase', lowercase)
|
.directive('lowercase', lowercase)
|
||||||
.directive('selectOnClick', ['$window', selectOnClick])
|
.directive('selectOnClick', ['$window', selectOnClick])
|
||||||
.directive('snEnter', snEnter);
|
.directive('snEnter', snEnter);
|
||||||
@@ -93,11 +90,6 @@ angular
|
|||||||
.directive('challengeModal', () => new ChallengeModal())
|
.directive('challengeModal', () => new ChallengeModal())
|
||||||
.directive('componentModal', () => new ComponentModal())
|
.directive('componentModal', () => new ComponentModal())
|
||||||
.directive('componentView', () => new ComponentView())
|
.directive('componentView', () => new ComponentView())
|
||||||
// .directive(
|
|
||||||
// 'componentView',
|
|
||||||
// ($rootScope, componentManager, desktopManager, $timeout) =>
|
|
||||||
// new ComponentView($rootScope, componentManager, desktopManager, $timeout)
|
|
||||||
// )
|
|
||||||
.directive('editorMenu', () => new EditorMenu())
|
.directive('editorMenu', () => new EditorMenu())
|
||||||
.directive('inputModal', () => new InputModal())
|
.directive('inputModal', () => new InputModal())
|
||||||
.directive('menuRow', () => new MenuRow())
|
.directive('menuRow', () => new MenuRow())
|
||||||
@@ -116,4 +108,4 @@ angular
|
|||||||
.filter('trusted', ['$sce', trusted]);
|
.filter('trusted', ['$sce', trusted]);
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
angular.module('app').service('applicationManager', ApplicationManager);
|
angular.module('app').service('mainApplicationGroup', ApplicationGroup);
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
export { PureCtrl } from './abstract/pure_ctrl';
|
|
||||||
export { EditorPanel } from './editor';
|
|
||||||
export { Footer } from './footer';
|
|
||||||
export { NotesPanel } from './notes/notes';
|
|
||||||
export { TagsPanel } from './tags';
|
|
||||||
export { Root } from './root';
|
|
||||||
export { ApplicationView } from './applicationView';
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { ApplicationManager } from './../applicationManager';
|
|
||||||
import { WebDirective } from './../types';
|
|
||||||
import template from '%/root.pug';
|
|
||||||
import { WebApplication } from '@/application';
|
|
||||||
|
|
||||||
class RootCtrl {
|
|
||||||
|
|
||||||
private $timeout: ng.ITimeoutService
|
|
||||||
private applicationManager: ApplicationManager
|
|
||||||
public applications: WebApplication[] = []
|
|
||||||
|
|
||||||
/* @ngInject */
|
|
||||||
constructor($timeout: ng.ITimeoutService, applicationManager: ApplicationManager) {
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.applicationManager = applicationManager;
|
|
||||||
this.applicationManager.addApplicationChangeObserver(() => {
|
|
||||||
this.reload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
reload() {
|
|
||||||
this.$timeout(() => {
|
|
||||||
this.applications = this.applicationManager.getApplications();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Root extends WebDirective {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.template = template;
|
|
||||||
this.controller = RootCtrl;
|
|
||||||
this.replace = true;
|
|
||||||
this.controllerAs = 'self';
|
|
||||||
this.bindToController = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import { WebApplication } from './application';
|
|
||||||
import { SNAlertService } from "../../../../snjs/dist/@types";
|
import { SNAlertService } from "../../../../snjs/dist/@types";
|
||||||
import { RawPayload } from '../../../../snjs/dist/@types/protocol/payloads/generator';
|
|
||||||
|
|
||||||
const DB_NAME = 'standardnotes';
|
const DB_NAME = 'standardnotes';
|
||||||
const STORE_NAME = 'items';
|
const STORE_NAME = 'items';
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
|
import { debounce } from '@/utils';
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
export function infiniteScroll() {
|
export function infiniteScroll() {
|
||||||
return {
|
return {
|
||||||
link: function (scope: ng.IScope, elem: JQLite, attrs: any) {
|
link: function (scope: ng.IScope, elem: JQLite, attrs: any) {
|
||||||
const scopeAny = scope as any;
|
const scopeAny = scope as any;
|
||||||
const offset = parseInt(attrs.threshold) || 0;
|
const offset = parseInt(attrs.threshold) || 0;
|
||||||
const e = elem[0];
|
const element = elem[0];
|
||||||
|
scopeAny.paginate = debounce(() => {
|
||||||
|
scope.$apply(attrs.infiniteScroll);
|
||||||
|
}, 100);
|
||||||
scopeAny.onScroll = () => {
|
scopeAny.onScroll = () => {
|
||||||
if (
|
if (
|
||||||
scope.$eval(attrs.canLoad) &&
|
scope.$eval(attrs.canLoad) &&
|
||||||
e.scrollTop + e.offsetHeight >= e.scrollHeight - offset
|
element.scrollTop + element.offsetHeight >= element.scrollHeight - offset
|
||||||
) {
|
) {
|
||||||
scope.$apply(attrs.infiniteScroll);
|
scopeAny.paginate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
elem.on('scroll', scopeAny.onScroll);
|
elem.on('scroll', scopeAny.onScroll);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { WebDirective } from './../../types';
|
|||||||
import { isDesktopApplication, isNullOrUndefined } from '@/utils';
|
import { isDesktopApplication, isNullOrUndefined } from '@/utils';
|
||||||
import template from '%/directives/account-menu.pug';
|
import template from '%/directives/account-menu.pug';
|
||||||
import { ProtectedAction, ContentType } from 'snjs';
|
import { ProtectedAction, ContentType } from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import {
|
import {
|
||||||
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
STRING_ACCOUNT_MENU_UNCHECK_MERGE,
|
||||||
STRING_SIGN_OUT_CONFIRMATION,
|
STRING_SIGN_OUT_CONFIRMATION,
|
||||||
@@ -59,7 +59,7 @@ type AccountMenuState = {
|
|||||||
importData: any
|
importData: any
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountMenuCtrl extends PureCtrl {
|
class AccountMenuCtrl extends PureViewCtrl {
|
||||||
|
|
||||||
public appVersion: string
|
public appVersion: string
|
||||||
private syncStatus?: SyncOpStatus
|
private syncStatus?: SyncOpStatus
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import template from '%/directives/actions-menu.pug';
|
import template from '%/directives/actions-menu.pug';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { SNItem, Action, SNActionsExtension } from '@/../../../../snjs/dist/@types';
|
import { SNItem, Action, SNActionsExtension } from '@/../../../../snjs/dist/@types';
|
||||||
import { ActionResponse } from '@/../../../../snjs/dist/@types/services/actions_service';
|
import { ActionResponse } from '@/../../../../snjs/dist/@types/services/actions_service';
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ type ActionsMenuScope = {
|
|||||||
item: SNItem
|
item: SNItem
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActionsMenuCtrl extends PureCtrl implements ActionsMenuScope {
|
class ActionsMenuCtrl extends PureViewCtrl implements ActionsMenuScope {
|
||||||
|
|
||||||
application!: WebApplication
|
application!: WebApplication
|
||||||
item!: SNItem
|
item!: SNItem
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import { WebApplication } from './../../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import template from '%/directives/challenge-modal.pug';
|
import template from '%/directives/challenge-modal.pug';
|
||||||
import {
|
import {
|
||||||
ChallengeType,
|
ChallengeType,
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
Challenge,
|
Challenge,
|
||||||
ChallengeOrchestrator
|
ChallengeOrchestrator
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
|
|
||||||
type InputValue = {
|
type InputValue = {
|
||||||
value: string
|
value: string
|
||||||
@@ -28,7 +28,7 @@ type ChallengeModalState = {
|
|||||||
processing: boolean
|
processing: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChallengeModalCtrl extends PureCtrl implements ChallengeModalScope {
|
class ChallengeModalCtrl extends PureViewCtrl implements ChallengeModalScope {
|
||||||
private $element: JQLite
|
private $element: JQLite
|
||||||
private processingTypes: ChallengeType[] = []
|
private processingTypes: ChallengeType[] = []
|
||||||
application!: WebApplication
|
application!: WebApplication
|
||||||
@@ -159,7 +159,8 @@ export class ChallengeModal extends WebDirective {
|
|||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = ChallengeModalCtrl;
|
this.controller = ChallengeModalCtrl;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = {
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
challenge: '=',
|
challenge: '=',
|
||||||
orchestrator: '=',
|
orchestrator: '=',
|
||||||
application: '='
|
application: '='
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from './../../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { SNComponent } from 'snjs';
|
import { SNComponent } from 'snjs';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import template from '%/directives/component-modal.pug';
|
import template from '%/directives/component-modal.pug';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { SNComponent } from 'snjs';
|
import { SNComponent } from 'snjs';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import template from '%/directives/component-view.pug';
|
import template from '%/directives/component-view.pug';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { SNComponent, SNItem, ComponentArea } from 'snjs';
|
import { SNComponent, SNItem, ComponentArea } from 'snjs';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import template from '%/directives/editor-menu.pug';
|
import template from '%/directives/editor-menu.pug';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { ComponentMutator } from '@/../../../../snjs/dist/@types/models';
|
import { ComponentMutator } from '@/../../../../snjs/dist/@types/models';
|
||||||
|
|
||||||
interface EditorMenuScope {
|
interface EditorMenuScope {
|
||||||
@@ -13,7 +13,7 @@ interface EditorMenuScope {
|
|||||||
application: WebApplication
|
application: WebApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorMenuCtrl extends PureCtrl implements EditorMenuScope {
|
class EditorMenuCtrl extends PureViewCtrl implements EditorMenuScope {
|
||||||
|
|
||||||
callback!: (component: SNComponent) => void
|
callback!: (component: SNComponent) => void
|
||||||
selectedEditor!: SNComponent
|
selectedEditor!: SNComponent
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class PanelResizerCtrl implements PanelResizerScope {
|
|||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
|
|
||||||
/** To allow for registering events */
|
/** To allow for registering events */
|
||||||
this.handleResize = this.handleResize.bind(this);
|
this.handleResize = debounce(this.handleResize.bind(this), 250);
|
||||||
this.onMouseMove = this.onMouseMove.bind(this);
|
this.onMouseMove = this.onMouseMove.bind(this);
|
||||||
this.onMouseUp = this.onMouseUp.bind(this);
|
this.onMouseUp = this.onMouseUp.bind(this);
|
||||||
this.onMouseDown = this.onMouseDown.bind(this);
|
this.onMouseDown = this.onMouseDown.bind(this);
|
||||||
@@ -163,13 +163,11 @@ class PanelResizerCtrl implements PanelResizerScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleResize() {
|
handleResize() {
|
||||||
debounce(() => {
|
this.reloadDefaultValues();
|
||||||
this.reloadDefaultValues();
|
this.handleWidthEvent();
|
||||||
this.handleWidthEvent();
|
this.$timeout(() => {
|
||||||
this.$timeout(() => {
|
this.finishSettingWidth();
|
||||||
this.finishSettingWidth();
|
});
|
||||||
});
|
|
||||||
}, 250);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getParentRect() {
|
getParentRect() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WebApplication } from './../../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { PasswordWizardScope, PasswordWizardType, WebDirective } from './../../types';
|
import { PasswordWizardScope, PasswordWizardType, WebDirective } from './../../types';
|
||||||
import template from '%/directives/password-wizard.pug';
|
import template from '%/directives/password-wizard.pug';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
|
|
||||||
const DEFAULT_CONTINUE_TITLE = "Continue";
|
const DEFAULT_CONTINUE_TITLE = "Continue";
|
||||||
const Steps = {
|
const Steps = {
|
||||||
@@ -9,7 +9,7 @@ const Steps = {
|
|||||||
FinishStep: 2
|
FinishStep: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class PasswordWizardCtrl extends PureCtrl implements PasswordWizardScope {
|
class PasswordWizardCtrl extends PureViewCtrl implements PasswordWizardScope {
|
||||||
$element: JQLite
|
$element: JQLite
|
||||||
application!: WebApplication
|
application!: WebApplication
|
||||||
type!: PasswordWizardType
|
type!: PasswordWizardType
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { ProtectedAction, PrivilegeCredential, PrivilegeSessionLength } from 'snjs';
|
import { ProtectedAction, PrivilegeCredential, PrivilegeSessionLength } from 'snjs';
|
||||||
import template from '%/directives/privileges-auth-modal.pug';
|
import template from '%/directives/privileges-auth-modal.pug';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import template from '%/directives/privileges-management-modal.pug';
|
import template from '%/directives/privileges-management-modal.pug';
|
||||||
import { PrivilegeCredential, ProtectedAction, SNPrivileges, PrivilegeSessionLength } from 'snjs';
|
import { PrivilegeCredential, ProtectedAction, SNPrivileges, PrivilegeSessionLength } from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { PrivilegeMutator } from '@/../../../../snjs/dist/@types/models';
|
import { PrivilegeMutator } from '@/../../../../snjs/dist/@types/models';
|
||||||
|
|
||||||
type DisplayInfo = {
|
type DisplayInfo = {
|
||||||
@@ -10,7 +10,7 @@ type DisplayInfo = {
|
|||||||
prompt: string
|
prompt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrivilegesManagementModalCtrl extends PureCtrl {
|
class PrivilegesManagementModalCtrl extends PureViewCtrl {
|
||||||
|
|
||||||
hasPasscode = false
|
hasPasscode = false
|
||||||
hasAccount = false
|
hasAccount = false
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import {
|
import {
|
||||||
ContentType,
|
ContentType,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import template from '%/directives/session-history-menu.pug';
|
import template from '%/directives/session-history-menu.pug';
|
||||||
import { SNItem, ItemHistoryEntry, ItemHistory } from '@/../../../../snjs/dist/@types';
|
import { SNItem, ItemHistoryEntry, ItemHistory } from '@/../../../../snjs/dist/@types';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
import template from '%/directives/sync-resolution-menu.pug';
|
import template from '%/directives/sync-resolution-menu.pug';
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { SKAlert } from 'sn-stylekit';
|
|||||||
|
|
||||||
export class AlertService extends SNAlertService {
|
export class AlertService extends SNAlertService {
|
||||||
async alert(
|
async alert(
|
||||||
title: string,
|
|
||||||
text: string,
|
text: string,
|
||||||
|
title: string,
|
||||||
closeButtonText = 'OK',
|
closeButtonText = 'OK',
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
) {
|
) {
|
||||||
@@ -28,8 +28,8 @@ export class AlertService extends SNAlertService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async confirm(
|
async confirm(
|
||||||
title: string,
|
|
||||||
text: string,
|
text: string,
|
||||||
|
title: string,
|
||||||
confirmButtonText = 'Confirm',
|
confirmButtonText = 'Confirm',
|
||||||
cancelButtonText = 'Cancel',
|
cancelButtonText = 'Cancel',
|
||||||
onConfirm: () => void,
|
onConfirm: () => void,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { EncryptionIntent, ProtectedAction, SNItem, ContentType, SNNote } from 'snjs';
|
import { EncryptionIntent, ProtectedAction, SNItem, ContentType, SNNote } from 'snjs';
|
||||||
|
|
||||||
export class ArchiveManager {
|
export class ArchiveManager {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { SNComponent, PurePayload, ComponentMutator, AppDataField } from 'snjs';
|
import { SNComponent, PurePayload, ComponentMutator, AppDataField } from 'snjs';
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
// An interface used by the Desktop app to interact with SN
|
// An interface used by the Desktop app to interact with SN
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { EncryptionIntent, ApplicationService, ApplicationEvent, removeFromArray } from 'snjs';
|
import { EncryptionIntent, ApplicationService, ApplicationEvent, removeFromArray } from 'snjs';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from './../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import {
|
import {
|
||||||
SNPredicate,
|
SNPredicate,
|
||||||
ContentType,
|
ContentType,
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
import { WebApplication } from './../application';
|
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import pull from 'lodash/pull';
|
import pull from 'lodash/pull';
|
||||||
import { ProtectedAction, ApplicationEvent, SNTag, SNNote, SNUserPrefs, ContentType, SNSmartTag } from 'snjs';
|
import {
|
||||||
|
ProtectedAction,
|
||||||
|
ApplicationEvent,
|
||||||
|
SNTag,
|
||||||
|
SNNote,
|
||||||
|
SNUserPrefs,
|
||||||
|
ContentType,
|
||||||
|
SNSmartTag
|
||||||
|
} from 'snjs';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
import { Editor } from '@/ui_models/editor';
|
||||||
|
|
||||||
export enum AppStateEvent {
|
export enum AppStateEvent {
|
||||||
TagChanged = 1,
|
TagChanged = 1,
|
||||||
NoteChanged = 2,
|
ActiveEditorChanged = 2,
|
||||||
PreferencesChanged = 3,
|
PreferencesChanged = 3,
|
||||||
PanelResized = 4,
|
PanelResized = 4,
|
||||||
EditorFocused = 5,
|
EditorFocused = 5,
|
||||||
@@ -34,8 +43,8 @@ export class AppState {
|
|||||||
rootScopeCleanup2: any
|
rootScopeCleanup2: any
|
||||||
onVisibilityChange: any
|
onVisibilityChange: any
|
||||||
selectedTag?: SNTag
|
selectedTag?: SNTag
|
||||||
selectedNote?: SNNote
|
|
||||||
userPreferences?: SNUserPrefs
|
userPreferences?: SNUserPrefs
|
||||||
|
multiEditorEnabled = false
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
@@ -74,16 +83,90 @@ export class AppState {
|
|||||||
this.onVisibilityChange = undefined;
|
this.onVisibilityChange = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new editor if one doesn't exist. If one does, we'll replace the
|
||||||
|
* editor's note with an empty one.
|
||||||
|
*/
|
||||||
|
createEditor(title?: string) {
|
||||||
|
const activeEditor = this.getActiveEditor();
|
||||||
|
if (!activeEditor || this.multiEditorEnabled) {
|
||||||
|
this.application.editorGroup.createEditor(title);
|
||||||
|
} else {
|
||||||
|
activeEditor.reset(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async openEditor(noteUuid: string) {
|
||||||
|
const note = this.application.findItem(noteUuid) as SNNote;
|
||||||
|
const run = async () => {
|
||||||
|
const activeEditor = this.getActiveEditor();
|
||||||
|
if (!activeEditor || this.multiEditorEnabled) {
|
||||||
|
this.application.editorGroup.createEditor(noteUuid);
|
||||||
|
} else {
|
||||||
|
activeEditor.setNote(note);
|
||||||
|
}
|
||||||
|
await this.notifyEvent(AppStateEvent.ActiveEditorChanged);
|
||||||
|
};
|
||||||
|
if (note && note.safeContent.protected &&
|
||||||
|
await this.application.privilegesService!.actionRequiresPrivilege(
|
||||||
|
ProtectedAction.ViewProtectedNotes
|
||||||
|
)) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.application.presentPrivilegesModal(
|
||||||
|
ProtectedAction.ViewProtectedNotes,
|
||||||
|
() => {
|
||||||
|
run().then(resolve);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveEditor() {
|
||||||
|
return this.application.editorGroup.editors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
getEditors() {
|
||||||
|
return this.application.editorGroup.editors;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeEditor(editor: Editor) {
|
||||||
|
this.application.editorGroup.closeEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeActiveEditor() {
|
||||||
|
this.application.editorGroup.closeActiveEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAllEditors() {
|
||||||
|
this.application.editorGroup.closeAllEditors();
|
||||||
|
}
|
||||||
|
|
||||||
|
editorForNote(note: SNNote) {
|
||||||
|
for (const editor of this.getEditors()) {
|
||||||
|
if (editor.note.uuid === note.uuid) {
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
streamNotesAndTags() {
|
streamNotesAndTags() {
|
||||||
this.application!.streamItems(
|
this.application!.streamItems(
|
||||||
[ContentType.Note, ContentType.Tag],
|
[ContentType.Note, ContentType.Tag],
|
||||||
async (items) => {
|
async (items) => {
|
||||||
if(this.selectedNote) {
|
/** Close any editors for deleted notes */
|
||||||
const matchingNote = items.find((candidate) => candidate.uuid === this.selectedNote!.uuid);
|
const notes = items.filter((candidate) => candidate.content_type === ContentType.Note) as SNNote[];
|
||||||
if(matchingNote) {
|
for (const note of notes) {
|
||||||
this.selectedNote = matchingNote as SNNote;
|
if (note.deleted) {
|
||||||
|
const editor = this.editorForNote(note);
|
||||||
|
if (editor) {
|
||||||
|
this.closeEditor(editor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedTag) {
|
if (this.selectedTag) {
|
||||||
const matchingTag = items.find((candidate) => candidate.uuid === this.selectedTag!.uuid);
|
const matchingTag = items.find((candidate) => candidate.uuid === this.selectedTag!.uuid);
|
||||||
if (matchingTag) {
|
if (matchingTag) {
|
||||||
@@ -161,32 +244,6 @@ export class AppState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSelectedNote(note?: SNNote) {
|
|
||||||
const run = async () => {
|
|
||||||
const previousNote = this.selectedNote;
|
|
||||||
this.selectedNote = note;
|
|
||||||
await this.notifyEvent(
|
|
||||||
AppStateEvent.NoteChanged,
|
|
||||||
{ previousNote: previousNote }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
if (note && note.safeContent.protected &&
|
|
||||||
await this.application.privilegesService!.actionRequiresPrivilege(
|
|
||||||
ProtectedAction.ViewProtectedNotes
|
|
||||||
)) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
this.application.presentPrivilegesModal(
|
|
||||||
ProtectedAction.ViewProtectedNotes,
|
|
||||||
() => {
|
|
||||||
run().then(resolve);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the tags that are referncing this note */
|
/** Returns the tags that are referncing this note */
|
||||||
getNoteTags(note: SNNote) {
|
getNoteTags(note: SNNote) {
|
||||||
return this.application.referencingForItem(note).filter((ref) => {
|
return this.application.referencingForItem(note).filter((ref) => {
|
||||||
@@ -196,11 +253,11 @@ export class AppState {
|
|||||||
|
|
||||||
/** Returns the notes this tag references */
|
/** Returns the notes this tag references */
|
||||||
getTagNotes(tag: SNTag) {
|
getTagNotes(tag: SNTag) {
|
||||||
if(tag.isSmartTag()) {
|
if (tag.isSmartTag()) {
|
||||||
return this.application.notesMatchingSmartTag(tag as SNSmartTag);
|
return this.application.notesMatchingSmartTag(tag as SNSmartTag);
|
||||||
} else {
|
} else {
|
||||||
return this.application.referencesForItem(tag).filter((ref) => {
|
return this.application.referencesForItem(tag).filter((ref) => {
|
||||||
return ref.content_type === tag.content_type;
|
return ref.content_type === ContentType.Note;
|
||||||
}) as SNNote[]
|
}) as SNNote[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,10 +266,6 @@ export class AppState {
|
|||||||
return this.selectedTag;
|
return this.selectedTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectedNote() {
|
|
||||||
return this.selectedNote;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUserPreferences(preferences: SNUserPrefs) {
|
setUserPreferences(preferences: SNUserPrefs) {
|
||||||
this.userPreferences = preferences;
|
this.userPreferences = preferences;
|
||||||
this.notifyEvent(
|
this.notifyEvent(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { removeFromArray } from 'snjs';
|
import { removeFromArray } from 'snjs';
|
||||||
import { FooterStatus } from './../types';
|
import { FooterStatus } from '@/types';
|
||||||
|
|
||||||
type StatusCallback = (string: string) => void
|
type StatusCallback = (string: string) => void
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {
|
import {
|
||||||
StorageValueModes,
|
StorageValueModes,
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"%/*": ["../templates/*"],
|
"%/*": ["../templates/*"],
|
||||||
"@/*": ["./*"],
|
"@/*": ["./*"],
|
||||||
"@Controllers/*": ["./controllers/*"]
|
"@Controllers/*": ["./controllers/*"],
|
||||||
|
"@Views/*": ["./views/*"],
|
||||||
|
"@Services/*": ["./services/*"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { InputModalScope } from './directives/views/inputModal';
|
import { EditorGroup } from '@/ui_models/editor_group';
|
||||||
import { PasswordWizardType, PasswordWizardScope } from './types';
|
import { InputModalScope } from '@/directives/views/inputModal';
|
||||||
|
import { PasswordWizardType, PasswordWizardScope } from '@/types';
|
||||||
import {
|
import {
|
||||||
Environment,
|
Environment,
|
||||||
SNApplication,
|
SNApplication,
|
||||||
@@ -23,7 +24,7 @@ import {
|
|||||||
ThemeManager,
|
ThemeManager,
|
||||||
PreferencesManager,
|
PreferencesManager,
|
||||||
KeyboardManager
|
KeyboardManager
|
||||||
} from './services';
|
} from '@/services';
|
||||||
|
|
||||||
type WebServices = {
|
type WebServices = {
|
||||||
appState: AppState
|
appState: AppState
|
||||||
@@ -44,6 +45,7 @@ export class WebApplication extends SNApplication {
|
|||||||
private onDeinit?: (app: WebApplication) => void
|
private onDeinit?: (app: WebApplication) => void
|
||||||
private webServices!: WebServices
|
private webServices!: WebServices
|
||||||
private currentAuthenticationElement?: JQLite
|
private currentAuthenticationElement?: JQLite
|
||||||
|
public editorGroup: EditorGroup
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
@@ -71,6 +73,7 @@ export class WebApplication extends SNApplication {
|
|||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.onDeinit = onDeinit;
|
this.onDeinit = onDeinit;
|
||||||
deviceInterface.setApplication(this);
|
deviceInterface.setApplication(this);
|
||||||
|
this.editorGroup = new EditorGroup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
@@ -86,6 +89,7 @@ export class WebApplication extends SNApplication {
|
|||||||
this.onDeinit!(this);
|
this.onDeinit!(this);
|
||||||
this.onDeinit = undefined;
|
this.onDeinit = undefined;
|
||||||
this.$compile = undefined;
|
this.$compile = undefined;
|
||||||
|
this.editorGroup.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;
|
||||||
@@ -10,11 +10,11 @@ import {
|
|||||||
StatusManager,
|
StatusManager,
|
||||||
ThemeManager,
|
ThemeManager,
|
||||||
AppState
|
AppState
|
||||||
} from './services';
|
} from '@/services';
|
||||||
|
|
||||||
type AppManagerChangeCallback = () => void
|
type AppManagerChangeCallback = () => void
|
||||||
|
|
||||||
export class ApplicationManager {
|
export class ApplicationGroup {
|
||||||
|
|
||||||
$compile: ng.ICompileService
|
$compile: ng.ICompileService
|
||||||
$rootScope: ng.IRootScopeService
|
$rootScope: ng.IRootScopeService
|
||||||
104
app/assets/javascripts/ui_models/editor.ts
Normal file
104
app/assets/javascripts/ui_models/editor.ts
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import { SNNote, ContentType, PayloadSource } from 'snjs';
|
||||||
|
import { WebApplication } from './application';
|
||||||
|
|
||||||
|
export class Editor {
|
||||||
|
|
||||||
|
public note!: SNNote
|
||||||
|
private application: WebApplication
|
||||||
|
private _onNoteChange?: () => void
|
||||||
|
private _onNoteValueChange?: (note: SNNote, source?: PayloadSource) => void
|
||||||
|
private removeStreamObserver: () => void
|
||||||
|
public isTemplateNote = true
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
application: WebApplication,
|
||||||
|
noteUuid?: string,
|
||||||
|
noteTitle?: string
|
||||||
|
) {
|
||||||
|
this.application = application;
|
||||||
|
if (noteUuid) {
|
||||||
|
this.note = application.findItem(noteUuid) as SNNote;
|
||||||
|
} else {
|
||||||
|
this.reset(noteTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeStreamObserver = this.application.streamItems(
|
||||||
|
ContentType.Note,
|
||||||
|
async (items, source) => {
|
||||||
|
await this.handleNoteStream(items as SNNote[], source);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleNoteStream(notes: SNNote[], source?: PayloadSource) {
|
||||||
|
/** Update our note object reference whenever it changes */
|
||||||
|
const matchingNote = notes.find((item) => {
|
||||||
|
return item.uuid === this.note.uuid;
|
||||||
|
}) as SNNote;
|
||||||
|
if (matchingNote) {
|
||||||
|
this.isTemplateNote = false;
|
||||||
|
this.note = matchingNote;
|
||||||
|
this._onNoteValueChange!(matchingNote, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async insertTemplatedNote() {
|
||||||
|
return this.application.insertItem(this.note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverts the editor to a blank state, removing any existing note from view,
|
||||||
|
* and creating a placeholder note.
|
||||||
|
*/
|
||||||
|
async reset(noteTitle?: string) {
|
||||||
|
const note = await this.application.createTemplateItem(
|
||||||
|
ContentType.Note,
|
||||||
|
{
|
||||||
|
text: '',
|
||||||
|
title: noteTitle || '',
|
||||||
|
references: []
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.isTemplateNote = true;
|
||||||
|
this.setNote(note as SNNote);
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.removeStreamObserver();
|
||||||
|
(this.removeStreamObserver as any) = undefined;
|
||||||
|
this._onNoteChange = undefined;
|
||||||
|
(this.application as any) = undefined;
|
||||||
|
this._onNoteChange = undefined;
|
||||||
|
this._onNoteValueChange = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register to be notified when the editor's note changes.
|
||||||
|
*/
|
||||||
|
public onNoteChange(onNoteChange: () => void) {
|
||||||
|
this._onNoteChange = onNoteChange;
|
||||||
|
if (this.note) {
|
||||||
|
onNoteChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register to be notified when the editor's note's values change
|
||||||
|
* (and thus a new object reference is created)
|
||||||
|
*/
|
||||||
|
public onNoteValueChange(
|
||||||
|
onNoteValueChange: (note: SNNote, source?: PayloadSource) => void
|
||||||
|
) {
|
||||||
|
this._onNoteValueChange = onNoteValueChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the editor contents by setting its note.
|
||||||
|
*/
|
||||||
|
public setNote(note: SNNote) {
|
||||||
|
this.note = note;
|
||||||
|
if (this._onNoteChange) {
|
||||||
|
this._onNoteChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
app/assets/javascripts/ui_models/editor_group.ts
Normal file
69
app/assets/javascripts/ui_models/editor_group.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { removeFromArray } from '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 any) = undefined;
|
||||||
|
for (const editor of this.editors) {
|
||||||
|
this.deleteEditor(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createEditor(noteUuid?: string, noteTitle?: string) {
|
||||||
|
const editor = new Editor(this.application, noteUuid, noteTitle);
|
||||||
|
this.editors.push(editor);
|
||||||
|
this.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteEditor(editor: Editor) {
|
||||||
|
editor.deinit();
|
||||||
|
removeFromArray(this.editors, editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeEditor(editor: Editor) {
|
||||||
|
this.deleteEditor(editor);
|
||||||
|
this.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeActiveEditor() {
|
||||||
|
this.deleteEditor(this.editors[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifyObservers() {
|
||||||
|
for (const observer of this.changeObservers) {
|
||||||
|
observer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import { AppStateEvent } from '@/services/state';
|
|
||||||
import { WebApplication } from './../../application';
|
|
||||||
import { ApplicationEvent } from 'snjs';
|
import { ApplicationEvent } from 'snjs';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
|
||||||
export type CtrlState = Partial<Record<string, any>>
|
export type CtrlState = Partial<Record<string, any>>
|
||||||
export type CtrlProps = Partial<Record<string, any>>
|
export type CtrlProps = Partial<Record<string, any>>
|
||||||
|
|
||||||
export class PureCtrl {
|
export class PureViewCtrl {
|
||||||
$timeout: ng.ITimeoutService
|
$timeout: ng.ITimeoutService
|
||||||
/** Passed through templates */
|
/** Passed through templates */
|
||||||
application?: WebApplication
|
application?: WebApplication
|
||||||
@@ -5,11 +5,13 @@
|
|||||||
ng-class='self.state.appClass',
|
ng-class='self.state.appClass',
|
||||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||||
)
|
)
|
||||||
tags-panel(application='self.application')
|
tags-view(application='self.application')
|
||||||
notes-panel(application='self.application')
|
notes-view(application='self.application')
|
||||||
editor-panel(application='self.application')
|
editor-group-view(
|
||||||
|
application='self.application'
|
||||||
|
)
|
||||||
|
|
||||||
footer(
|
footer-view(
|
||||||
ng-if='!self.state.needsUnlock && self.state.ready'
|
ng-if='!self.state.needsUnlock && self.state.ready'
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { PanelPuppet, WebDirective, PermissionsModalScope, ModalComponentScope } from './../types';
|
import { WebDirective, PermissionsModalScope, ModalComponentScope } from '@/types';
|
||||||
import { getPlatformString } from '@/utils';
|
import { getPlatformString } from '@/utils';
|
||||||
import template from '%/application-view.pug';
|
import template from './application-view.pug';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { ApplicationEvent, SNComponent } from 'snjs';
|
import { ApplicationEvent, SNComponent } from 'snjs';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import {
|
import {
|
||||||
PANEL_NAME_NOTES,
|
PANEL_NAME_NOTES,
|
||||||
PANEL_NAME_TAGS
|
PANEL_NAME_TAGS
|
||||||
} from '@/controllers/constants';
|
} from '@/views/constants';
|
||||||
import {
|
import {
|
||||||
STRING_SESSION_EXPIRED,
|
STRING_SESSION_EXPIRED,
|
||||||
STRING_DEFAULT_FILE_ERROR
|
STRING_DEFAULT_FILE_ERROR
|
||||||
} from '@/strings';
|
} from '@/strings';
|
||||||
import { PureCtrl } from './abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { PermissionDialog } from '@/../../../../snjs/dist/@types/services/component_manager';
|
import { PermissionDialog } from '@/../../../../snjs/dist/@types/services/component_manager';
|
||||||
|
|
||||||
class ApplicationViewCtrl extends PureCtrl {
|
class ApplicationViewCtrl extends PureViewCtrl {
|
||||||
private $compile?: ng.ICompileService
|
private $compile?: ng.ICompileService
|
||||||
private $location?: ng.ILocationService
|
private $location?: ng.ILocationService
|
||||||
private $rootScope?: ng.IRootScopeService
|
private $rootScope?: ng.IRootScopeService
|
||||||
@@ -47,7 +47,7 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
this.presentPermissionsDialog = this.presentPermissionsDialog.bind(this);
|
this.presentPermissionsDialog = this.presentPermissionsDialog.bind(this);
|
||||||
this.addDragDropHandlers();
|
this.addDragDropHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
this.$location = undefined;
|
this.$location = undefined;
|
||||||
this.$rootScope = undefined;
|
this.$rootScope = undefined;
|
||||||
@@ -61,7 +61,7 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
(this.presentPermissionsDialog as any) = undefined;
|
(this.presentPermissionsDialog as any) = undefined;
|
||||||
super.deinit();
|
super.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
super.$onInit();
|
super.$onInit();
|
||||||
this.loadApplication();
|
this.loadApplication();
|
||||||
@@ -226,7 +226,7 @@ class ApplicationViewCtrl extends PureCtrl {
|
|||||||
scope.component = dialog.component;
|
scope.component = dialog.component;
|
||||||
scope.callback = dialog.callback;
|
scope.callback = dialog.callback;
|
||||||
const el = this.$compile!(
|
const el = this.$compile!(
|
||||||
"<permissions-modal component='component' permissions-string='permissionsString'"
|
"<permissions-modal component='component' permissions-string='permissionsString'"
|
||||||
+ " callback='callback' class='sk-modal'></permissions-modal>"
|
+ " callback='callback' class='sk-modal'></permissions-modal>"
|
||||||
)(scope as any);
|
)(scope as any);
|
||||||
angular.element(document.body).append(el);
|
angular.element(document.body).append(el);
|
||||||
@@ -310,7 +310,8 @@ export class ApplicationView extends WebDirective {
|
|||||||
this.controller = ApplicationViewCtrl;
|
this.controller = ApplicationViewCtrl;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = {
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
application: '='
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { ApplicationGroup } from '@/ui_models/application_group';
|
||||||
|
import { WebDirective } from '@/types';
|
||||||
|
import template from './application-group-view.pug';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
|
||||||
|
class ApplicationGroupViewCtrl {
|
||||||
|
|
||||||
|
private $timeout: ng.ITimeoutService
|
||||||
|
private applicationGroup: ApplicationGroup
|
||||||
|
public applications: WebApplication[] = []
|
||||||
|
|
||||||
|
/* @ngInject */
|
||||||
|
constructor(
|
||||||
|
$timeout: ng.ITimeoutService,
|
||||||
|
mainApplicationGroup: ApplicationGroup
|
||||||
|
) {
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
this.applicationGroup = mainApplicationGroup;
|
||||||
|
this.applicationGroup.addApplicationChangeObserver(() => {
|
||||||
|
this.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
this.$timeout(() => {
|
||||||
|
this.applications = this.applicationGroup.getApplications();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApplicationGroupView extends WebDirective {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = template;
|
||||||
|
this.controller = ApplicationGroupViewCtrl;
|
||||||
|
this.replace = true;
|
||||||
|
this.controllerAs = 'self';
|
||||||
|
this.bindToController = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
| {{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.state.note && !self.state.note.errorDecrypting'
|
ng-show='self.note && !self.note.errorDecrypting'
|
||||||
)
|
)
|
||||||
.title
|
.title
|
||||||
input#note-title-editor.input(
|
input#note-title-editor.input(
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
spellcheck='false',
|
spellcheck='false',
|
||||||
type='text'
|
type='text'
|
||||||
)
|
)
|
||||||
.sn-component(ng-if='self.state.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(
|
||||||
@@ -65,12 +65,12 @@
|
|||||||
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.state.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.state.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()',
|
||||||
@@ -81,11 +81,11 @@
|
|||||||
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.state.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.state.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'"
|
||||||
@@ -94,22 +94,22 @@
|
|||||||
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.state.note.trashed && !self.state.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.state.note.trashed && self.state.note.errorDecrypting',
|
ng-show='!self.note.trashed && self.note.errorDecrypting',
|
||||||
stylekit-class="'danger'"
|
stylekit-class="'danger'"
|
||||||
)
|
)
|
||||||
div(ng-if='self.state.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.state.note.trashed',
|
ng-show='self.note.trashed',
|
||||||
stylekit-class="'info'"
|
stylekit-class="'info'"
|
||||||
)
|
)
|
||||||
menu-row(
|
menu-row(
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
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.state.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'"
|
||||||
)
|
)
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
.sk-label Editor
|
.sk-label Editor
|
||||||
editor-menu(
|
editor-menu(
|
||||||
callback='self.editorMenuOnSelect()',
|
callback='self.editorMenuOnSelect()',
|
||||||
current-item='self.state.note',
|
current-item='self.note',
|
||||||
ng-if='self.state.showEditorMenu',
|
ng-if='self.state.showEditorMenu',
|
||||||
selected-editor='self.state.selectedEditor',
|
selected-editor='self.state.selectedEditor',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
)
|
)
|
||||||
.sk-label Actions
|
.sk-label Actions
|
||||||
actions-menu(
|
actions-menu(
|
||||||
item='self.state.note',
|
item='self.note',
|
||||||
ng-if='self.state.showExtensions',
|
ng-if='self.state.showExtensions',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
@@ -188,12 +188,12 @@
|
|||||||
)
|
)
|
||||||
.sk-label Session History
|
.sk-label Session History
|
||||||
session-history-menu(
|
session-history-menu(
|
||||||
item='self.state.note',
|
item='self.note',
|
||||||
ng-if='self.state.showSessionHistory',
|
ng-if='self.state.showSessionHistory',
|
||||||
application='self.application'
|
application='self.application'
|
||||||
)
|
)
|
||||||
#editor-content.editor-content(
|
#editor-content.editor-content(
|
||||||
ng-if='self.state.noteReady && !self.state.note.errorDecrypting'
|
ng-if='self.state.noteReady && !self.note.errorDecrypting'
|
||||||
)
|
)
|
||||||
panel-resizer.left(
|
panel-resizer.left(
|
||||||
control='self.leftPanelPuppet',
|
control='self.leftPanelPuppet',
|
||||||
@@ -231,11 +231,11 @@
|
|||||||
panel-id="'editor-content'",
|
panel-id="'editor-content'",
|
||||||
property="'right'"
|
property="'right'"
|
||||||
)
|
)
|
||||||
.section(ng-show='self.state.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.state.note')
|
#editor-pane-component-stack(ng-show='self.note')
|
||||||
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='self.state.componentStack.length')
|
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='self.state.componentStack.length')
|
||||||
.left
|
.left
|
||||||
.sk-app-bar-item(
|
.sk-app-bar-item(
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { WebApplication } from './../application';
|
import { Editor } from '@/ui_models/editor';
|
||||||
import { PanelPuppet, WebDirective } from './../types';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
import { PanelPuppet, WebDirective } from '@/types';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import {
|
import {
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
@@ -19,8 +20,8 @@ import {
|
|||||||
import find from 'lodash/find';
|
import find from 'lodash/find';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
||||||
import template from '%/editor.pug';
|
import template from './editor-view.pug';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { AppStateEvent, EventSource } from '@/services/state';
|
import { AppStateEvent, EventSource } from '@/services/state';
|
||||||
import {
|
import {
|
||||||
STRING_DELETED_NOTE,
|
STRING_DELETED_NOTE,
|
||||||
@@ -39,12 +40,6 @@ const SAVE_TIMEOUT_DEBOUNCE = 350;
|
|||||||
const SAVE_TIMEOUT_NO_DEBOUNCE = 100;
|
const SAVE_TIMEOUT_NO_DEBOUNCE = 100;
|
||||||
const EDITOR_DEBOUNCE = 200;
|
const EDITOR_DEBOUNCE = 200;
|
||||||
|
|
||||||
const AppDataKeys = {
|
|
||||||
Pinned: 'pinned',
|
|
||||||
Locked: 'locked',
|
|
||||||
Archived: 'archived',
|
|
||||||
PrefersPlainEditor: 'prefersPlainEditor'
|
|
||||||
};
|
|
||||||
const ElementIds = {
|
const ElementIds = {
|
||||||
NoteTextEditor: 'note-text-editor',
|
NoteTextEditor: 'note-text-editor',
|
||||||
NoteTitleEditor: 'note-title-editor',
|
NoteTitleEditor: 'note-title-editor',
|
||||||
@@ -63,9 +58,8 @@ type NoteStatus = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EditorState = {
|
type EditorState = {
|
||||||
note: SNNote
|
|
||||||
saveError?: any
|
saveError?: any
|
||||||
selectedEditor?: SNComponent
|
editorComponent?: SNComponent
|
||||||
noteStatus?: NoteStatus
|
noteStatus?: NoteStatus
|
||||||
tagsAsStrings?: string
|
tagsAsStrings?: string
|
||||||
marginResizersEnabled?: boolean
|
marginResizersEnabled?: boolean
|
||||||
@@ -73,6 +67,12 @@ type EditorState = {
|
|||||||
isDesktop?: boolean
|
isDesktop?: boolean
|
||||||
tagsComponent?: SNComponent
|
tagsComponent?: SNComponent
|
||||||
componentStack?: SNComponent[]
|
componentStack?: SNComponent[]
|
||||||
|
syncTakingTooLong: boolean
|
||||||
|
showExtensions: boolean
|
||||||
|
noteReady: boolean
|
||||||
|
showOptionsMenu: boolean
|
||||||
|
altKeyDown: boolean
|
||||||
|
spellcheck: boolean
|
||||||
/** Fields that can be directly mutated by the template */
|
/** Fields that can be directly mutated by the template */
|
||||||
mutable: {}
|
mutable: {}
|
||||||
}
|
}
|
||||||
@@ -83,9 +83,16 @@ type EditorValues = {
|
|||||||
tagsInputValue?: string
|
tagsInputValue?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorCtrl extends PureCtrl {
|
interface EditorViewScope {
|
||||||
|
application: WebApplication
|
||||||
|
editor: Editor
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
||||||
/** Passed through template */
|
/** Passed through template */
|
||||||
readonly application!: WebApplication
|
readonly application!: WebApplication
|
||||||
|
readonly editor!: Editor
|
||||||
|
|
||||||
private leftPanelPuppet?: PanelPuppet
|
private leftPanelPuppet?: PanelPuppet
|
||||||
private rightPanelPuppet?: PanelPuppet
|
private rightPanelPuppet?: PanelPuppet
|
||||||
private unregisterComponent: any
|
private unregisterComponent: any
|
||||||
@@ -150,9 +157,23 @@ class EditorCtrl extends PureCtrl {
|
|||||||
return this.state as EditorState;
|
return this.state as EditorState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get note() {
|
||||||
|
return this.editor.note;
|
||||||
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
super.$onInit();
|
super.$onInit();
|
||||||
this.registerKeyboardShortcuts();
|
this.registerKeyboardShortcuts();
|
||||||
|
this.editor.onNoteChange(() => {
|
||||||
|
this.handleEditorNoteChange();
|
||||||
|
})
|
||||||
|
this.editor.onNoteValueChange((note, source) => {
|
||||||
|
if (isPayloadSourceRetrieved(source!)) {
|
||||||
|
this.editorValues.title = note.title;
|
||||||
|
this.editorValues.text = note.text;
|
||||||
|
this.reloadTagsString();
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
@@ -168,6 +189,10 @@ class EditorCtrl extends PureCtrl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setEditorState(state: Partial<EditorState>) {
|
||||||
|
return this.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
async onAppLaunch() {
|
async onAppLaunch() {
|
||||||
await super.onAppLaunch();
|
await super.onAppLaunch();
|
||||||
this.streamItems();
|
this.streamItems();
|
||||||
@@ -176,29 +201,21 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppStateEvent(eventName: AppStateEvent, data: any) {
|
onAppStateEvent(eventName: AppStateEvent, data: any) {
|
||||||
if (eventName === AppStateEvent.NoteChanged) {
|
if (eventName === AppStateEvent.PreferencesChanged) {
|
||||||
this.handleNoteSelectionChange(
|
|
||||||
this.application.getAppState().getSelectedNote()!,
|
|
||||||
data.previousNote
|
|
||||||
);
|
|
||||||
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppEvent(eventName: ApplicationEvent) {
|
onAppEvent(eventName: ApplicationEvent) {
|
||||||
if (!this.getState().note) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (eventName === ApplicationEvent.HighLatencySync) {
|
if (eventName === ApplicationEvent.HighLatencySync) {
|
||||||
this.setState({ syncTakingTooLong: true });
|
this.setEditorState({ syncTakingTooLong: true });
|
||||||
} else if (eventName === ApplicationEvent.CompletedSync) {
|
} else if (eventName === ApplicationEvent.CompletedSync) {
|
||||||
this.setState({ syncTakingTooLong: false });
|
this.setEditorState({ syncTakingTooLong: false });
|
||||||
if (this.getState().note.dirty) {
|
if (this.note.dirty) {
|
||||||
/** 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. */
|
||||||
} else {
|
} else {
|
||||||
const saved = this.getState().note.lastSyncEnd! > this.getState().note.lastSyncBegan!;
|
const saved = this.note.lastSyncEnd! > this.note.lastSyncBegan!;
|
||||||
const isInErrorState = this.getState().saveError;
|
const isInErrorState = this.getState().saveError;
|
||||||
if (isInErrorState || saved) {
|
if (isInErrorState || saved) {
|
||||||
this.showAllChangesSavedStatus();
|
this.showAllChangesSavedStatus();
|
||||||
@@ -210,7 +227,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
* Otherwise, it means the originating sync came from somewhere else
|
* Otherwise, it means the originating sync came from somewhere else
|
||||||
* and we don't want to display an error here.
|
* and we don't want to display an error here.
|
||||||
*/
|
*/
|
||||||
if (this.getState().note.dirty) {
|
if (this.note.dirty) {
|
||||||
this.showErrorStatus();
|
this.showErrorStatus();
|
||||||
}
|
}
|
||||||
} else if (eventName === ApplicationEvent.LocalDatabaseWriteError) {
|
} else if (eventName === ApplicationEvent.LocalDatabaseWriteError) {
|
||||||
@@ -221,6 +238,50 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleEditorNoteChange() {
|
||||||
|
const note = this.editor.note;
|
||||||
|
await this.setEditorState({
|
||||||
|
showExtensions: false,
|
||||||
|
showOptionsMenu: false,
|
||||||
|
altKeyDown: false,
|
||||||
|
noteStatus: undefined
|
||||||
|
});
|
||||||
|
this.editorValues.title = note.title;
|
||||||
|
this.editorValues.text = note.text;
|
||||||
|
if (!note) {
|
||||||
|
this.setEditorState({
|
||||||
|
noteReady: false
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const associatedEditor = this.editorForNote(note);
|
||||||
|
if (associatedEditor && associatedEditor !== this.getState().editorComponent) {
|
||||||
|
/**
|
||||||
|
* Setting note to not ready will remove the editor from view in a flash,
|
||||||
|
* so we only want to do this if switching between external editors
|
||||||
|
*/
|
||||||
|
this.setEditorState({
|
||||||
|
noteReady: false,
|
||||||
|
editorComponent: associatedEditor
|
||||||
|
});
|
||||||
|
} else if (!associatedEditor) {
|
||||||
|
/** No editor */
|
||||||
|
this.setEditorState({
|
||||||
|
editorComponent: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await this.setEditorState({
|
||||||
|
noteReady: true,
|
||||||
|
});
|
||||||
|
this.reloadTagsString();
|
||||||
|
this.reloadPreferences();
|
||||||
|
if (note.safeText().length === 0) {
|
||||||
|
this.focusTitle();
|
||||||
|
}
|
||||||
|
this.reloadComponentContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,
|
||||||
@@ -230,57 +291,24 @@ class EditorCtrl extends PureCtrl {
|
|||||||
* on a deleted note.
|
* on a deleted note.
|
||||||
*/
|
*/
|
||||||
get noteLocked() {
|
get noteLocked() {
|
||||||
if (!this.getState().note || this.getState().note.deleted) {
|
if (!this.note || this.note.deleted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.getState().note.locked;
|
return this.note.locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamItems() {
|
streamItems() {
|
||||||
this.application.streamItems(
|
|
||||||
ContentType.Note,
|
|
||||||
async (items, source) => {
|
|
||||||
const currentNote = this.getState().note;
|
|
||||||
if (!currentNote) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const matchingNote = items.find((item) => {
|
|
||||||
return item.uuid === currentNote.uuid;
|
|
||||||
}) as SNNote;
|
|
||||||
if (!matchingNote) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (matchingNote?.deleted) {
|
|
||||||
await this.setState({
|
|
||||||
note: undefined,
|
|
||||||
noteReady: false
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
await this.setState({
|
|
||||||
note: matchingNote
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!isPayloadSourceRetrieved(source!)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.editorValues.title = matchingNote.title;
|
|
||||||
this.editorValues.text = matchingNote.text;
|
|
||||||
this.reloadTagsString();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
this.application.streamItems(
|
this.application.streamItems(
|
||||||
ContentType.Tag,
|
ContentType.Tag,
|
||||||
(items) => {
|
(items) => {
|
||||||
if (!this.getState().note) {
|
if (!this.note) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const tag of items) {
|
for (const tag of items) {
|
||||||
if (
|
if (
|
||||||
!this.editorValues.tagsInputValue ||
|
!this.editorValues.tagsInputValue ||
|
||||||
tag.deleted ||
|
tag.deleted ||
|
||||||
tag.hasRelationshipWithItem(this.getState().note)
|
tag.hasRelationshipWithItem(this.note)
|
||||||
) {
|
) {
|
||||||
this.reloadTagsString();
|
this.reloadTagsString();
|
||||||
break;
|
break;
|
||||||
@@ -293,7 +321,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
ContentType.Component,
|
ContentType.Component,
|
||||||
async (items) => {
|
async (items) => {
|
||||||
const components = items as SNComponent[];
|
const components = items as SNComponent[];
|
||||||
if (!this.getState().note) {
|
if (!this.note) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/** Reload componentStack in case new ones were added or removed */
|
/** Reload componentStack in case new ones were added or removed */
|
||||||
@@ -306,9 +334,9 @@ class EditorCtrl extends PureCtrl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/** Find the most recent editor for note */
|
/** Find the most recent editor for note */
|
||||||
const editor = this.editorForNote(this.getState().note);
|
const editor = this.editorForNote(this.note);
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
selectedEditor: editor
|
editorComponent: editor
|
||||||
});
|
});
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
@@ -317,62 +345,12 @@ class EditorCtrl extends PureCtrl {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleNoteSelectionChange(note: SNNote, previousNote?: SNNote) {
|
|
||||||
await this.setState({
|
|
||||||
note: note,
|
|
||||||
showExtensions: false,
|
|
||||||
showOptionsMenu: false,
|
|
||||||
altKeyDown: false,
|
|
||||||
noteStatus: null
|
|
||||||
});
|
|
||||||
this.editorValues.title = note.title;
|
|
||||||
this.editorValues.text = note.text;
|
|
||||||
if (!note) {
|
|
||||||
this.setState({
|
|
||||||
noteReady: false
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const associatedEditor = this.editorForNote(note);
|
|
||||||
if (associatedEditor && associatedEditor !== this.getState().selectedEditor) {
|
|
||||||
/**
|
|
||||||
* Setting note to not ready will remove the editor from view in a flash,
|
|
||||||
* so we only want to do this if switching between external editors
|
|
||||||
*/
|
|
||||||
this.setState({
|
|
||||||
noteReady: false,
|
|
||||||
selectedEditor: associatedEditor
|
|
||||||
});
|
|
||||||
} else if (!associatedEditor) {
|
|
||||||
/** No editor */
|
|
||||||
this.setState({
|
|
||||||
selectedEditor: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await this.setState({
|
|
||||||
noteReady: true,
|
|
||||||
});
|
|
||||||
this.reloadTagsString();
|
|
||||||
this.reloadPreferences();
|
|
||||||
|
|
||||||
if (note.dummy) {
|
|
||||||
this.focusTitle();
|
|
||||||
}
|
|
||||||
if (previousNote && previousNote !== note) {
|
|
||||||
if (previousNote.dummy) {
|
|
||||||
this.performNoteDeletion(previousNote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.reloadComponentContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
editorForNote(note: SNNote) {
|
editorForNote(note: SNNote) {
|
||||||
return this.application.componentManager!.editorForNote(note);
|
return this.application.componentManager!.editorForNote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMenuState(menu: string, state: boolean) {
|
setMenuState(menu: string, state: boolean) {
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
[menu]: state
|
[menu]: state
|
||||||
});
|
});
|
||||||
this.closeAllMenus(menu);
|
this.closeAllMenus(menu);
|
||||||
@@ -395,7 +373,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
menuState[candidate] = false;
|
menuState[candidate] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState(menuState);
|
this.setEditorState(menuState);
|
||||||
}
|
}
|
||||||
|
|
||||||
editorMenuOnSelect(component: SNComponent) {
|
editorMenuOnSelect(component: SNComponent) {
|
||||||
@@ -403,10 +381,10 @@ class EditorCtrl extends PureCtrl {
|
|||||||
/** If plain editor or other editor */
|
/** If plain editor or other editor */
|
||||||
this.setMenuState('showEditorMenu', false);
|
this.setMenuState('showEditorMenu', false);
|
||||||
const editor = component;
|
const editor = component;
|
||||||
if (this.getState().selectedEditor && editor !== this.getState().selectedEditor) {
|
if (this.getState().editorComponent && editor !== this.getState().editorComponent) {
|
||||||
this.disassociateComponentWithCurrentNote(this.getState().selectedEditor!);
|
this.disassociateComponentWithCurrentNote(this.getState().editorComponent!);
|
||||||
}
|
}
|
||||||
const note = this.getState().note;
|
const note = this.note;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
const prefersPlain = note.prefersPlainEditor;
|
const prefersPlain = note.prefersPlainEditor;
|
||||||
if (prefersPlain) {
|
if (prefersPlain) {
|
||||||
@@ -427,8 +405,8 @@ class EditorCtrl extends PureCtrl {
|
|||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
selectedEditor: editor
|
editorComponent: editor
|
||||||
});
|
});
|
||||||
} else if (component.area === 'editor-stack') {
|
} else if (component.area === 'editor-stack') {
|
||||||
this.toggleStackComponentForCurrentItem(component);
|
this.toggleStackComponentForCurrentItem(component);
|
||||||
@@ -440,7 +418,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
hasAvailableExtensions() {
|
hasAvailableExtensions() {
|
||||||
return this.application.actionsManager!.
|
return this.application.actionsManager!.
|
||||||
extensionsInContextOfItem(this.getState().note).length > 0;
|
extensionsInContextOfItem(this.note).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
performFirefoxPinnedTabFix() {
|
performFirefoxPinnedTabFix() {
|
||||||
@@ -454,14 +432,14 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveNote(
|
async saveNote(
|
||||||
bypassDebouncer = false,
|
bypassDebouncer = false,
|
||||||
isUserModified = false,
|
isUserModified = false,
|
||||||
dontUpdatePreviews = false,
|
dontUpdatePreviews = false,
|
||||||
customMutate?: (mutator: NoteMutator) => void
|
customMutate?: (mutator: NoteMutator) => void
|
||||||
) {
|
) {
|
||||||
this.performFirefoxPinnedTabFix();
|
this.performFirefoxPinnedTabFix();
|
||||||
const note = this.getState().note;
|
const note = this.note;
|
||||||
|
|
||||||
if (note.deleted) {
|
if (note.deleted) {
|
||||||
this.application.alertService!.alert(
|
this.application.alertService!.alert(
|
||||||
@@ -469,15 +447,16 @@ class EditorCtrl extends PureCtrl {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.editor.isTemplateNote) {
|
||||||
|
await this.editor.insertTemplatedNote();
|
||||||
|
}
|
||||||
if (!this.application.findItem(note.uuid)) {
|
if (!this.application.findItem(note.uuid)) {
|
||||||
this.application.alertService!.alert(
|
this.application.alertService!.alert(
|
||||||
STRING_INVALID_NOTE
|
STRING_INVALID_NOTE
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showSavingStatus();
|
this.showSavingStatus();
|
||||||
|
|
||||||
this.application.changeItem(note.uuid, (mutator) => {
|
this.application.changeItem(note.uuid, (mutator) => {
|
||||||
const noteMutator = mutator as NoteMutator;
|
const noteMutator = mutator as NoteMutator;
|
||||||
if (customMutate) {
|
if (customMutate) {
|
||||||
@@ -516,7 +495,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showAllChangesSavedStatus() {
|
showAllChangesSavedStatus() {
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
saveError: false,
|
saveError: false,
|
||||||
syncTakingTooLong: false
|
syncTakingTooLong: false
|
||||||
});
|
});
|
||||||
@@ -532,7 +511,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
desc: "Changes saved offline"
|
desc: "Changes saved offline"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
saveError: true,
|
saveError: true,
|
||||||
syncTakingTooLong: false
|
syncTakingTooLong: false
|
||||||
});
|
});
|
||||||
@@ -541,11 +520,11 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
setStatus(status: { message: string, date?: Date }, wait = true) {
|
setStatus(status: { message: string, date?: Date }, wait = true) {
|
||||||
let waitForMs;
|
let waitForMs;
|
||||||
if (!this.getState().noteStatus || !this.getState().noteStatus!.date) {
|
if (!this.state.noteStatus || !this.state.noteStatus!.date) {
|
||||||
waitForMs = 0;
|
waitForMs = 0;
|
||||||
} else {
|
} else {
|
||||||
waitForMs = MINIMUM_STATUS_DURATION - (
|
waitForMs = MINIMUM_STATUS_DURATION - (
|
||||||
new Date().getTime() - this.getState().noteStatus!.date!.getTime()
|
new Date().getTime() - this.state.noteStatus!.date!.getTime()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!wait || waitForMs < 0) {
|
if (!wait || waitForMs < 0) {
|
||||||
@@ -556,7 +535,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
this.statusTimeout = this.$timeout(() => {
|
this.statusTimeout = this.$timeout(() => {
|
||||||
status.date = new Date();
|
status.date = new Date();
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
noteStatus: status
|
noteStatus: status
|
||||||
});
|
});
|
||||||
}, waitForMs);
|
}, waitForMs);
|
||||||
@@ -619,21 +598,21 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteNote(permanently: boolean) {
|
async deleteNote(permanently: boolean) {
|
||||||
if (this.getState().note.dummy) {
|
if (this.editor.isTemplateNote) {
|
||||||
this.application.alertService!.alert(
|
this.application.alertService!.alert(
|
||||||
STRING_DELETE_PLACEHOLDER_ATTEMPT
|
STRING_DELETE_PLACEHOLDER_ATTEMPT
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const run = () => {
|
const run = () => {
|
||||||
if (this.getState().note.locked) {
|
if (this.note.locked) {
|
||||||
this.application.alertService!.alert(
|
this.application.alertService!.alert(
|
||||||
STRING_DELETE_LOCKED_ATTEMPT
|
STRING_DELETE_LOCKED_ATTEMPT
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const title = this.getState().note.safeTitle().length
|
const title = this.note.safeTitle().length
|
||||||
? `'${this.getState().note.title}'`
|
? `'${this.note.title}'`
|
||||||
: "this note";
|
: "this note";
|
||||||
const text = StringDeleteNote(
|
const text = StringDeleteNote(
|
||||||
title,
|
title,
|
||||||
@@ -646,7 +625,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
undefined,
|
undefined,
|
||||||
() => {
|
() => {
|
||||||
if (permanently) {
|
if (permanently) {
|
||||||
this.performNoteDeletion(this.getState().note);
|
this.performNoteDeletion(this.note);
|
||||||
} else {
|
} else {
|
||||||
this.saveNote(
|
this.saveNote(
|
||||||
true,
|
true,
|
||||||
@@ -657,8 +636,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.application.getAppState().setSelectedNote(undefined);
|
this.appState.closeEditor(this.editor);
|
||||||
this.setMenuState('showOptionsMenu', false);
|
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
@@ -681,16 +659,6 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
performNoteDeletion(note: SNNote) {
|
performNoteDeletion(note: SNNote) {
|
||||||
this.application.deleteItem(note);
|
this.application.deleteItem(note);
|
||||||
if (note === this.getState().note) {
|
|
||||||
this.setState({
|
|
||||||
note: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (note.dummy) {
|
|
||||||
this.application.deleteItemLocally(note);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.application.sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreTrashedNote() {
|
restoreTrashedNote() {
|
||||||
@@ -702,7 +670,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
mutator.trashed = false;
|
mutator.trashed = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.application.getAppState().setSelectedNote(undefined);
|
this.appState.closeEditor(this.editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteNotePermanantely() {
|
deleteNotePermanantely() {
|
||||||
@@ -735,7 +703,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.pinned = !this.getState().note.pinned
|
mutator.pinned = !this.note.pinned
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -746,7 +714,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.locked = !this.getState().note.locked
|
mutator.locked = !this.note.locked
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -757,7 +725,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.protected = !this.getState().note.protected
|
mutator.protected = !this.note.protected
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
/** Show privileges manager if protection is not yet set up */
|
/** Show privileges manager if protection is not yet set up */
|
||||||
@@ -776,7 +744,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.hidePreview = !this.getState().note.hidePreview
|
mutator.hidePreview = !this.note.hidePreview
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -787,21 +755,21 @@ class EditorCtrl extends PureCtrl {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.archived = !this.getState().note.archived
|
mutator.archived = !this.note.archived
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadTagsString() {
|
reloadTagsString() {
|
||||||
const tags = this.appState.getNoteTags(this.getState().note);
|
const tags = this.appState.getNoteTags(this.note);
|
||||||
const string = SNTag.arrayToDisplayString(tags);
|
const string = SNTag.arrayToDisplayString(tags);
|
||||||
this.updateUI(() => {
|
this.updateUI(() => {
|
||||||
this.editorValues.tagsInputValue = string;
|
this.editorValues.tagsInputValue = string;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addTag(tag: SNTag) {
|
private addTag(tag: SNTag) {
|
||||||
const tags = this.appState.getNoteTags(this.getState().note);
|
const tags = this.appState.getNoteTags(this.note);
|
||||||
const strings = tags.map((currentTag) => {
|
const strings = tags.map((currentTag) => {
|
||||||
return currentTag.title;
|
return currentTag.title;
|
||||||
});
|
});
|
||||||
@@ -810,7 +778,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeTag(tag: SNTag) {
|
removeTag(tag: SNTag) {
|
||||||
const tags = this.appState.getNoteTags(this.getState().note);
|
const tags = this.appState.getNoteTags(this.note);
|
||||||
const strings = tags.map((currentTag) => {
|
const strings = tags.map((currentTag) => {
|
||||||
return currentTag.title;
|
return currentTag.title;
|
||||||
}).filter((title) => {
|
}).filter((title) => {
|
||||||
@@ -819,7 +787,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
this.saveTagsFromStrings(strings);
|
this.saveTagsFromStrings(strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveTagsFromStrings(strings?: string[]) {
|
public async saveTagsFromStrings(strings?: string[]) {
|
||||||
if (
|
if (
|
||||||
!strings
|
!strings
|
||||||
&& this.editorValues.tagsInputValue === this.getState().tagsAsStrings
|
&& this.editorValues.tagsInputValue === this.getState().tagsAsStrings
|
||||||
@@ -836,10 +804,8 @@ class EditorCtrl extends PureCtrl {
|
|||||||
return string.trim();
|
return string.trim();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const note = this.note;
|
||||||
const note = this.getState().note;
|
|
||||||
const currentTags = this.appState.getNoteTags(note);
|
const currentTags = this.appState.getNoteTags(note);
|
||||||
|
|
||||||
const removeTags = [];
|
const removeTags = [];
|
||||||
for (const tag of currentTags) {
|
for (const tag of currentTags) {
|
||||||
if (strings.indexOf(tag.title) === -1) {
|
if (strings.indexOf(tag.title) === -1) {
|
||||||
@@ -907,7 +873,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
WebPrefKey.EditorResizersEnabled,
|
WebPrefKey.EditorResizersEnabled,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
monospaceEnabled,
|
monospaceEnabled,
|
||||||
spellcheck,
|
spellcheck,
|
||||||
marginResizersEnabled
|
marginResizersEnabled
|
||||||
@@ -973,10 +939,10 @@ class EditorCtrl extends PureCtrl {
|
|||||||
|
|
||||||
if (key === WebPrefKey.EditorSpellcheck) {
|
if (key === WebPrefKey.EditorSpellcheck) {
|
||||||
/** Allows textarea to reload */
|
/** Allows textarea to reload */
|
||||||
await this.setState({
|
await this.setEditorState({
|
||||||
noteReady: false
|
noteReady: false
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
noteReady: true
|
noteReady: true
|
||||||
});
|
});
|
||||||
this.reloadFont();
|
this.reloadFont();
|
||||||
@@ -1000,42 +966,42 @@ class EditorCtrl extends PureCtrl {
|
|||||||
],
|
],
|
||||||
activationHandler: (component) => {
|
activationHandler: (component) => {
|
||||||
if (component.area === 'note-tags') {
|
if (component.area === 'note-tags') {
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
tagsComponent: component.active ? component : null
|
tagsComponent: component.active ? component : undefined
|
||||||
});
|
});
|
||||||
} else if (component.area === 'editor-editor') {
|
} else if (component.area === 'editor-editor') {
|
||||||
if (
|
if (
|
||||||
component === this.getState().selectedEditor &&
|
component === this.getState().editorComponent &&
|
||||||
!component.active
|
!component.active
|
||||||
) {
|
) {
|
||||||
this.setState({ selectedEditor: null });
|
this.setEditorState({ editorComponent: undefined });
|
||||||
}
|
}
|
||||||
else if (this.getState().selectedEditor) {
|
else if (this.getState().editorComponent) {
|
||||||
if (this.getState().selectedEditor!.active && this.getState().note) {
|
if (this.getState().editorComponent!.active && this.note) {
|
||||||
if (
|
if (
|
||||||
component.isExplicitlyEnabledForItem(this.getState().note)
|
component.isExplicitlyEnabledForItem(this.note)
|
||||||
&& !this.getState().selectedEditor!.isExplicitlyEnabledForItem(this.getState().note)
|
&& !this.getState().editorComponent!.isExplicitlyEnabledForItem(this.note)
|
||||||
) {
|
) {
|
||||||
this.setState({ selectedEditor: component });
|
this.setEditorState({ editorComponent: component });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.getState().note) {
|
else if (this.note) {
|
||||||
const enableable = (
|
const enableable = (
|
||||||
component.isExplicitlyEnabledForItem(this.getState().note)
|
component.isExplicitlyEnabledForItem(this.note)
|
||||||
|| component.isDefaultEditor()
|
|| component.isDefaultEditor()
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
component.active
|
component.active
|
||||||
&& enableable
|
&& enableable
|
||||||
) {
|
) {
|
||||||
this.setState({ selectedEditor: component });
|
this.setEditorState({ editorComponent: component });
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
* Not a candidate, and no qualified editor.
|
* Not a candidate, and no qualified editor.
|
||||||
* Disable the current editor.
|
* Disable the current editor.
|
||||||
*/
|
*/
|
||||||
this.setState({ selectedEditor: null });
|
this.setEditorState({ editorComponent: undefined });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,11 +1011,11 @@ class EditorCtrl extends PureCtrl {
|
|||||||
},
|
},
|
||||||
contextRequestHandler: (component) => {
|
contextRequestHandler: (component) => {
|
||||||
if (
|
if (
|
||||||
component === this.getState().selectedEditor ||
|
component === this.getState().editorComponent ||
|
||||||
component === this.getState().tagsComponent ||
|
component === this.getState().tagsComponent ||
|
||||||
this.getState().componentStack!.includes(component)
|
this.getState().componentStack!.includes(component)
|
||||||
) {
|
) {
|
||||||
return this.getState().note;
|
return this.note;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
focusHandler: (component, focused) => {
|
focusHandler: (component, focused) => {
|
||||||
@@ -1093,7 +1059,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
else if (action === ComponentAction.SaveItems) {
|
else if (action === ComponentAction.SaveItems) {
|
||||||
const includesNote = data.items.map((item: RawPayload) => {
|
const includesNote = data.items.map((item: RawPayload) => {
|
||||||
return item.uuid;
|
return item.uuid;
|
||||||
}).includes(this.getState().note.uuid);
|
}).includes(this.note.uuid);
|
||||||
if (includesNote) {
|
if (includesNote) {
|
||||||
this.showSavingStatus();
|
this.showSavingStatus();
|
||||||
}
|
}
|
||||||
@@ -1109,19 +1075,19 @@ class EditorCtrl extends PureCtrl {
|
|||||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
componentStack: components
|
componentStack: components
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadComponentContext() {
|
reloadComponentContext() {
|
||||||
this.reloadComponentStackArray();
|
this.reloadComponentStackArray();
|
||||||
if (this.getState().note) {
|
if (this.note) {
|
||||||
for (const component of this.getState().componentStack!) {
|
for (const component of this.getState().componentStack!) {
|
||||||
if (component.active) {
|
if (component.active) {
|
||||||
this.application.componentManager!.setComponentHidden(
|
this.application.componentManager!.setComponentHidden(
|
||||||
component,
|
component,
|
||||||
!component.isExplicitlyEnabledForItem(this.getState().note)
|
!component.isExplicitlyEnabledForItem(this.note)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1148,7 +1114,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disassociateComponentWithCurrentNote(component: SNComponent) {
|
disassociateComponentWithCurrentNote(component: SNComponent) {
|
||||||
const note = this.getState().note;
|
const note = this.note;
|
||||||
this.application.changeAndSaveItem(component.uuid, (m) => {
|
this.application.changeAndSaveItem(component.uuid, (m) => {
|
||||||
const mutator = m as ComponentMutator;
|
const mutator = m as ComponentMutator;
|
||||||
mutator.removeAssociatedItemId(note.uuid);
|
mutator.removeAssociatedItemId(note.uuid);
|
||||||
@@ -1157,7 +1123,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
associateComponentWithCurrentNote(component: SNComponent) {
|
associateComponentWithCurrentNote(component: SNComponent) {
|
||||||
const note = this.getState().note;
|
const note = this.note;
|
||||||
this.application.changeAndSaveItem(component.uuid, (m) => {
|
this.application.changeAndSaveItem(component.uuid, (m) => {
|
||||||
const mutator = m as ComponentMutator;
|
const mutator = m as ComponentMutator;
|
||||||
mutator.removeDisassociatedItemId(note.uuid);
|
mutator.removeDisassociatedItemId(note.uuid);
|
||||||
@@ -1171,12 +1137,12 @@ class EditorCtrl extends PureCtrl {
|
|||||||
KeyboardModifier.Alt
|
KeyboardModifier.Alt
|
||||||
],
|
],
|
||||||
onKeyDown: () => {
|
onKeyDown: () => {
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
altKeyDown: true
|
altKeyDown: true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onKeyUp: () => {
|
onKeyUp: () => {
|
||||||
this.setState({
|
this.setEditorState({
|
||||||
altKeyDown: false
|
altKeyDown: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1189,7 @@ class EditorCtrl extends PureCtrl {
|
|||||||
element: editor,
|
element: editor,
|
||||||
key: KeyboardKey.Tab,
|
key: KeyboardKey.Tab,
|
||||||
onKeyDown: (event) => {
|
onKeyDown: (event) => {
|
||||||
if (this.getState().note.locked || event.shiftKey) {
|
if (this.note.locked || event.shiftKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -1260,16 +1226,17 @@ class EditorCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EditorPanel extends WebDirective {
|
export class EditorView extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.scope = {
|
this.scope = {
|
||||||
|
editor: '=',
|
||||||
application: '='
|
application: '='
|
||||||
};
|
};
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = EditorCtrl;
|
this.controller = EditorViewCtrl;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
editor-view(
|
||||||
|
ng-repeat='editor in self.editors'
|
||||||
|
application='self.application'
|
||||||
|
editor='editor'
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
import { WebDirective } from './../../types';
|
||||||
|
import template from './editor-group-view.pug';
|
||||||
|
import { Editor } from '@/ui_models/editor';
|
||||||
|
|
||||||
|
class EditorGroupViewCtrl {
|
||||||
|
|
||||||
|
private application!: WebApplication
|
||||||
|
public editors: Editor[] = []
|
||||||
|
|
||||||
|
/* @ngInject */
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.application.editorGroup.addChangeObserver(() => {
|
||||||
|
this.editors = this.application.editorGroup.editors;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EditorGroupView extends WebDirective {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = template;
|
||||||
|
this.controller = EditorGroupViewCtrl;
|
||||||
|
this.replace = true;
|
||||||
|
this.controllerAs = 'self';
|
||||||
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
|
application: '='
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FooterStatus, WebDirective } from './../types';
|
import { FooterStatus, WebDirective } from '@/types';
|
||||||
import { dateToLocalizedString } from '@/utils';
|
import { dateToLocalizedString } from '@/utils';
|
||||||
import {
|
import {
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
@@ -10,13 +10,13 @@ import {
|
|||||||
ComponentArea,
|
ComponentArea,
|
||||||
ComponentAction
|
ComponentAction
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import template from '%/footer.pug';
|
import template from './footer-view.pug';
|
||||||
import { AppStateEvent, EventSource } from '@/services/state';
|
import { AppStateEvent, EventSource } from '@/services/state';
|
||||||
import {
|
import {
|
||||||
STRING_GENERIC_SYNC_ERROR,
|
STRING_GENERIC_SYNC_ERROR,
|
||||||
STRING_NEW_UPDATE_READY
|
STRING_NEW_UPDATE_READY
|
||||||
} from '@/strings';
|
} from '@/strings';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { ComponentMutator } from '@/../../../../snjs/dist/@types/models';
|
import { ComponentMutator } from '@/../../../../snjs/dist/@types/models';
|
||||||
|
|
||||||
type DockShortcut = {
|
type DockShortcut = {
|
||||||
@@ -29,7 +29,7 @@ type DockShortcut = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FooterCtrl extends PureCtrl {
|
class FooterViewCtrl extends PureViewCtrl {
|
||||||
|
|
||||||
private $rootScope: ng.IRootScopeService
|
private $rootScope: ng.IRootScopeService
|
||||||
private rooms: SNComponent[] = []
|
private rooms: SNComponent[] = []
|
||||||
@@ -427,15 +427,16 @@ class FooterCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Footer extends WebDirective {
|
export class FooterView extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.controller = FooterCtrl;
|
this.controller = FooterViewCtrl;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controllerAs = 'ctrl';
|
this.controllerAs = 'ctrl';
|
||||||
this.bindToController = {
|
this.bindToController = true;
|
||||||
|
this.scope = {
|
||||||
application: '='
|
application: '='
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
11
app/assets/javascripts/views/index.ts
Normal file
11
app/assets/javascripts/views/index.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export { PureViewCtrl } from './abstract/pure_view_ctrl';
|
||||||
|
|
||||||
|
export { ApplicationGroupView } from './application_group/application_group_view';
|
||||||
|
export { ApplicationView } from './application/application_view';
|
||||||
|
|
||||||
|
export { EditorGroupView } from './editor_group/editor_group_view';
|
||||||
|
export { EditorView } from './editor/editor_view';
|
||||||
|
|
||||||
|
export { FooterView } from './footer/footer_view';
|
||||||
|
export { NotesView } from './notes/notes_view';
|
||||||
|
export { TagsView } from './tags/tags_view';
|
||||||
@@ -111,10 +111,8 @@ export function sortNotes(
|
|||||||
notes: SNNote[] = [],
|
notes: SNNote[] = [],
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
reverse: boolean
|
reverse: boolean
|
||||||
) {
|
) {
|
||||||
const sortValueFn = (a: SNNote, b: SNNote, pinCheck = false): number => {
|
const sortValueFn = (a: SNNote, b: SNNote, pinCheck = false): number => {
|
||||||
if (a.dummy) { return -1; }
|
|
||||||
if (b.dummy) { return 1; }
|
|
||||||
if (!pinCheck) {
|
if (!pinCheck) {
|
||||||
if (a.pinned && b.pinned) {
|
if (a.pinned && b.pinned) {
|
||||||
return sortValueFn(a, b, true);
|
return sortValueFn(a, b, true);
|
||||||
@@ -123,7 +121,7 @@ export function sortNotes(
|
|||||||
if (b.pinned) { return 1; }
|
if (b.pinned) { return 1; }
|
||||||
}
|
}
|
||||||
let aValue = (a as any)[sortBy] || '';
|
let aValue = (a as any)[sortBy] || '';
|
||||||
let bValue = (a as any)[sortBy] || '';
|
let bValue = (b as any)[sortBy] || '';
|
||||||
let vector = 1;
|
let vector = 1;
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
vector *= -1;
|
vector *= -1;
|
||||||
@@ -109,8 +109,8 @@
|
|||||||
)
|
)
|
||||||
.note(
|
.note(
|
||||||
ng-repeat='note in self.state.renderedNotes track by note.uuid'
|
ng-repeat='note in self.state.renderedNotes track by note.uuid'
|
||||||
ng-class="{'selected' : self.selectedNote == note}"
|
ng-class="{'selected' : self.activeEditorNote == note}"
|
||||||
ng-click='self.selectNote(note, true)'
|
ng-click='self.selectNote(note)'
|
||||||
)
|
)
|
||||||
.note-flags(ng-show='self.noteFlags[note.uuid].length > 0')
|
.note-flags(ng-show='self.noteFlags[note.uuid].length > 0')
|
||||||
.flag(ng-class='flag.class', ng-repeat='flag in self.noteFlags[note.uuid]')
|
.flag(ng-class='flag.class', ng-repeat='flag in self.noteFlags[note.uuid]')
|
||||||
@@ -138,6 +138,7 @@
|
|||||||
| Modified {{note.updatedAtString || 'Now'}}
|
| Modified {{note.updatedAtString || 'Now'}}
|
||||||
span(ng-show="self.state.sortBy != 'client_updated_at'")
|
span(ng-show="self.state.sortBy != 'client_updated_at'")
|
||||||
| {{note.createdAtString || 'Now'}}
|
| {{note.createdAtString || 'Now'}}
|
||||||
|
|
||||||
panel-resizer(
|
panel-resizer(
|
||||||
collapsable="true"
|
collapsable="true"
|
||||||
control="self.panelPuppet"
|
control="self.panelPuppet"
|
||||||
@@ -1,13 +1,20 @@
|
|||||||
import { PanelPuppet, WebDirective } from './../../types';
|
import { PanelPuppet, WebDirective } from './../../types';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import template from '%/notes.pug';
|
import template from './notes-view.pug';
|
||||||
import { ApplicationEvent, ContentType, removeFromArray, SNNote, SNTag, WebPrefKey } from 'snjs';
|
import {
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
ApplicationEvent,
|
||||||
|
ContentType,
|
||||||
|
removeFromArray,
|
||||||
|
SNNote,
|
||||||
|
SNTag,
|
||||||
|
WebPrefKey
|
||||||
|
} from 'snjs';
|
||||||
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
||||||
import {
|
import {
|
||||||
PANEL_NAME_NOTES
|
PANEL_NAME_NOTES
|
||||||
} from '@/controllers/constants';
|
} from '@/views/constants';
|
||||||
import {
|
import {
|
||||||
NoteSortKey,
|
NoteSortKey,
|
||||||
filterAndSortNotes
|
filterAndSortNotes
|
||||||
@@ -15,6 +22,7 @@ import {
|
|||||||
import { UuidString } from '@/../../../../snjs/dist/@types/types';
|
import { UuidString } from '@/../../../../snjs/dist/@types/types';
|
||||||
|
|
||||||
type NotesState = {
|
type NotesState = {
|
||||||
|
panelTitle: string
|
||||||
tag?: SNTag
|
tag?: SNTag
|
||||||
notes?: SNNote[]
|
notes?: SNNote[]
|
||||||
renderedNotes?: SNNote[]
|
renderedNotes?: SNNote[]
|
||||||
@@ -43,7 +51,7 @@ const DEFAULT_LIST_NUM_NOTES = 20;
|
|||||||
const ELEMENT_ID_SEARCH_BAR = 'search-bar';
|
const ELEMENT_ID_SEARCH_BAR = 'search-bar';
|
||||||
const ELEMENT_ID_SCROLL_CONTAINER = 'notes-scrollable';
|
const ELEMENT_ID_SCROLL_CONTAINER = 'notes-scrollable';
|
||||||
|
|
||||||
class NotesCtrl extends PureCtrl {
|
class NotesViewCtrl extends PureViewCtrl {
|
||||||
|
|
||||||
private panelPuppet?: PanelPuppet
|
private panelPuppet?: PanelPuppet
|
||||||
private reloadNotesPromise?: any
|
private reloadNotesPromise?: any
|
||||||
@@ -101,13 +109,17 @@ class NotesCtrl extends PureCtrl {
|
|||||||
return this.state as NotesState;
|
return this.state as NotesState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setNotesState(state: Partial<NotesState>) {
|
||||||
|
return this.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
notes: [],
|
notes: [],
|
||||||
renderedNotes: [],
|
renderedNotes: [],
|
||||||
mutable: { showMenu: false },
|
mutable: { showMenu: false },
|
||||||
noteFilter: { text: '' },
|
noteFilter: { text: '' },
|
||||||
} as NotesState;
|
} as Partial<NotesState>;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAppLaunch() {
|
async onAppLaunch() {
|
||||||
@@ -120,13 +132,10 @@ class NotesCtrl extends PureCtrl {
|
|||||||
onAppStateEvent(eventName: AppStateEvent, data?: any) {
|
onAppStateEvent(eventName: AppStateEvent, data?: any) {
|
||||||
if (eventName === AppStateEvent.TagChanged) {
|
if (eventName === AppStateEvent.TagChanged) {
|
||||||
this.handleTagChange(
|
this.handleTagChange(
|
||||||
this.application!.getAppState().getSelectedTag()!,
|
this.application!.getAppState().getSelectedTag()!
|
||||||
data.previousTag
|
|
||||||
);
|
|
||||||
} else if (eventName === AppStateEvent.NoteChanged) {
|
|
||||||
this.handleNoteSelection(
|
|
||||||
this.application!.getAppState().getSelectedNote()!
|
|
||||||
);
|
);
|
||||||
|
} else if (eventName === AppStateEvent.ActiveEditorChanged) {
|
||||||
|
this.handleEditorChange();
|
||||||
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
@@ -135,19 +144,19 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedNote() {
|
get activeEditorNote() {
|
||||||
return this.appState.getSelectedNote();
|
const activeEditor = this.appState.getActiveEditor();
|
||||||
|
return activeEditor && activeEditor.note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get editorNotes() {
|
||||||
|
return this.appState.getEditors().map((editor) => editor.note);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async onAppEvent(eventName: ApplicationEvent) {
|
async onAppEvent(eventName: ApplicationEvent) {
|
||||||
if (eventName === ApplicationEvent.SignedIn) {
|
if (eventName === ApplicationEvent.SignedIn) {
|
||||||
/** Delete dummy note if applicable */
|
this.appState.closeAllEditors();
|
||||||
if (this.selectedNote && this.selectedNote!.dummy) {
|
|
||||||
this.application!.deleteItemLocally(this.selectedNote!);
|
|
||||||
await this.selectNote(undefined);
|
|
||||||
await this.reloadNotes();
|
|
||||||
}
|
|
||||||
} else if (eventName === ApplicationEvent.CompletedSync) {
|
} else if (eventName === ApplicationEvent.CompletedSync) {
|
||||||
this.getMostValidNotes().then((notes) => {
|
this.getMostValidNotes().then((notes) => {
|
||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
@@ -196,9 +205,9 @@ class NotesCtrl extends PureCtrl {
|
|||||||
[ContentType.Note, ContentType.Tag],
|
[ContentType.Note, ContentType.Tag],
|
||||||
async (items) => {
|
async (items) => {
|
||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
const selectedNote = this.selectedNote;
|
const activeNote = this.activeEditorNote;
|
||||||
if (selectedNote) {
|
if (activeNote) {
|
||||||
const discarded = selectedNote.deleted || selectedNote.trashed;
|
const discarded = activeNote.deleted || activeNote.trashed;
|
||||||
if (discarded) {
|
if (discarded) {
|
||||||
this.selectNextOrCreateNew();
|
this.selectNextOrCreateNew();
|
||||||
}
|
}
|
||||||
@@ -218,51 +227,20 @@ class NotesCtrl extends PureCtrl {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectNote(note?: SNNote) {
|
async selectNote(note: SNNote) {
|
||||||
return this.application!.getAppState().setSelectedNote(note);
|
this.appState.openEditor(note.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNewNote() {
|
async createNewNote() {
|
||||||
const selectedTag = this.application!.getAppState().getSelectedTag();
|
let title = `Note ${this.getState().notes!.length + 1}`;
|
||||||
if (!selectedTag) {
|
|
||||||
throw 'Attempting to create note with no selected tag';
|
|
||||||
}
|
|
||||||
let title;
|
|
||||||
let isDummyNote = true;
|
|
||||||
if (this.isFiltering()) {
|
if (this.isFiltering()) {
|
||||||
title = this.getState().noteFilter.text;
|
title = this.getState().noteFilter.text;
|
||||||
isDummyNote = false;
|
|
||||||
} else if (this.selectedNote && this.selectedNote!.dummy) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
title = `Note ${this.getState().notes!.length + 1}`;
|
|
||||||
}
|
}
|
||||||
const newNote = await this.application!.createManagedItem(
|
this.appState.createEditor(title);
|
||||||
ContentType.Note,
|
|
||||||
{
|
|
||||||
text: '',
|
|
||||||
title: title,
|
|
||||||
references: []
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
{
|
|
||||||
dummy: isDummyNote
|
|
||||||
}
|
|
||||||
) as SNNote;
|
|
||||||
if (!selectedTag.isSmartTag()) {
|
|
||||||
this.application!.changeItem(selectedTag.uuid, (mutator) => {
|
|
||||||
mutator.addItemAsRelationship(newNote);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.selectNote(newNote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleTagChange(tag: SNTag, previousTag?: SNTag) {
|
async handleTagChange(tag: SNTag) {
|
||||||
if (this.selectedNote && this.selectedNote!.dummy) {
|
await this.setNotesState({ tag });
|
||||||
await this.application!.deleteItemLocally(this.selectedNote!);
|
|
||||||
await this.selectNote(undefined);
|
|
||||||
}
|
|
||||||
await this.setState({ tag: tag });
|
|
||||||
|
|
||||||
this.resetScrollPosition();
|
this.resetScrollPosition();
|
||||||
this.setShowMenuFalse();
|
this.setShowMenuFalse();
|
||||||
@@ -270,7 +248,8 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.application!.getDesktopService().searchText();
|
this.application!.getDesktopService().searchText();
|
||||||
this.resetPagination();
|
this.resetPagination();
|
||||||
|
|
||||||
/* Capture db load state before beginning reloadNotes, since this status may change during reload */
|
/* Capture db load state before beginning reloadNotes,
|
||||||
|
since this status may change during reload */
|
||||||
const dbLoaded = this.application!.isDatabaseLoaded();
|
const dbLoaded = this.application!.isDatabaseLoaded();
|
||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
|
|
||||||
@@ -280,10 +259,10 @@ class NotesCtrl extends PureCtrl {
|
|||||||
if (!tag.isSmartTag() || tag.isAllTag) {
|
if (!tag.isSmartTag() || tag.isAllTag) {
|
||||||
this.createPlaceholderNote();
|
this.createPlaceholderNote();
|
||||||
} else if (
|
} else if (
|
||||||
this.selectedNote &&
|
this.activeEditorNote &&
|
||||||
!this.getState().notes!.includes(this.selectedNote!)
|
!this.getState().notes!.includes(this.activeEditorNote!)
|
||||||
) {
|
) {
|
||||||
this.selectNote(undefined);
|
this.appState.closeActiveEditor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,7 +278,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
async removeNoteFromList(note: SNNote) {
|
async removeNoteFromList(note: SNNote) {
|
||||||
const notes = this.getState().notes!;
|
const notes = this.getState().notes!;
|
||||||
removeFromArray(notes, note);
|
removeFromArray(notes, note);
|
||||||
await this.setState({
|
await this.setNotesState({
|
||||||
notes: notes,
|
notes: notes,
|
||||||
renderedNotes: notes.slice(0, this.notesToDisplay)
|
renderedNotes: notes.slice(0, this.notesToDisplay)
|
||||||
});
|
});
|
||||||
@@ -330,7 +309,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.loadFlagsForNote(note);
|
this.loadFlagsForNote(note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.setState({
|
await this.setNotesState({
|
||||||
notes: notes,
|
notes: notes,
|
||||||
renderedNotes: notes.slice(0, this.notesToDisplay)
|
renderedNotes: notes.slice(0, this.notesToDisplay)
|
||||||
});
|
});
|
||||||
@@ -338,7 +317,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setShowMenuFalse() {
|
setShowMenuFalse() {
|
||||||
this.setState({
|
this.setNotesState({
|
||||||
mutable: {
|
mutable: {
|
||||||
...this.getState().mutable,
|
...this.getState().mutable,
|
||||||
showMenu: false
|
showMenu: false
|
||||||
@@ -346,20 +325,10 @@ class NotesCtrl extends PureCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleNoteSelection(note: SNNote) {
|
async handleEditorChange() {
|
||||||
const previousNote = this.selectedNote;
|
const activeNote = this.appState.getActiveEditor().note;
|
||||||
if (previousNote === note) {
|
if (activeNote && activeNote.conflictOf) {
|
||||||
return;
|
this.application!.changeAndSaveItem(activeNote.uuid, (mutator) => {
|
||||||
}
|
|
||||||
if (previousNote && previousNote.dummy) {
|
|
||||||
await this.application!.deleteItemLocally(previousNote);
|
|
||||||
this.removeNoteFromList(previousNote);
|
|
||||||
}
|
|
||||||
if (!note) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (note.conflictOf) {
|
|
||||||
this.application!.changeAndSaveItem(note.uuid, (mutator) => {
|
|
||||||
mutator.conflictOf = undefined;
|
mutator.conflictOf = undefined;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -404,7 +373,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
WebPrefKey.NotesHideTags,
|
WebPrefKey.NotesHideTags,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
this.setState({
|
this.setNotesState({
|
||||||
...viewOptions
|
...viewOptions
|
||||||
});
|
});
|
||||||
if (prevSortValue && prevSortValue !== sortBy) {
|
if (prevSortValue && prevSortValue !== sortBy) {
|
||||||
@@ -469,7 +438,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
} else if (this.getState().tag) {
|
} else if (this.getState().tag) {
|
||||||
title = `${this.getState().tag!.title}`;
|
title = `${this.getState().tag!.title}`;
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setNotesState({
|
||||||
panelTitle: title
|
panelTitle: title
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -584,7 +553,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
selectNextNote() {
|
selectNextNote() {
|
||||||
const displayableNotes = this.displayableNotes();
|
const displayableNotes = this.displayableNotes();
|
||||||
const currentIndex = displayableNotes.findIndex((candidate) => {
|
const currentIndex = displayableNotes.findIndex((candidate) => {
|
||||||
return candidate.uuid === this.selectedNote!.uuid
|
return candidate.uuid === this.activeEditorNote!.uuid
|
||||||
});
|
});
|
||||||
if (currentIndex + 1 < displayableNotes.length) {
|
if (currentIndex + 1 < displayableNotes.length) {
|
||||||
this.selectNote(displayableNotes[currentIndex + 1]);
|
this.selectNote(displayableNotes[currentIndex + 1]);
|
||||||
@@ -598,13 +567,13 @@ class NotesCtrl extends PureCtrl {
|
|||||||
} else if (!this.getState().tag || !this.getState().tag!.isSmartTag()) {
|
} else if (!this.getState().tag || !this.getState().tag!.isSmartTag()) {
|
||||||
this.createPlaceholderNote();
|
this.createPlaceholderNote();
|
||||||
} else {
|
} else {
|
||||||
this.selectNote(undefined);
|
this.appState.closeActiveEditor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectPreviousNote() {
|
selectPreviousNote() {
|
||||||
const displayableNotes = this.displayableNotes();
|
const displayableNotes = this.displayableNotes();
|
||||||
const currentIndex = displayableNotes.indexOf(this.selectedNote!);
|
const currentIndex = displayableNotes.indexOf(this.activeEditorNote!);
|
||||||
if (currentIndex - 1 >= 0) {
|
if (currentIndex - 1 >= 0) {
|
||||||
this.selectNote(displayableNotes[currentIndex - 1]);
|
this.selectNote(displayableNotes[currentIndex - 1]);
|
||||||
return true;
|
return true;
|
||||||
@@ -619,7 +588,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setNoteFilterText(text: string) {
|
async setNoteFilterText(text: string) {
|
||||||
await this.setState({
|
await this.setNotesState({
|
||||||
noteFilter: {
|
noteFilter: {
|
||||||
...this.getState().noteFilter,
|
...this.getState().noteFilter,
|
||||||
text: text
|
text: text
|
||||||
@@ -748,12 +717,12 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotesPanel extends WebDirective {
|
export class NotesView extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = NotesCtrl;
|
this.controller = NotesViewCtrl;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
this.scope = {
|
this.scope = {
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { WebDirective, PanelPuppet } from './../types';
|
import { WebDirective, PanelPuppet } from '@/types';
|
||||||
import { WebApplication } from './../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import {
|
import {
|
||||||
SNNote,
|
|
||||||
SNTag,
|
SNTag,
|
||||||
ContentType,
|
ContentType,
|
||||||
ApplicationEvent,
|
ApplicationEvent,
|
||||||
@@ -11,17 +10,17 @@ import {
|
|||||||
SNComponent,
|
SNComponent,
|
||||||
WebPrefKey
|
WebPrefKey
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import template from '%/tags.pug';
|
import template from './tags-view.pug';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { PANEL_NAME_TAGS } from '@/controllers/constants';
|
import { PANEL_NAME_TAGS } from '@/views/constants';
|
||||||
import { STRING_DELETE_TAG } from '@/strings';
|
import { STRING_DELETE_TAG } from '@/strings';
|
||||||
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { UuidString } from '@/../../../../snjs/dist/@types/types';
|
import { UuidString } from '@/../../../../snjs/dist/@types/types';
|
||||||
import { TagMutator } from '@/../../../../snjs/dist/@types/models/app/tag';
|
import { TagMutator } from '@/../../../../snjs/dist/@types/models/app/tag';
|
||||||
|
|
||||||
type NoteCounts = Partial<Record<string, number>>
|
type NoteCounts = Partial<Record<string, number>>
|
||||||
|
|
||||||
class TagsPanelCtrl extends PureCtrl {
|
class TagsViewCtrl extends PureViewCtrl {
|
||||||
|
|
||||||
/** Passed through template */
|
/** Passed through template */
|
||||||
readonly application!: WebApplication
|
readonly application!: WebApplication
|
||||||
@@ -106,6 +105,10 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
});
|
});
|
||||||
if (!matchingTag || matchingTag.deleted) {
|
if (!matchingTag || matchingTag.deleted) {
|
||||||
this.selectTag(this.state.smartTags[0]);
|
this.selectTag(this.state.smartTags[0]);
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
selectedTag: matchingTag
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,7 +345,7 @@ class TagsPanelCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TagsPanel extends WebDirective {
|
export class TagsView extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.restrict = 'E';
|
this.restrict = 'E';
|
||||||
@@ -351,7 +354,7 @@ export class TagsPanel extends WebDirective {
|
|||||||
};
|
};
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = TagsPanelCtrl;
|
this.controller = TagsViewCtrl;
|
||||||
this.controllerAs = 'self';
|
this.controllerAs = 'self';
|
||||||
this.bindToController = true;
|
this.bindToController = true;
|
||||||
}
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#lock-screen.sn-component
|
|
||||||
.sk-panel
|
|
||||||
.sk-panel-header
|
|
||||||
.sk-panel-header-title Passcode Required
|
|
||||||
.sk-panel-content
|
|
||||||
.sk-panel-section
|
|
||||||
form.sk-panel-form.sk-panel-row(ng-submit='ctrl.submitPasscodeForm($event)')
|
|
||||||
.sk-panel-column.stretch
|
|
||||||
input#passcode-input.center-text.sk-input.contrast(
|
|
||||||
autocomplete='new-password',
|
|
||||||
autofocus='true',
|
|
||||||
ng-model='ctrl.formData.passcode',
|
|
||||||
placeholder='Enter Passcode',
|
|
||||||
should-focus='true',
|
|
||||||
sn-autofocus='true',
|
|
||||||
type='password'
|
|
||||||
)
|
|
||||||
.sk-button-group.stretch.sk-panel-row.form-submit
|
|
||||||
button.sk-button.info(type='submit')
|
|
||||||
.sk-label Unlock
|
|
||||||
.sk-panel-footer
|
|
||||||
#passcode-reset
|
|
||||||
a.sk-a.neutral(
|
|
||||||
ng-click='ctrl.forgotPasscode()',
|
|
||||||
ng-if='!ctrl.formData.showRecovery'
|
|
||||||
) Forgot?
|
|
||||||
div(ng-if='ctrl.formData.showRecovery')
|
|
||||||
.sk-p
|
|
||||||
| If you forgot your application passcode, your only option is to clear
|
|
||||||
| your local data from this device and sign back in to your account.
|
|
||||||
.sk-panel-row
|
|
||||||
a.sk-a.danger.center-text(
|
|
||||||
ng-click='ctrl.beginDeleteData()'
|
|
||||||
) Delete Local Data
|
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<root />
|
<application-group-view />
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/// <reference types="angular" />
|
/// <reference types="angular" />
|
||||||
import { WebApplication } from './../../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { SNComponent } from 'snjs';
|
import { SNComponent } from 'snjs';
|
||||||
import { WebDirective } from './../../types';
|
import { WebDirective } from './../../types';
|
||||||
declare type ComponentModalScope = {
|
declare type ComponentModalScope = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { SNAlertService } from 'snjs';
|
import { SNAlertService } from 'snjs';
|
||||||
export declare class AlertService extends SNAlertService {
|
export declare class AlertService extends SNAlertService {
|
||||||
alert(title: string, text: string, closeButtonText: string | undefined, onClose: () => void): Promise<unknown>;
|
alert(text: string, title: string, closeButtonText: string | undefined, onClose: () => void): Promise<unknown>;
|
||||||
confirm(title: string, text: string, confirmButtonText: string | undefined, cancelButtonText: string | undefined, onConfirm: () => void, onCancel: () => void, destructive?: boolean): Promise<unknown>;
|
confirm(text: string, title: string, confirmButtonText: string | undefined, cancelButtonText: string | undefined, onConfirm: () => void, onCancel: () => void, destructive?: boolean): Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { SNItem } from 'snjs';
|
import { SNItem } from 'snjs';
|
||||||
export declare class ArchiveManager {
|
export declare class ArchiveManager {
|
||||||
private readonly application;
|
private readonly application;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="angular" />
|
/// <reference types="angular" />
|
||||||
import { SNComponent, PurePayload } from 'snjs';
|
import { SNComponent, PurePayload } from 'snjs';
|
||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { ApplicationService, ApplicationEvent } from 'snjs';
|
import { ApplicationService, ApplicationEvent } from 'snjs';
|
||||||
declare type UpdateObserverCallback = (component: SNComponent) => void;
|
declare type UpdateObserverCallback = (component: SNComponent) => void;
|
||||||
declare type ComponentActivationCallback = (payload: PurePayload) => void;
|
declare type ComponentActivationCallback = (payload: PurePayload) => void;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from './../application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
export declare class LockManager {
|
export declare class LockManager {
|
||||||
private application;
|
private application;
|
||||||
private unsubState;
|
private unsubState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { ApplicationService, WebPrefKey } from 'snjs';
|
import { ApplicationService, WebPrefKey } from 'snjs';
|
||||||
export declare class PreferencesManager extends ApplicationService {
|
export declare class PreferencesManager extends ApplicationService {
|
||||||
private userPreferences;
|
private userPreferences;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
/// <reference types="angular" />
|
/// <reference types="angular" />
|
||||||
import { WebApplication } from './../application';
|
|
||||||
import { SNTag, SNNote, SNUserPrefs } from 'snjs';
|
import { SNTag, SNNote, SNUserPrefs } from 'snjs';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
import { Editor } from '@/ui_models/editor';
|
||||||
export declare enum AppStateEvent {
|
export declare enum AppStateEvent {
|
||||||
TagChanged = 1,
|
TagChanged = 1,
|
||||||
NoteChanged = 2,
|
ActiveEditorChanged = 2,
|
||||||
PreferencesChanged = 3,
|
PreferencesChanged = 3,
|
||||||
PanelResized = 4,
|
PanelResized = 4,
|
||||||
EditorFocused = 5,
|
EditorFocused = 5,
|
||||||
@@ -29,10 +30,22 @@ export declare class AppState {
|
|||||||
rootScopeCleanup2: any;
|
rootScopeCleanup2: any;
|
||||||
onVisibilityChange: any;
|
onVisibilityChange: any;
|
||||||
selectedTag?: SNTag;
|
selectedTag?: SNTag;
|
||||||
selectedNote?: SNNote;
|
|
||||||
userPreferences?: SNUserPrefs;
|
userPreferences?: SNUserPrefs;
|
||||||
|
multiEditorEnabled: boolean;
|
||||||
constructor($rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService, application: WebApplication);
|
constructor($rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService, application: WebApplication);
|
||||||
deinit(): void;
|
deinit(): void;
|
||||||
|
/**
|
||||||
|
* Creates a new editor if one doesn't exist. If one does, we'll replace the
|
||||||
|
* editor's note with an empty one.
|
||||||
|
*/
|
||||||
|
createEditor(title?: string): void;
|
||||||
|
openEditor(noteUuid: string): Promise<unknown>;
|
||||||
|
getActiveEditor(): Editor;
|
||||||
|
getEditors(): Editor[];
|
||||||
|
closeEditor(editor: Editor): void;
|
||||||
|
closeActiveEditor(): void;
|
||||||
|
closeAllEditors(): void;
|
||||||
|
editorForNote(note: SNNote): Editor | undefined;
|
||||||
streamNotesAndTags(): void;
|
streamNotesAndTags(): void;
|
||||||
addAppEventObserver(): void;
|
addAppEventObserver(): void;
|
||||||
isLocked(): boolean;
|
isLocked(): boolean;
|
||||||
@@ -41,13 +54,11 @@ export declare class AppState {
|
|||||||
addObserver(callback: ObserverCallback): () => void;
|
addObserver(callback: ObserverCallback): () => void;
|
||||||
notifyEvent(eventName: AppStateEvent, data?: any): Promise<unknown>;
|
notifyEvent(eventName: AppStateEvent, data?: any): Promise<unknown>;
|
||||||
setSelectedTag(tag: SNTag): void;
|
setSelectedTag(tag: SNTag): void;
|
||||||
setSelectedNote(note?: SNNote): Promise<unknown>;
|
|
||||||
/** Returns the tags that are referncing this note */
|
/** Returns the tags that are referncing this note */
|
||||||
getNoteTags(note: SNNote): SNTag[];
|
getNoteTags(note: SNNote): SNTag[];
|
||||||
/** Returns the notes this tag references */
|
/** Returns the notes this tag references */
|
||||||
getTagNotes(tag: SNTag): SNNote[];
|
getTagNotes(tag: SNTag): SNNote[];
|
||||||
getSelectedTag(): SNTag | undefined;
|
getSelectedTag(): SNTag | undefined;
|
||||||
getSelectedNote(): SNNote | undefined;
|
|
||||||
setUserPreferences(preferences: SNUserPrefs): void;
|
setUserPreferences(preferences: SNUserPrefs): void;
|
||||||
panelDidResize(name: string, collapsed: boolean): void;
|
panelDidResize(name: string, collapsed: boolean): void;
|
||||||
editorDidFocus(eventSource: EventSource): void;
|
editorDidFocus(eventSource: EventSource): void;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FooterStatus } from './../types';
|
import { FooterStatus } from '@/types';
|
||||||
declare type StatusCallback = (string: string) => void;
|
declare type StatusCallback = (string: string) => void;
|
||||||
export declare class StatusManager {
|
export declare class StatusManager {
|
||||||
private statuses;
|
private statuses;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WebApplication } from '@/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { ApplicationService } from 'snjs';
|
import { ApplicationService } from 'snjs';
|
||||||
export declare class ThemeManager extends ApplicationService {
|
export declare class ThemeManager extends ApplicationService {
|
||||||
private activeThemes;
|
private activeThemes;
|
||||||
|
|||||||
56
dist/@types/app/assets/javascripts/ui_models/application.d.ts
vendored
Normal file
56
dist/@types/app/assets/javascripts/ui_models/application.d.ts
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/// <reference types="angular" />
|
||||||
|
import { EditorGroup } from '@/ui_models/editor_group';
|
||||||
|
import { PasswordWizardType } from '@/types';
|
||||||
|
import { SNApplication, Challenge, ChallengeOrchestrator, ProtectedAction } from 'snjs';
|
||||||
|
import { AppState, DesktopManager, LockManager, ArchiveManager, NativeExtManager, StatusManager, ThemeManager, PreferencesManager, KeyboardManager } from '@/services';
|
||||||
|
declare type WebServices = {
|
||||||
|
appState: AppState;
|
||||||
|
desktopService: DesktopManager;
|
||||||
|
lockService: LockManager;
|
||||||
|
archiveService: ArchiveManager;
|
||||||
|
nativeExtService: NativeExtManager;
|
||||||
|
statusService: StatusManager;
|
||||||
|
themeService: ThemeManager;
|
||||||
|
prefsService: PreferencesManager;
|
||||||
|
keyboardService: KeyboardManager;
|
||||||
|
};
|
||||||
|
export declare class WebApplication extends SNApplication {
|
||||||
|
private $compile?;
|
||||||
|
private scope?;
|
||||||
|
private onDeinit?;
|
||||||
|
private webServices;
|
||||||
|
private currentAuthenticationElement?;
|
||||||
|
editorGroup: EditorGroup;
|
||||||
|
constructor($compile: ng.ICompileService, $timeout: ng.ITimeoutService, scope: ng.IScope, onDeinit: (app: WebApplication) => void);
|
||||||
|
/** @override */
|
||||||
|
deinit(): void;
|
||||||
|
setWebServices(services: WebServices): void;
|
||||||
|
/** @access public */
|
||||||
|
getAppState(): AppState;
|
||||||
|
/** @access public */
|
||||||
|
getDesktopService(): DesktopManager;
|
||||||
|
/** @access public */
|
||||||
|
getLockService(): LockManager;
|
||||||
|
/** @access public */
|
||||||
|
getArchiveService(): ArchiveManager;
|
||||||
|
/** @access public */
|
||||||
|
getNativeExtService(): NativeExtManager;
|
||||||
|
/** @access public */
|
||||||
|
getStatusService(): StatusManager;
|
||||||
|
/** @access public */
|
||||||
|
getThemeService(): ThemeManager;
|
||||||
|
/** @access public */
|
||||||
|
getPrefsService(): PreferencesManager;
|
||||||
|
/** @access public */
|
||||||
|
getKeyboardService(): KeyboardManager;
|
||||||
|
checkForSecurityUpdate(): Promise<boolean>;
|
||||||
|
presentPasswordWizard(type: PasswordWizardType): void;
|
||||||
|
promptForChallenge(challenge: Challenge, orchestrator: ChallengeOrchestrator): void;
|
||||||
|
performProtocolUpgrade(): Promise<void>;
|
||||||
|
presentPrivilegesModal(action: ProtectedAction, onSuccess?: any, onCancel?: any): Promise<void>;
|
||||||
|
presentPrivilegesManagementModal(): void;
|
||||||
|
authenticationInProgress(): boolean;
|
||||||
|
presentPasswordModal(callback: () => void): void;
|
||||||
|
presentRevisionPreviewModal(uuid: string, content: any): void;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
26
dist/@types/app/assets/javascripts/ui_models/application_group.d.ts
vendored
Normal file
26
dist/@types/app/assets/javascripts/ui_models/application_group.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/// <reference types="angular" />
|
||||||
|
import { WebApplication } from './application';
|
||||||
|
declare type AppManagerChangeCallback = () => void;
|
||||||
|
export declare class ApplicationGroup {
|
||||||
|
$compile: ng.ICompileService;
|
||||||
|
$rootScope: ng.IRootScopeService;
|
||||||
|
$timeout: ng.ITimeoutService;
|
||||||
|
applications: WebApplication[];
|
||||||
|
changeObservers: AppManagerChangeCallback[];
|
||||||
|
activeApplication?: WebApplication;
|
||||||
|
constructor($compile: ng.ICompileService, $rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService);
|
||||||
|
private createDefaultApplication;
|
||||||
|
/** @callback */
|
||||||
|
onApplicationDeinit(application: WebApplication): void;
|
||||||
|
private createNewApplication;
|
||||||
|
get application(): WebApplication | undefined;
|
||||||
|
getApplications(): WebApplication[];
|
||||||
|
/**
|
||||||
|
* Notifies observer when the active application has changed.
|
||||||
|
* Any application which is no longer active is destroyed, and
|
||||||
|
* must be removed from the interface.
|
||||||
|
*/
|
||||||
|
addApplicationChangeObserver(callback: AppManagerChangeCallback): void;
|
||||||
|
private notifyObserversOfAppChange;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
32
dist/@types/app/assets/javascripts/ui_models/editor.d.ts
vendored
Normal file
32
dist/@types/app/assets/javascripts/ui_models/editor.d.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { SNNote, PayloadSource } from 'snjs';
|
||||||
|
import { WebApplication } from './application';
|
||||||
|
export declare class Editor {
|
||||||
|
note: SNNote;
|
||||||
|
private application;
|
||||||
|
private _onNoteChange?;
|
||||||
|
private _onNoteValueChange?;
|
||||||
|
private removeStreamObserver;
|
||||||
|
isTemplateNote: boolean;
|
||||||
|
constructor(application: WebApplication, noteUuid?: string, noteTitle?: string);
|
||||||
|
private handleNoteStream;
|
||||||
|
insertTemplatedNote(): Promise<import("../../../../../snjs/dist/@types").SNItem>;
|
||||||
|
/**
|
||||||
|
* Reverts the editor to a blank state, removing any existing note from view,
|
||||||
|
* and creating a placeholder note.
|
||||||
|
*/
|
||||||
|
reset(noteTitle?: string): Promise<void>;
|
||||||
|
deinit(): void;
|
||||||
|
/**
|
||||||
|
* Register to be notified when the editor's note changes.
|
||||||
|
*/
|
||||||
|
onNoteChange(onNoteChange: () => void): void;
|
||||||
|
/**
|
||||||
|
* Register to be notified when the editor's note's values change
|
||||||
|
* (and thus a new object reference is created)
|
||||||
|
*/
|
||||||
|
onNoteValueChange(onNoteValueChange: (note: SNNote, source?: PayloadSource) => void): void;
|
||||||
|
/**
|
||||||
|
* Sets the editor contents by setting its note.
|
||||||
|
*/
|
||||||
|
setNote(note: SNNote): void;
|
||||||
|
}
|
||||||
22
dist/@types/app/assets/javascripts/ui_models/editor_group.d.ts
vendored
Normal file
22
dist/@types/app/assets/javascripts/ui_models/editor_group.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Editor } from './editor';
|
||||||
|
import { WebApplication } from './application';
|
||||||
|
declare type EditorGroupChangeCallback = () => void;
|
||||||
|
export declare class EditorGroup {
|
||||||
|
editors: Editor[];
|
||||||
|
private application;
|
||||||
|
changeObservers: EditorGroupChangeCallback[];
|
||||||
|
constructor(application: WebApplication);
|
||||||
|
deinit(): void;
|
||||||
|
createEditor(noteUuid?: string, noteTitle?: string): void;
|
||||||
|
deleteEditor(editor: Editor): void;
|
||||||
|
closeEditor(editor: Editor): void;
|
||||||
|
closeActiveEditor(): void;
|
||||||
|
closeAllEditors(): void;
|
||||||
|
get activeEditor(): Editor;
|
||||||
|
/**
|
||||||
|
* Notifies observer when the active editor has changed.
|
||||||
|
*/
|
||||||
|
addChangeObserver(callback: EditorGroupChangeCallback): void;
|
||||||
|
private notifyObservers;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
36
dist/@types/app/assets/javascripts/views/abstract/pure_view_ctrl.d.ts
vendored
Normal file
36
dist/@types/app/assets/javascripts/views/abstract/pure_view_ctrl.d.ts
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/// <reference types="angular" />
|
||||||
|
import { ApplicationEvent } from 'snjs';
|
||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
export declare type CtrlState = Partial<Record<string, any>>;
|
||||||
|
export declare type CtrlProps = Partial<Record<string, any>>;
|
||||||
|
export declare class PureViewCtrl {
|
||||||
|
$timeout: ng.ITimeoutService;
|
||||||
|
/** Passed through templates */
|
||||||
|
application?: WebApplication;
|
||||||
|
props: CtrlProps;
|
||||||
|
state: CtrlState;
|
||||||
|
private unsubApp;
|
||||||
|
private unsubState;
|
||||||
|
private stateTimeout;
|
||||||
|
constructor($timeout: ng.ITimeoutService);
|
||||||
|
$onInit(): void;
|
||||||
|
deinit(): void;
|
||||||
|
$onDestroy(): void;
|
||||||
|
get appState(): import("../../services").AppState;
|
||||||
|
/** @private */
|
||||||
|
resetState(): Promise<void>;
|
||||||
|
/** @override */
|
||||||
|
getInitialState(): {};
|
||||||
|
setState(state: CtrlState): Promise<unknown>;
|
||||||
|
updateUI(func: () => void): Promise<void>;
|
||||||
|
initProps(props: CtrlProps): void;
|
||||||
|
addAppStateObserver(): void;
|
||||||
|
onAppStateEvent(eventName: any, data: any): void;
|
||||||
|
addAppEventObserver(): void;
|
||||||
|
onAppEvent(eventName: ApplicationEvent): void;
|
||||||
|
/** @override */
|
||||||
|
onAppStart(): Promise<void>;
|
||||||
|
onAppLaunch(): Promise<void>;
|
||||||
|
onAppKeyChange(): Promise<void>;
|
||||||
|
onAppSync(): void;
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/application/application_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/application/application_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class ApplicationView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/application_group/application_group.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/application_group/application_group.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class ApplicationGroupView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/application_group/application_group_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/application_group/application_group_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class ApplicationGroupView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
2
dist/@types/app/assets/javascripts/views/constants.d.ts
vendored
Normal file
2
dist/@types/app/assets/javascripts/views/constants.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export declare const PANEL_NAME_NOTES = "notes";
|
||||||
|
export declare const PANEL_NAME_TAGS = "tags";
|
||||||
4
dist/@types/app/assets/javascripts/views/editor/editor_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/editor/editor_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class EditorView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/editor_group/editor_group.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/editor_group/editor_group.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from './../../types';
|
||||||
|
export declare class EditorGroupView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/editor_group/editor_group_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/editor_group/editor_group_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from './../../types';
|
||||||
|
export declare class EditorGroupView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/footer/footer_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/footer/footer_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class FooterView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
8
dist/@types/app/assets/javascripts/views/index.d.ts
vendored
Normal file
8
dist/@types/app/assets/javascripts/views/index.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export { PureViewCtrl } from './abstract/pure_view_ctrl';
|
||||||
|
export { ApplicationGroupView } from './application_group/application_group_view';
|
||||||
|
export { ApplicationView } from './application/application_view';
|
||||||
|
export { EditorGroupView } from './editor_group/editor_group_view';
|
||||||
|
export { EditorView } from './editor/editor_view';
|
||||||
|
export { FooterView } from './footer/footer_view';
|
||||||
|
export { NotesView } from './notes/notes_view';
|
||||||
|
export { TagsView } from './tags/tags_view';
|
||||||
10
dist/@types/app/assets/javascripts/views/notes/note_utils.d.ts
vendored
Normal file
10
dist/@types/app/assets/javascripts/views/notes/note_utils.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { SNNote, SNTag } from 'snjs';
|
||||||
|
export declare enum NoteSortKey {
|
||||||
|
CreatedAt = "created_at",
|
||||||
|
UpdatedAt = "updated_at",
|
||||||
|
ClientUpdatedAt = "client_updated_at",
|
||||||
|
Title = "title"
|
||||||
|
}
|
||||||
|
export declare function filterAndSortNotes(notes: SNNote[], selectedTag: SNTag, showArchived: boolean, hidePinned: boolean, filterText: string, sortBy: string, reverse: boolean): SNNote[];
|
||||||
|
export declare function filterNotes(notes: SNNote[], selectedTag: SNTag, showArchived: boolean, hidePinned: boolean, filterText: string): SNNote[];
|
||||||
|
export declare function sortNotes(notes: SNNote[] | undefined, sortBy: string, reverse: boolean): SNNote[];
|
||||||
4
dist/@types/app/assets/javascripts/views/notes/notes_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/notes/notes_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from './../../types';
|
||||||
|
export declare class NotesView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
4
dist/@types/app/assets/javascripts/views/tags/tags_view.d.ts
vendored
Normal file
4
dist/@types/app/assets/javascripts/views/tags/tags_view.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { WebDirective } from '@/types';
|
||||||
|
export declare class TagsView extends WebDirective {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
13795
dist/javascripts/app.js
vendored
13795
dist/javascripts/app.js
vendored
File diff suppressed because one or more lines are too long
2
dist/javascripts/app.js.map
vendored
2
dist/javascripts/app.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -36,7 +36,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<root />
|
<application-group-view />
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ module.exports = {
|
|||||||
alias: {
|
alias: {
|
||||||
'%': path.resolve(__dirname, 'app/assets/templates'),
|
'%': path.resolve(__dirname, 'app/assets/templates'),
|
||||||
'@': path.resolve(__dirname, 'app/assets/javascripts'),
|
'@': path.resolve(__dirname, 'app/assets/javascripts'),
|
||||||
'@Controllers': path.resolve(__dirname, 'app/assets/javascripts/controllers')
|
'@Controllers': path.resolve(__dirname, 'app/assets/javascripts/controllers'),
|
||||||
|
'@Views': path.resolve(__dirname, 'app/assets/javascripts/views'),
|
||||||
|
'@Services': path.resolve(__dirname, 'app/assets/javascripts/services'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
|
|||||||
Reference in New Issue
Block a user