Merge branch 'release/3.6.3' into main

This commit is contained in:
Baptiste Grob
2021-03-25 11:04:59 +01:00
32 changed files with 851 additions and 916 deletions

View File

@@ -43,7 +43,6 @@ import {
MenuRow, MenuRow,
PanelResizer, PanelResizer,
PasswordWizard, PasswordWizard,
PermissionsModal,
RevisionPreviewModal, RevisionPreviewModal,
HistoryMenu, HistoryMenu,
SyncResolutionMenu, SyncResolutionMenu,
@@ -57,7 +56,7 @@ import { StartApplication } from './startApplication';
import { Bridge } from './services/bridge'; import { Bridge } from './services/bridge';
import { SessionsModalDirective } from './components/SessionsModal'; import { SessionsModalDirective } from './components/SessionsModal';
import { NoAccountWarningDirective } from './components/NoAccountWarning'; import { NoAccountWarningDirective } from './components/NoAccountWarning';
import { NoProtectionsdNoteWarningDirective } from './components/NoProtectionsNoteWarning';
function reloadHiddenFirefoxTab(): boolean { function reloadHiddenFirefoxTab(): boolean {
/** /**
@@ -67,14 +66,15 @@ function reloadHiddenFirefoxTab(): boolean {
*/ */
if ( if (
document.hidden && document.hidden &&
navigator.userAgent.toLowerCase().includes('firefox') && navigator.userAgent.toLowerCase().includes('firefox')
!localStorage.getItem('reloading')
) { ) {
localStorage.setItem('reloading', 'true'); document.addEventListener('visibilitychange', () => {
if (!document.hidden) {
location.reload(); location.reload();
}
});
return true; return true;
} else { } else {
localStorage.removeItem('reloading');
return false; return false;
} }
} }
@@ -138,12 +138,12 @@ const startApplication: StartApplication = async function startApplication(
.directive('menuRow', () => new MenuRow()) .directive('menuRow', () => new MenuRow())
.directive('panelResizer', () => new PanelResizer()) .directive('panelResizer', () => new PanelResizer())
.directive('passwordWizard', () => new PasswordWizard()) .directive('passwordWizard', () => new PasswordWizard())
.directive('permissionsModal', () => new PermissionsModal())
.directive('revisionPreviewModal', () => new RevisionPreviewModal()) .directive('revisionPreviewModal', () => new RevisionPreviewModal())
.directive('historyMenu', () => new HistoryMenu()) .directive('historyMenu', () => new HistoryMenu())
.directive('syncResolutionMenu', () => new SyncResolutionMenu()) .directive('syncResolutionMenu', () => new SyncResolutionMenu())
.directive('sessionsModal', SessionsModalDirective) .directive('sessionsModal', SessionsModalDirective)
.directive('noAccountWarning', NoAccountWarningDirective); .directive('noAccountWarning', NoAccountWarningDirective)
.directive('protectedNotePanel', NoProtectionsdNoteWarningDirective);
// Filters // Filters
angular.module('app').filter('trusted', ['$sce', trusted]); angular.module('app').filter('trusted', ['$sce', trusted]);
@@ -170,7 +170,10 @@ const startApplication: StartApplication = async function startApplication(
}; };
if (__WEB__) { if (__WEB__) {
startApplication((window as any)._default_sync_server, new BrowserBridge(__VERSION__)); startApplication(
(window as any)._default_sync_server,
new BrowserBridge(__VERSION__)
);
} else { } else {
(window as any).startApplication = startApplication; (window as any).startApplication = startApplication;
} }

View File

@@ -2,7 +2,9 @@ import { toDirective, useAutorunValue } from './utils';
import Close from '../../icons/ic_close.svg'; import Close from '../../icons/ic_close.svg';
import { AppState } from '@/ui_models/app_state'; import { AppState } from '@/ui_models/app_state';
function NoAccountWarning({ appState }: { appState: AppState }) { type Props = { appState: AppState };
function NoAccountWarning({ appState }: Props) {
const canShow = useAutorunValue(() => appState.noAccountWarning.show); const canShow = useAutorunValue(() => appState.noAccountWarning.show);
if (!canShow) { if (!canShow) {
return null; return null;
@@ -14,7 +16,7 @@ function NoAccountWarning({ appState }: { appState: AppState }) {
Sign in or register to back up your notes. Sign in or register to back up your notes.
</p> </p>
<button <button
className="sn-btn mt-3 col-start-1 col-end-3 justify-self-start" className="sn-button info mt-3 col-start-1 col-end-3 justify-self-start"
onClick={(event) => { onClick={(event) => {
event.stopPropagation(); event.stopPropagation();
appState.accountMenu.setShow(true); appState.accountMenu.setShow(true);
@@ -28,12 +30,13 @@ function NoAccountWarning({ appState }: { appState: AppState }) {
}} }}
title="Ignore" title="Ignore"
label="Ignore" label="Ignore"
style="height: 20px"
className="border-0 m-0 p-0 bg-transparent cursor-pointer rounded-md col-start-2 row-start-1 color-neutral hover:color-info" className="border-0 m-0 p-0 bg-transparent cursor-pointer rounded-md col-start-2 row-start-1 color-neutral hover:color-info"
> >
<Close className="fill-current" /> <Close className="fill-current block" />
</button> </button>
</div> </div>
); );
} }
export const NoAccountWarningDirective = toDirective(NoAccountWarning); export const NoAccountWarningDirective = toDirective<Props>(NoAccountWarning);

View File

@@ -0,0 +1,36 @@
import { AppState } from '@/ui_models/app_state';
import { toDirective } from './utils';
type Props = { appState: AppState; onViewNote: () => void };
function NoProtectionsNoteWarning({ appState, onViewNote }: Props) {
return (
<div className="flex flex-col items-center justify-center text-center max-w-md">
<h1 className="text-2xl m-0 w-full">This note is protected</h1>
<p className="text-lg mt-2 w-full">
Add a passcode or create an account to require authentication to view
this note.
</p>
<div className="mt-4 flex gap-3">
<button
className="sn-button info"
onClick={() => {
appState.accountMenu.setShow(true);
}}
>
Open account menu
</button>
<button className="sn-button outlined" onClick={onViewNote}>
View note
</button>
</div>
</div>
);
}
export const NoProtectionsdNoteWarningDirective = toDirective<Props>(
NoProtectionsNoteWarning,
{
onViewNote: '&',
}
);

View File

@@ -171,7 +171,7 @@ const SessionsModal: FunctionComponent<{
{formatter.format(session.updated_at)} {formatter.format(session.updated_at)}
</p> </p>
<button <button
className="sk-button danger sk-label" className="sn-button danger sk-label"
disabled={session.revoking} disabled={session.revoking}
onClick={() => onClick={() =>
setRevokingSessionUuid(session.uuid) setRevokingSessionUuid(session.uuid)
@@ -210,17 +210,16 @@ const SessionsModal: FunctionComponent<{
<AlertDialogDescription className="sk-panel-row"> <AlertDialogDescription className="sk-panel-row">
<p>{SessionStrings.RevokeText}</p> <p>{SessionStrings.RevokeText}</p>
</AlertDialogDescription> </AlertDialogDescription>
<div className="sk-panel-row"> <div className="flex my-1 gap-2">
<div className="sk-button-group">
<button <button
className="sk-button neutral sk-label" className="sn-button neutral sk-label"
ref={cancelRevokeRef} ref={cancelRevokeRef}
onClick={closeRevokeSessionAlert} onClick={closeRevokeSessionAlert}
> >
<span>{SessionStrings.RevokeCancelButton}</span> <span>{SessionStrings.RevokeCancelButton}</span>
</button> </button>
<button <button
className="sk-button danger sk-label" className="sn-button danger sk-label"
onClick={() => { onClick={() => {
closeRevokeSessionAlert(); closeRevokeSessionAlert();
revokeSession(confirmRevokingSessionUuid); revokeSession(confirmRevokingSessionUuid);
@@ -234,7 +233,6 @@ const SessionsModal: FunctionComponent<{
</div> </div>
</div> </div>
</div> </div>
</div>
</AlertDialog> </AlertDialog>
)} )}
</> </>

View File

@@ -20,11 +20,9 @@ export function useAutorun(
useEffect(() => autorun(view, opts), [view, opts]); useEffect(() => autorun(view, opts), [view, opts]);
} }
export function toDirective( export function toDirective<Props>(
component: FunctionComponent<{ component: FunctionComponent<Props>,
application: WebApplication; scope: Record<string, '=' | '&'> = {}
appState: AppState;
}>
) { ) {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
return function () { return function () {
@@ -37,10 +35,7 @@ export function toDirective(
return { return {
$onChanges() { $onChanges() {
render( render(
h(component, { h(component, $scope),
application: $scope.application,
appState: $scope.appState,
}),
$element[0] $element[0]
); );
}, },
@@ -50,6 +45,7 @@ export function toDirective(
scope: { scope: {
application: '=', application: '=',
appState: '=', appState: '=',
...scope,
}, },
}; };
}; };

View File

@@ -533,7 +533,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
if (this.application!.hasPasscode()) { if (this.application!.hasPasscode()) {
await this.application!.changePasscode(passcode); await this.application!.changePasscode(passcode);
} else { } else {
await this.application!.setPasscode(passcode); await this.application!.addPasscode(passcode);
} }
} }
); );

View File

@@ -7,7 +7,6 @@ export { InputModal } from './inputModal';
export { MenuRow } from './menuRow'; export { MenuRow } from './menuRow';
export { PanelResizer } from './panelResizer'; export { PanelResizer } from './panelResizer';
export { PasswordWizard } from './passwordWizard'; export { PasswordWizard } from './passwordWizard';
export { PermissionsModal } from './permissionsModal';
export { RevisionPreviewModal } from './revisionPreviewModal'; export { RevisionPreviewModal } from './revisionPreviewModal';
export { HistoryMenu } from './historyMenu'; export { HistoryMenu } from './historyMenu';
export { SyncResolutionMenu } from './syncResolutionMenu'; export { SyncResolutionMenu } from './syncResolutionMenu';

View File

@@ -1,47 +0,0 @@
import { WebDirective } from './../../types';
import template from '%/directives/permissions-modal.pug';
class PermissionsModalCtrl {
$element: JQLite
callback!: (success: boolean) => void
/* @ngInject */
constructor($element: JQLite) {
this.$element = $element;
}
dismiss() {
const elem = this.$element;
const scope = elem.scope();
scope.$destroy();
elem.remove();
}
accept() {
this.callback(true);
this.dismiss();
}
deny() {
this.callback(false);
this.dismiss();
}
}
export class PermissionsModal extends WebDirective {
constructor() {
super();
this.restrict = 'E';
this.template = template;
this.controller = PermissionsModalCtrl;
this.controllerAs = 'ctrl';
this.bindToController = true;
this.scope = {
show: '=',
component: '=',
permissionsString: '=',
callback: '='
};
}
}

View File

@@ -4,7 +4,6 @@
import '@reach/dialog/styles.css'; import '@reach/dialog/styles.css';
import 'sn-stylekit/dist/stylekit.css'; import 'sn-stylekit/dist/stylekit.css';
import '../stylesheets/index.css.scss'; import '../stylesheets/index.css.scss';
// import '../stylesheets/_reach-sub.scss';
// Vendor // Vendor
import 'angular'; import 'angular';

View File

@@ -17,6 +17,7 @@ export interface Bridge {
syncComponents(payloads: unknown[]): void; syncComponents(payloads: unknown[]): void;
onMajorDataChange(): void; onMajorDataChange(): void;
onInitialDataLoad(): void; onInitialDataLoad(): void;
onSignOut(): void;
onSearch(text?: string): void; onSearch(text?: string): void;
downloadBackup(): void | Promise<void>; downloadBackup(): void | Promise<void>;
} }

View File

@@ -30,4 +30,5 @@ export class BrowserBridge implements Bridge {
onInitialDataLoad(): void {} onInitialDataLoad(): void {}
onSearch(): void {} onSearch(): void {}
downloadBackup(): void {} downloadBackup(): void {}
onSignOut(): void {}
} }

View File

@@ -7,6 +7,7 @@ import {
ApplicationService, ApplicationService,
ApplicationEvent, ApplicationEvent,
removeFromArray, removeFromArray,
BackupFile,
} from '@standardnotes/snjs'; } from '@standardnotes/snjs';
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import { WebApplication } from '@/ui_models/application'; import { WebApplication } from '@/ui_models/application';
@@ -14,33 +15,32 @@ import { WebApplication } from '@/ui_models/application';
import { isDesktopApplication } from '@/utils'; import { isDesktopApplication } from '@/utils';
import { Bridge } from './bridge'; import { Bridge } from './bridge';
type UpdateObserverCallback = (component: SNComponent) => void type UpdateObserverCallback = (component: SNComponent) => void;
type ComponentActivationCallback = (payload: PurePayload) => void type ComponentActivationCallback = (payload: PurePayload) => void;
type ComponentActivationObserver = { type ComponentActivationObserver = {
id: string; id: string;
callback: ComponentActivationCallback; callback: ComponentActivationCallback;
} };
export class DesktopManager extends ApplicationService { export class DesktopManager extends ApplicationService {
$rootScope: ng.IRootScopeService;
$rootScope: ng.IRootScopeService $timeout: ng.ITimeoutService;
$timeout: ng.ITimeoutService componentActivationObservers: ComponentActivationObserver[] = [];
componentActivationObservers: ComponentActivationObserver[] = []
updateObservers: { updateObservers: {
callback: UpdateObserverCallback; callback: UpdateObserverCallback;
}[] = []; }[] = [];
isDesktop = isDesktopApplication(); isDesktop = isDesktopApplication();
dataLoaded = false dataLoaded = false;
lastSearchedText?: string lastSearchedText?: string;
private removeComponentObserver?: () => void; private removeComponentObserver?: () => void;
constructor( constructor(
$rootScope: ng.IRootScopeService, $rootScope: ng.IRootScopeService,
$timeout: ng.ITimeoutService, $timeout: ng.ITimeoutService,
application: WebApplication, application: WebApplication,
private bridge: Bridge, private bridge: Bridge
) { ) {
super(application); super(application);
this.$rootScope = $rootScope; this.$rootScope = $rootScope;
@@ -74,10 +74,7 @@ export class DesktopManager extends ApplicationService {
} }
getExtServerHost() { getExtServerHost() {
console.assert( console.assert(!!this.bridge.extensionsServerHost, 'extServerHost is null');
!!this.bridge.extensionsServerHost,
'extServerHost is null'
);
return this.bridge.extensionsServerHost; return this.bridge.extensionsServerHost;
} }
@@ -97,12 +94,14 @@ export class DesktopManager extends ApplicationService {
if (!this.isDesktop) { if (!this.isDesktop) {
return; return;
} }
Promise.all(components.map((component) => { Promise.all(
components.map((component) => {
return this.convertComponentForTransmission(component); return this.convertComponentForTransmission(component);
})).then((payloads) => { })
).then((payloads) => {
this.bridge.syncComponents( this.bridge.syncComponents(
payloads.filter(payload => payloads.filter(
!payload.errorDecrypting && !payload.waitingForKey (payload) => !payload.errorDecrypting && !payload.waitingForKey
) )
); );
}); });
@@ -110,7 +109,7 @@ export class DesktopManager extends ApplicationService {
registerUpdateObserver(callback: UpdateObserverCallback) { registerUpdateObserver(callback: UpdateObserverCallback) {
const observer = { const observer = {
callback: callback callback: callback,
}; };
this.updateObservers.push(observer); this.updateObservers.push(observer);
return () => { return () => {
@@ -153,19 +152,14 @@ export class DesktopManager extends ApplicationService {
(m) => { (m) => {
const mutator = m as ComponentMutator; const mutator = m as ComponentMutator;
if (error) { if (error) {
mutator.setAppDataItem( mutator.setAppDataItem(AppDataField.ComponentInstallError, error);
AppDataField.ComponentInstallError,
error
);
} else { } else {
mutator.local_url = componentData.content.local_url; mutator.local_url = componentData.content.local_url;
mutator.package_info = componentData.content.package_info; mutator.package_info = componentData.content.package_info;
mutator.setAppDataItem( mutator.setAppDataItem(AppDataField.ComponentInstallError, undefined);
AppDataField.ComponentInstallError,
undefined
);
} }
}); }
);
this.$timeout(() => { this.$timeout(() => {
for (const observer of this.updateObservers) { for (const observer of this.updateObservers) {
@@ -174,13 +168,17 @@ export class DesktopManager extends ApplicationService {
}); });
} }
desktop_registerComponentActivationObserver(callback: ComponentActivationCallback) { desktop_registerComponentActivationObserver(
callback: ComponentActivationCallback
) {
const observer = { id: `${Math.random}`, callback: callback }; const observer = { id: `${Math.random}`, callback: callback };
this.componentActivationObservers.push(observer); this.componentActivationObservers.push(observer);
return observer; return observer;
} }
desktop_deregisterComponentActivationObserver(observer: ComponentActivationObserver) { desktop_deregisterComponentActivationObserver(
observer: ComponentActivationObserver
) {
removeFromArray(this.componentActivationObservers, observer); removeFromArray(this.componentActivationObservers, observer);
} }
@@ -198,7 +196,9 @@ export class DesktopManager extends ApplicationService {
async desktop_requestBackupFile() { async desktop_requestBackupFile() {
const data = await this.application!.createBackupFile( const data = await this.application!.createBackupFile(
EncryptionIntent.FileEncrypted this.application.hasProtectionSources()
? EncryptionIntent.FileEncrypted
: EncryptionIntent.FileDecrypted
); );
if (data) { if (data) {
return JSON.stringify(data, null, 2); return JSON.stringify(data, null, 2);

View File

@@ -6,13 +6,12 @@ import { InputModalScope } from '@/directives/views/inputModal';
import { PasswordWizardType, PasswordWizardScope } from '@/types'; import { PasswordWizardType, PasswordWizardScope } from '@/types';
import { import {
SNApplication, SNApplication,
platformFromString,
SNComponent, SNComponent,
PermissionDialog, PermissionDialog,
DeinitSource, DeinitSource,
} from '@standardnotes/snjs'; } from '@standardnotes/snjs';
import angular from 'angular'; import angular from 'angular';
import { getPlatform, getPlatformString } from '@/utils'; import { getPlatform } from '@/utils';
import { AlertService } from '@/services/alertService'; import { AlertService } from '@/services/alertService';
import { WebDeviceInterface } from '@/web_device_interface'; import { WebDeviceInterface } from '@/web_device_interface';
import { import {
@@ -96,6 +95,9 @@ export class WebApplication extends SNApplication {
* to complete before destroying the global application instance and all its services */ * to complete before destroying the global application instance and all its services */
setTimeout(() => { setTimeout(() => {
super.deinit(source); super.deinit(source);
if (source === DeinitSource.SignOut) {
this.bridge.onSignOut();
}
}, 0); }, 0);
} }
@@ -204,10 +206,17 @@ export class WebApplication extends SNApplication {
} }
async openModalComponent(component: SNComponent): Promise<void> { async openModalComponent(component: SNComponent): Promise<void> {
if (component.package_info?.identifier === "org.standardnotes.batch-manager") { switch (component.package_info?.identifier) {
case 'org.standardnotes.batch-manager':
if (!await this.authorizeBatchManagerAccess()) { if (!await this.authorizeBatchManagerAccess()) {
return; return;
} }
break;
case 'org.standardnotes.cloudlink':
if (!await this.authorizeCloudLinkAccess()) {
return;
}
break;
} }
const scope = this.scope!.$new(true) as Partial<ComponentModalScope>; const scope = this.scope!.$new(true) as Partial<ComponentModalScope>;
scope.componentUuid = component.uuid; scope.componentUuid = component.uuid;

View File

@@ -26,7 +26,6 @@
.sk-sublabel(ng-if='descriptor.identifier == ctrl.activeApplication.identifier') .sk-sublabel(ng-if='descriptor.identifier == ctrl.activeApplication.identifier')
| Current Application | Current Application
.sk-menu-panel-column(ng-if='descriptor.identifier == ctrl.activeApplication.identifier') .sk-menu-panel-column(ng-if='descriptor.identifier == ctrl.activeApplication.identifier')
.sk-button.success( button.sn-button.success(
ng-click='ctrl.renameDescriptor($event, descriptor)' ng-click='ctrl.renameDescriptor($event, descriptor)'
) ) Rename
.sk-label Rename

View File

@@ -1,4 +1,4 @@
.main-ui-view( .main-ui-view.sn-component(
ng-class='self.platformString' ng-class='self.platformString'
) )
#app.app( #app.app(

View File

@@ -279,18 +279,16 @@ function ChallengeModalView({ ctrl }: { ctrl: ChallengeModalCtrl }) {
</div> </div>
</div> </div>
<div className="sk-panel-footer extra-padding"> <div className="sk-panel-footer extra-padding">
<div <button
className={ className={
'sk-button big block bold ' + 'sn-button w-full py-3 text-base ' +
(ctrl.state.processing ? 'neutral' : 'info') (ctrl.state.processing ? 'neutral' : 'info')
} }
disabled={ctrl.state.processing} disabled={ctrl.state.processing}
onClick={() => ctrl.submit()} onClick={() => ctrl.submit()}
> >
<div className="sk-label">
{ctrl.state.processing ? 'Generating Keys…' : 'Submit'} {ctrl.state.processing ? 'Generating Keys…' : 'Submit'}
</div> </button>
</div>
{ctrl.challenge.cancelable && ( {ctrl.challenge.cancelable && (
<> <>
<div className="sk-panel-row"></div> <div className="sk-panel-row"></div>

View File

@@ -1,4 +1,12 @@
#editor-column.section.editor.sn-component(aria-label='Note') #editor-column.section.editor.sn-component(aria-label='Note')
protected-note-panel.h-full.flex.justify-center.items-center(
ng-if='self.state.showProtectedWarning'
app-state='self.appState'
on-view-note='self.dismissProtectedWarning()'
)
.flex-grow.flex.flex-col(
ng-if='!self.state.showProtectedWarning'
)
.sn-component .sn-component
.sk-app-bar.no-edges( .sk-app-bar.no-edges(
ng-if='self.noteLocked', ng-if='self.noteLocked',

View File

@@ -1,4 +1,8 @@
import { Strings, STRING_ARCHIVE_LOCKED_ATTEMPT, STRING_SAVING_WHILE_DOCUMENT_HIDDEN, STRING_UNARCHIVE_LOCKED_ATTEMPT } from './../../strings'; import {
STRING_ARCHIVE_LOCKED_ATTEMPT,
STRING_SAVING_WHILE_DOCUMENT_HIDDEN,
STRING_UNARCHIVE_LOCKED_ATTEMPT,
} from './../../strings';
import { Editor } from '@/ui_models/editor'; import { Editor } from '@/ui_models/editor';
import { WebApplication } from '@/ui_models/application'; import { WebApplication } from '@/ui_models/application';
import { PanelPuppet, WebDirective } from '@/types'; import { PanelPuppet, WebDirective } from '@/types';
@@ -31,7 +35,7 @@ import {
STRING_DELETE_PLACEHOLDER_ATTEMPT, STRING_DELETE_PLACEHOLDER_ATTEMPT,
STRING_DELETE_LOCKED_ATTEMPT, STRING_DELETE_LOCKED_ATTEMPT,
StringDeleteNote, StringDeleteNote,
StringEmptyTrash StringEmptyTrash,
} from '@/strings'; } from '@/strings';
import { alertDialog, confirmDialog } from '@/services/alertService'; import { alertDialog, confirmDialog } from '@/services/alertService';
@@ -45,88 +49,91 @@ const ElementIds = {
NoteTextEditor: 'note-text-editor', NoteTextEditor: 'note-text-editor',
NoteTitleEditor: 'note-title-editor', NoteTitleEditor: 'note-title-editor',
EditorContent: 'editor-content', EditorContent: 'editor-content',
NoteTagsComponentContainer: 'note-tags-component-container' NoteTagsComponentContainer: 'note-tags-component-container',
}; };
type NoteStatus = { type NoteStatus = {
message?: string message?: string;
date?: Date date?: Date;
} };
type EditorState = { type EditorState = {
stackComponents: SNComponent[] stackComponents: SNComponent[];
editorComponent?: SNComponent editorComponent?: SNComponent;
tagsComponent?: SNComponent tagsComponent?: SNComponent;
saveError?: any saveError?: any;
noteStatus?: NoteStatus noteStatus?: NoteStatus;
tagsAsStrings?: string tagsAsStrings?: string;
marginResizersEnabled?: boolean marginResizersEnabled?: boolean;
monospaceFont?: boolean monospaceFont?: boolean;
isDesktop?: boolean isDesktop?: boolean;
syncTakingTooLong: boolean syncTakingTooLong: boolean;
showActionsMenu: boolean showActionsMenu: boolean;
showOptionsMenu: boolean showOptionsMenu: boolean;
showEditorMenu: boolean showEditorMenu: boolean;
showHistoryMenu: boolean showHistoryMenu: boolean;
altKeyDown: boolean altKeyDown: boolean;
spellcheck: boolean spellcheck: boolean;
/** /**
* Setting to false then true will allow the current editor component-view to be destroyed * Setting to false then true will allow the current editor component-view to be destroyed
* then re-initialized. Used when changing between component editors. * then re-initialized. Used when changing between component editors.
*/ */
editorUnloading: boolean editorUnloading: boolean;
/** Setting to true then false will allow the main content textarea to be destroyed /** Setting to true then false will allow the main content textarea to be destroyed
* then re-initialized. Used when reloading spellcheck status. */ * then re-initialized. Used when reloading spellcheck status. */
textareaUnloading: boolean textareaUnloading: boolean;
/** Fields that can be directly mutated by the template */ /** Fields that can be directly mutated by the template */
mutable: any mutable: any;
} showProtectedWarning: boolean;
};
type EditorValues = { type EditorValues = {
title?: string title?: string;
text?: string text?: string;
tagsInputValue?: string tagsInputValue?: string;
} };
function sortAlphabetically(array: SNComponent[]): SNComponent[] { function sortAlphabetically(array: SNComponent[]): SNComponent[] {
return array.sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1); return array.sort((a, b) =>
a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1
);
} }
class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> { class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
/** Passed through template */ /** Passed through template */
readonly application!: WebApplication readonly application!: WebApplication;
readonly editor!: Editor readonly editor!: Editor;
private leftPanelPuppet?: PanelPuppet private leftPanelPuppet?: PanelPuppet;
private rightPanelPuppet?: PanelPuppet private rightPanelPuppet?: PanelPuppet;
private unregisterComponent: any private unregisterComponent: any;
private saveTimeout?: ng.IPromise<void> private saveTimeout?: ng.IPromise<void>;
private statusTimeout?: ng.IPromise<void> private statusTimeout?: ng.IPromise<void>;
private lastEditorFocusEventSource?: EventSource private lastEditorFocusEventSource?: EventSource;
public editorValues: EditorValues = {} public editorValues: EditorValues = {};
onEditorLoad?: () => void onEditorLoad?: () => void;
private tags: SNTag[] = []; private tags: SNTag[] = [];
private removeAltKeyObserver?: any private removeAltKeyObserver?: any;
private removeTrashKeyObserver?: any private removeTrashKeyObserver?: any;
private removeTabObserver?: any private removeTabObserver?: any;
private removeTagsObserver!: () => void private removeTagsObserver!: () => void;
private removeComponentsObserver!: () => void private removeComponentsObserver!: () => void;
prefKeyMonospace: string prefKeyMonospace: string;
prefKeySpellcheck: string prefKeySpellcheck: string;
prefKeyMarginResizers: string prefKeyMarginResizers: string;
/* @ngInject */ /* @ngInject */
constructor($timeout: ng.ITimeoutService) { constructor($timeout: ng.ITimeoutService) {
super($timeout); super($timeout);
this.leftPanelPuppet = { this.leftPanelPuppet = {
onReady: () => this.reloadPreferences() onReady: () => this.reloadPreferences(),
}; };
this.rightPanelPuppet = { this.rightPanelPuppet = {
onReady: () => this.reloadPreferences() onReady: () => this.reloadPreferences(),
}; };
/** Used by .pug template */ /** Used by .pug template */
this.prefKeyMonospace = PrefKey.EditorMonospaceEnabled; this.prefKeyMonospace = PrefKey.EditorMonospaceEnabled;
@@ -195,7 +202,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (note.lastSyncEnd) { if (note.lastSyncEnd) {
if (note.lastSyncBegan!.getTime() > note.lastSyncEnd!.getTime()) { if (note.lastSyncBegan!.getTime() > note.lastSyncEnd!.getTime()) {
this.showSavingStatus(); this.showSavingStatus();
} else if (note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()) { } else if (
note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()
) {
this.showAllChangesSavedStatus(); this.showAllChangesSavedStatus();
} }
} else { } else {
@@ -222,8 +231,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
editorUnloading: false, editorUnloading: false,
textareaUnloading: false, textareaUnloading: false,
mutable: { mutable: {
tagsString: '' tagsString: '',
} },
showProtectedWarning: false,
} as EditorState; } as EditorState;
} }
@@ -263,8 +273,8 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
break; break;
case ApplicationEvent.LocalDatabaseWriteError: case ApplicationEvent.LocalDatabaseWriteError:
this.showErrorStatus({ this.showErrorStatus({
message: "Offline Saving Issue", message: 'Offline Saving Issue',
desc: "Changes not saved" desc: 'Changes not saved',
}); });
break; break;
} }
@@ -272,15 +282,18 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async handleEditorNoteChange() { async handleEditorNoteChange() {
this.cancelPendingSetStatus(); this.cancelPendingSetStatus();
const note = this.editor.note;
const showProtectedWarning =
note.protected && !this.application.hasProtectionSources();
await this.setState({ await this.setState({
showActionsMenu: false, showActionsMenu: false,
showOptionsMenu: false, showOptionsMenu: false,
showEditorMenu: false, showEditorMenu: false,
showHistoryMenu: false, showHistoryMenu: false,
altKeyDown: false, altKeyDown: false,
noteStatus: undefined noteStatus: undefined,
showProtectedWarning,
}); });
const note = this.editor.note;
this.editorValues.title = note.title; this.editorValues.title = note.title;
this.editorValues.text = note.text; this.editorValues.text = note.text;
this.reloadEditor(); this.reloadEditor();
@@ -288,11 +301,18 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
this.reloadPreferences(); this.reloadPreferences();
this.reloadStackComponents(); this.reloadStackComponents();
this.reloadNoteTagsComponent(); this.reloadNoteTagsComponent();
if (note.safeText().length === 0) { if (note.safeText().length === 0 && !showProtectedWarning) {
this.focusTitle(); this.focusTitle();
} }
} }
async dismissProtectedWarning() {
await this.setState({
showProtectedWarning: false,
});
this.focusTitle();
}
/** /**
* 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,
@@ -331,7 +351,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
private async reloadEditor() { private async reloadEditor() {
const newEditor = this.application.componentManager!.editorForNote(this.note); const newEditor = this.application.componentManager!.editorForNote(
this.note
);
/** Editors cannot interact with template notes so the note must be inserted */ /** Editors cannot interact with template notes so the note must be inserted */
if (newEditor && this.editor.isTemplateNote) { if (newEditor && this.editor.isTemplateNote) {
await this.editor.insertTemplatedNote(); await this.editor.insertTemplatedNote();
@@ -340,7 +362,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (currentEditor?.uuid !== newEditor?.uuid) { if (currentEditor?.uuid !== newEditor?.uuid) {
await this.setState({ await this.setState({
/** Unload current component view so that we create a new one */ /** Unload current component view so that we create a new one */
editorUnloading: true editorUnloading: true,
}); });
await this.setState({ await this.setState({
/** Reload component view */ /** Reload component view */
@@ -349,12 +371,14 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}); });
this.reloadFont(); this.reloadFont();
} }
this.application.componentManager!.contextItemDidChangeInArea(ComponentArea.Editor); this.application.componentManager!.contextItemDidChangeInArea(
ComponentArea.Editor
);
} }
setMenuState(menu: string, state: boolean) { setMenuState(menu: string, state: boolean) {
this.setState({ this.setState({
[menu]: state [menu]: state,
}); });
this.closeAllMenus(menu); this.closeAllMenus(menu);
} }
@@ -392,12 +416,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}); });
this.reloadEditor(); this.reloadEditor();
} }
if (this.state.editorComponent?.isExplicitlyEnabledForItem(this.note.uuid)) { if (
await this.disassociateComponentWithCurrentNote(this.state.editorComponent); this.state.editorComponent?.isExplicitlyEnabledForItem(this.note.uuid)
) {
await this.disassociateComponentWithCurrentNote(
this.state.editorComponent
);
} }
this.reloadFont(); this.reloadFont();
} } else if (component.area === ComponentArea.Editor) {
else if (component.area === ComponentArea.Editor) {
const currentEditor = this.state.editorComponent; const currentEditor = this.state.editorComponent;
if (currentEditor && component !== currentEditor) { if (currentEditor && component !== currentEditor) {
await this.disassociateComponentWithCurrentNote(currentEditor); await this.disassociateComponentWithCurrentNote(currentEditor);
@@ -410,8 +437,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}); });
} }
await this.associateComponentWithCurrentNote(component); await this.associateComponentWithCurrentNote(component);
} } else if (component.area === ComponentArea.EditorStack) {
else if (component.area === ComponentArea.EditorStack) {
await this.toggleStackComponentForCurrentItem(component); await this.toggleStackComponentForCurrentItem(component);
} }
/** Dirtying can happen above */ /** Dirtying can happen above */
@@ -419,8 +445,10 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
hasAvailableExtensions() { hasAvailableExtensions() {
return this.application.actionsManager!. return (
extensionsInContextOfItem(this.note).length > 0; this.application.actionsManager!.extensionsInContextOfItem(this.note)
.length > 0
);
} }
/** /**
@@ -444,37 +472,33 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
closeAfterSync = false closeAfterSync = false
) { ) {
if (document.hidden) { if (document.hidden) {
this.application.alertService!.alert( this.application.alertService!.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
STRING_SAVING_WHILE_DOCUMENT_HIDDEN
);
return; return;
} }
const note = this.note; const note = this.note;
if (note.deleted) { if (note.deleted) {
this.application.alertService!.alert( this.application.alertService!.alert(STRING_DELETED_NOTE);
STRING_DELETED_NOTE
);
return; return;
} }
if (this.editor.isTemplateNote) { if (this.editor.isTemplateNote) {
await this.editor.insertTemplatedNote(); await this.editor.insertTemplatedNote();
} }
const selectedTag = this.appState.selectedTag; const selectedTag = this.appState.selectedTag;
if (!selectedTag?.isSmartTag && !selectedTag?.hasRelationshipWithItem(note)) { if (
await this.application.changeItem( !selectedTag?.isSmartTag &&
selectedTag!.uuid, !selectedTag?.hasRelationshipWithItem(note)
(mutator) => { ) {
await this.application.changeItem(selectedTag!.uuid, (mutator) => {
mutator.addItemAsRelationship(note); mutator.addItemAsRelationship(note);
} });
);
} }
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;
} }
await this.application.changeItem(note.uuid, (mutator) => { await this.application.changeItem(
note.uuid,
(mutator) => {
const noteMutator = mutator as NoteMutator; const noteMutator = mutator as NoteMutator;
if (customMutate) { if (customMutate) {
customMutate(noteMutator); customMutate(noteMutator);
@@ -489,7 +513,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
noteMutator.preview_plain = previewPlain; noteMutator.preview_plain = previewPlain;
noteMutator.preview_html = undefined; noteMutator.preview_html = undefined;
} }
}, isUserModified); },
isUserModified
);
if (this.saveTimeout) { if (this.saveTimeout) {
this.$timeout.cancel(this.saveTimeout); this.$timeout.cancel(this.saveTimeout);
} }
@@ -506,16 +532,13 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
showSavingStatus() { showSavingStatus() {
this.setStatus( this.setStatus({ message: 'Saving…' }, false);
{ message: "Saving…" },
false
);
} }
showAllChangesSavedStatus() { showAllChangesSavedStatus() {
this.setState({ this.setState({
saveError: false, saveError: false,
syncTakingTooLong: false syncTakingTooLong: false,
}); });
this.setStatus({ this.setStatus({
message: 'All changes saved', message: 'All changes saved',
@@ -525,13 +548,13 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
showErrorStatus(error?: any) { showErrorStatus(error?: any) {
if (!error) { if (!error) {
error = { error = {
message: "Sync Unreachable", message: 'Sync Unreachable',
desc: "Changes saved offline" desc: 'Changes saved offline',
}; };
} }
this.setState({ this.setState({
saveError: true, saveError: true,
syncTakingTooLong: false syncTakingTooLong: false,
}); });
this.setStatus(error); this.setStatus(error);
} }
@@ -543,12 +566,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (wait) { if (wait) {
this.statusTimeout = this.$timeout(() => { this.statusTimeout = this.$timeout(() => {
this.setState({ this.setState({
noteStatus: status noteStatus: status,
}); });
}, MINIMUM_STATUS_DURATION); }, MINIMUM_STATUS_DURATION);
} else { } else {
this.setState({ this.setState({
noteStatus: status noteStatus: status,
}); });
} }
} }
@@ -560,10 +583,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
contentChanged() { contentChanged() {
this.saveNote( this.saveNote(false, true);
false,
true
);
} }
onTitleEnter($event: Event) { onTitleEnter($event: Event) {
@@ -573,11 +593,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
onTitleChange() { onTitleChange() {
this.saveNote( this.saveNote(false, true, true);
false,
true,
true,
);
} }
focusEditor() { focusEditor() {
@@ -597,17 +613,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleFocus() { onTitleFocus() {}
}
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleBlur() { onTitleBlur() {}
}
onContentFocus() { onContentFocus() {
this.application.getAppState().editorDidFocus(this.lastEditorFocusEventSource!); this.application
.getAppState()
.editorDidFocus(this.lastEditorFocusEventSource!);
this.lastEditorFocusEventSource = undefined; this.lastEditorFocusEventSource = undefined;
} }
@@ -619,39 +633,29 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async deleteNote(permanently: boolean) { async deleteNote(permanently: boolean) {
if (this.editor.isTemplateNote) { if (this.editor.isTemplateNote) {
this.application.alertService!.alert( this.application.alertService!.alert(STRING_DELETE_PLACEHOLDER_ATTEMPT);
STRING_DELETE_PLACEHOLDER_ATTEMPT
);
return; return;
} }
if (this.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.note.safeTitle().length const title = this.note.safeTitle().length
? `'${this.note.title}'` ? `'${this.note.title}'`
: "this note"; : 'this note';
const text = StringDeleteNote( const text = StringDeleteNote(title, permanently);
title, if (
permanently await confirmDialog({
);
if (await confirmDialog({
text, text,
confirmButtonStyle: 'danger' confirmButtonStyle: 'danger',
})) { })
) {
if (permanently) { if (permanently) {
this.performNoteDeletion(this.note); this.performNoteDeletion(this.note);
} else { } else {
this.saveNote( this.saveNote(true, false, true, (mutator) => {
true,
false,
true,
(mutator) => {
mutator.trashed = true; mutator.trashed = true;
} });
);
} }
} }
} }
@@ -682,35 +686,27 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async emptyTrash() { async emptyTrash() {
const count = this.getTrashCount(); const count = this.getTrashCount();
if (await confirmDialog({ if (
await confirmDialog({
text: StringEmptyTrash(count), text: StringEmptyTrash(count),
confirmButtonStyle: 'danger' confirmButtonStyle: 'danger',
})) { })
) {
this.application.emptyTrash(); this.application.emptyTrash();
this.application.sync(); this.application.sync();
} }
} }
togglePin() { togglePin() {
this.saveNote( this.saveNote(true, false, true, (mutator) => {
true,
false,
true,
(mutator) => {
mutator.pinned = !this.note.pinned; mutator.pinned = !this.note.pinned;
} });
);
} }
toggleLockNote() { toggleLockNote() {
this.saveNote( this.saveNote(true, false, true, (mutator) => {
true,
false,
true,
(mutator) => {
mutator.locked = !this.note.locked; mutator.locked = !this.note.locked;
} });
);
} }
async toggleProtectNote() { async toggleProtectNote() {
@@ -719,34 +715,25 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} else { } else {
const note = await this.application.protectNote(this.note); const note = await this.application.protectNote(this.note);
if (note?.protected && !this.application.hasProtectionSources()) { if (note?.protected && !this.application.hasProtectionSources()) {
if (await confirmDialog({ this.setState({
text: Strings.protectingNoteWithoutProtectionSources, showProtectedWarning: true,
confirmButtonText: Strings.openAccountMenu, });
confirmButtonStyle: 'info',
})) {
this.appState.accountMenu.setShow(true);
}
} }
} }
} }
toggleNotePreview() { toggleNotePreview() {
this.saveNote( this.saveNote(true, false, true, (mutator) => {
true,
false,
true,
(mutator) => {
mutator.hidePreview = !this.note.hidePreview; mutator.hidePreview = !this.note.hidePreview;
} });
);
} }
toggleArchiveNote() { toggleArchiveNote() {
if (this.note.locked) { if (this.note.locked) {
alertDialog({ alertDialog({
text: this.note.archived ? text: this.note.archived
STRING_UNARCHIVE_LOCKED_ATTEMPT : ? STRING_UNARCHIVE_LOCKED_ATTEMPT
STRING_ARCHIVE_LOCKED_ATTEMPT, : STRING_ARCHIVE_LOCKED_ATTEMPT,
}); });
return; return;
} }
@@ -774,10 +761,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
for (let i = 0; i < tags.length; i++) { for (let i = 0; i < tags.length; i++) {
const localTag = this.tags[i]; const localTag = this.tags[i];
const tag = tags[i]; const tag = tags[i];
if ( if (tag.title !== localTag.title || tag.uuid !== localTag.uuid) {
tag.title !== localTag.title ||
tag.uuid !== localTag.uuid
) {
this.reloadTagsString(tags); this.reloadTagsString(tags);
break; break;
} }
@@ -803,9 +787,11 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
removeTag(tag: SNTag) { removeTag(tag: SNTag) {
const tags = this.appState.getNoteTags(this.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) => {
return title !== tag.title; return title !== tag.title;
}); });
this.saveTagsFromStrings(strings); this.saveTagsFromStrings(strings);
@@ -818,14 +804,14 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
public async saveTagsFromStrings(strings?: string[]) { public async saveTagsFromStrings(strings?: string[]) {
if ( if (
!strings !strings &&
&& this.editorValues.tagsInputValue === this.state.tagsAsStrings this.editorValues.tagsInputValue === this.state.tagsAsStrings
) { ) {
return; return;
} }
if (!strings) { if (!strings) {
strings = this.editorValues.tagsInputValue! strings = this.editorValues
.split('#') .tagsInputValue!.split('#')
.filter((string) => { .filter((string) => {
return string.length > 0; return string.length > 0;
}) })
@@ -848,23 +834,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
const newRelationships: SNTag[] = []; const newRelationships: SNTag[] = [];
for (const title of strings) { for (const title of strings) {
const existingRelationship = find( const existingRelationship = find(currentTags, { title: title });
currentTags,
{ title: title }
);
if (!existingRelationship) { if (!existingRelationship) {
newRelationships.push( newRelationships.push(await this.application.findOrCreateTag(title));
await this.application.findOrCreateTag(title)
);
} }
} }
if (newRelationships.length > 0) { if (newRelationships.length > 0) {
await this.application.changeItems( await this.application.changeItems(Uuids(newRelationships), (mutator) => {
Uuids(newRelationships),
(mutator) => {
mutator.addItemAsRelationship(note); mutator.addItemAsRelationship(note);
} });
);
} }
this.application.sync(); this.application.sync();
this.reloadTags(); this.reloadTags();
@@ -872,24 +850,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async onPanelResizeFinish(width: number, left: number, isMaxWidth: boolean) { async onPanelResizeFinish(width: number, left: number, isMaxWidth: boolean) {
if (isMaxWidth) { if (isMaxWidth) {
await this.application.setPreference( await this.application.setPreference(PrefKey.EditorWidth, null);
PrefKey.EditorWidth,
null
);
} else { } else {
if (width !== undefined && width !== null) { if (width !== undefined && width !== null) {
await this.application.setPreference( await this.application.setPreference(PrefKey.EditorWidth, width);
PrefKey.EditorWidth,
width
);
this.leftPanelPuppet!.setWidth!(width); this.leftPanelPuppet!.setWidth!(width);
} }
} }
if (left !== undefined && left !== null) { if (left !== undefined && left !== null) {
await this.application.setPreference( await this.application.setPreference(PrefKey.EditorLeft, left);
PrefKey.EditorLeft,
left
);
this.rightPanelPuppet!.setLeft!(left); this.rightPanelPuppet!.setLeft!(left);
} }
this.application.sync(); this.application.sync();
@@ -911,7 +880,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
await this.setState({ await this.setState({
monospaceFont, monospaceFont,
spellcheck, spellcheck,
marginResizersEnabled marginResizersEnabled,
}); });
if (!document.getElementById(ElementIds.EditorContent)) { if (!document.getElementById(ElementIds.EditorContent)) {
@@ -926,18 +895,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
this.leftPanelPuppet?.ready && this.leftPanelPuppet?.ready &&
this.rightPanelPuppet?.ready this.rightPanelPuppet?.ready
) { ) {
const width = this.application.getPreference( const width = this.application.getPreference(PrefKey.EditorWidth, null);
PrefKey.EditorWidth,
null
);
if (width != null) { if (width != null) {
this.leftPanelPuppet!.setWidth!(width); this.leftPanelPuppet!.setWidth!(width);
this.rightPanelPuppet!.setWidth!(width); this.rightPanelPuppet!.setWidth!(width);
} }
const left = this.application.getPreference( const left = this.application.getPreference(PrefKey.EditorLeft, null);
PrefKey.EditorLeft,
null
);
if (left != null) { if (left != null) {
this.leftPanelPuppet!.setLeft!(left); this.leftPanelPuppet!.setLeft!(left);
this.rightPanelPuppet!.setLeft!(left); this.rightPanelPuppet!.setLeft!(left);
@@ -949,10 +912,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
const root = document.querySelector(':root') as HTMLElement; const root = document.querySelector(':root') as HTMLElement;
const propertyName = '--sn-stylekit-editor-font-family'; const propertyName = '--sn-stylekit-editor-font-family';
if (this.state.monospaceFont) { if (this.state.monospaceFont) {
root.style.setProperty( root.style.setProperty(propertyName, 'var(--sn-stylekit-monospace-font)');
propertyName,
'var(--sn-stylekit-monospace-font)'
);
} else { } else {
root.style.setProperty( root.style.setProperty(
propertyName, propertyName,
@@ -963,12 +923,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async toggleWebPrefKey(key: PrefKey) { async toggleWebPrefKey(key: PrefKey) {
const currentValue = (this.state as any)[key]; const currentValue = (this.state as any)[key];
await this.application.setPreference( await this.application.setPreference(key, !currentValue);
key,
!currentValue,
);
await this.setState({ await this.setState({
[key]: !currentValue [key]: !currentValue,
}); });
this.reloadFont(); this.reloadFont();
@@ -977,7 +934,10 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
await this.setState({ textareaUnloading: true }); await this.setState({ textareaUnloading: true });
await this.setState({ textareaUnloading: false }); await this.setState({ textareaUnloading: false });
this.reloadFont(); this.reloadFont();
} else if (key === PrefKey.EditorResizersEnabled && this.state[key] === true) { } else if (
key === PrefKey.EditorResizersEnabled &&
this.state[key] === true
) {
this.$timeout(() => { this.$timeout(() => {
this.leftPanelPuppet!.flash!(); this.leftPanelPuppet!.flash!();
this.rightPanelPuppet!.flash!(); this.rightPanelPuppet!.flash!();
@@ -988,12 +948,13 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
/** @components */ /** @components */
registerComponentHandler() { registerComponentHandler() {
this.unregisterComponent = this.application.componentManager!.registerHandler({ this.unregisterComponent = this.application.componentManager!.registerHandler(
{
identifier: 'editor', identifier: 'editor',
areas: [ areas: [
ComponentArea.NoteTags, ComponentArea.NoteTags,
ComponentArea.EditorStack, ComponentArea.EditorStack,
ComponentArea.Editor ComponentArea.Editor,
], ],
contextRequestHandler: (componentUuid) => { contextRequestHandler: (componentUuid) => {
const currentEditor = this.state.editorComponent; const currentEditor = this.state.editorComponent;
@@ -1014,12 +975,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (action === ComponentAction.SetSize) { if (action === ComponentAction.SetSize) {
const setSize = ( const setSize = (
element: HTMLElement, element: HTMLElement,
size: { width: string | number, height: string | number } size: { width: string | number; height: string | number }
) => { ) => {
const widthString = typeof size.width === 'string' const widthString =
? size.width typeof size.width === 'string' ? size.width : `${data.width}px`;
: `${data.width}px`; const heightString =
const heightString = typeof size.height === 'string' typeof size.height === 'string'
? size.height ? size.height
: `${data.height}px`; : `${data.height}px`;
element.setAttribute( element.setAttribute(
@@ -1032,22 +993,21 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
const container = document.getElementById( const container = document.getElementById(
ElementIds.NoteTagsComponentContainer ElementIds.NoteTagsComponentContainer
); );
setSize(container!, { width: data.width!, height: data.height! }); setSize(container!, {
width: data.width!,
height: data.height!,
});
} }
} }
} } else if (action === ComponentAction.AssociateItem) {
else if (action === ComponentAction.AssociateItem) {
if (data.item!.content_type === ContentType.Tag) { if (data.item!.content_type === ContentType.Tag) {
const tag = this.application.findItem(data.item!.uuid) as SNTag; const tag = this.application.findItem(data.item!.uuid) as SNTag;
this.addTag(tag); this.addTag(tag);
} }
} } else if (action === ComponentAction.DeassociateItem) {
else if (action === ComponentAction.DeassociateItem) {
const tag = this.application.findItem(data.item!.uuid) as SNTag; const tag = this.application.findItem(data.item!.uuid) as SNTag;
this.removeTag(tag); this.removeTag(tag);
} else if ( } else if (action === ComponentAction.SaveSuccess) {
action === ComponentAction.SaveSuccess
) {
const savedUuid = data.item ? data.item.uuid : data.items![0].uuid; const savedUuid = data.item ? data.item.uuid : data.items![0].uuid;
if (savedUuid === this.note.uuid) { if (savedUuid === this.note.uuid) {
const selectedTag = this.appState.selectedTag; const selectedTag = this.appState.selectedTag;
@@ -1064,23 +1024,30 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
} }
} }
},
} }
}); );
} }
async reloadNoteTagsComponent() { async reloadNoteTagsComponent() {
const [tagsComponent] = const [
this.application.componentManager!.componentsForArea(ComponentArea.NoteTags); tagsComponent,
] = this.application.componentManager!.componentsForArea(
ComponentArea.NoteTags
);
await this.setState({ await this.setState({
tagsComponent: tagsComponent?.active ? tagsComponent : undefined tagsComponent: tagsComponent?.active ? tagsComponent : undefined,
}); });
this.application.componentManager!.contextItemDidChangeInArea(ComponentArea.NoteTags); this.application.componentManager!.contextItemDidChangeInArea(
ComponentArea.NoteTags
);
} }
async reloadStackComponents() { async reloadStackComponents() {
const stackComponents = sortAlphabetically( const stackComponents = sortAlphabetically(
this.application.componentManager!.componentsForArea(ComponentArea.EditorStack) this.application
.filter(component => component.active) .componentManager!.componentsForArea(ComponentArea.EditorStack)
.filter((component) => component.active)
); );
if (this.note) { if (this.note) {
for (const component of stackComponents) { for (const component of stackComponents) {
@@ -1093,7 +1060,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
} }
await this.setState({ stackComponents }); await this.setState({ stackComponents });
this.application.componentManager!.contextItemDidChangeInArea(ComponentArea.EditorStack); this.application.componentManager!.contextItemDidChangeInArea(
ComponentArea.EditorStack
);
} }
stackComponentHidden(component: SNComponent) { stackComponentHidden(component: SNComponent) {
@@ -1101,11 +1070,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
async toggleStackComponentForCurrentItem(component: SNComponent) { async toggleStackComponentForCurrentItem(component: SNComponent) {
const hidden = this.application.componentManager!.isComponentHidden(component); const hidden = this.application.componentManager!.isComponentHidden(
component
);
if (hidden || !component.active) { if (hidden || !component.active) {
this.application.componentManager!.setComponentHidden(component, false); this.application.componentManager!.setComponentHidden(component, false);
await this.associateComponentWithCurrentNote(component); await this.associateComponentWithCurrentNote(component);
this.application.componentManager!.contextItemDidChangeInArea(ComponentArea.EditorStack); this.application.componentManager!.contextItemDidChangeInArea(
ComponentArea.EditorStack
);
} else { } else {
this.application.componentManager!.setComponentHidden(component, true); this.application.componentManager!.setComponentHidden(component, true);
await this.disassociateComponentWithCurrentNote(component); await this.disassociateComponentWithCurrentNote(component);
@@ -1132,28 +1105,27 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
registerKeyboardShortcuts() { registerKeyboardShortcuts() {
this.removeAltKeyObserver = this.application.getKeyboardService().addKeyObserver({ this.removeAltKeyObserver = this.application
modifiers: [ .getKeyboardService()
KeyboardModifier.Alt .addKeyObserver({
], modifiers: [KeyboardModifier.Alt],
onKeyDown: () => { onKeyDown: () => {
this.setState({ this.setState({
altKeyDown: true altKeyDown: true,
}); });
}, },
onKeyUp: () => { onKeyUp: () => {
this.setState({ this.setState({
altKeyDown: false altKeyDown: false,
}); });
} },
}); });
this.removeTrashKeyObserver = this.application.getKeyboardService().addKeyObserver({ this.removeTrashKeyObserver = this.application
.getKeyboardService()
.addKeyObserver({
key: KeyboardKey.Backspace, key: KeyboardKey.Backspace,
notElementIds: [ notElementIds: [ElementIds.NoteTextEditor, ElementIds.NoteTitleEditor],
ElementIds.NoteTextEditor,
ElementIds.NoteTitleEditor
],
modifiers: [KeyboardModifier.Meta], modifiers: [KeyboardModifier.Meta],
onKeyDown: () => { onKeyDown: () => {
this.deleteNote(false); this.deleteNote(false);
@@ -1171,8 +1143,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
* If the shift key is pressed first, this event is * If the shift key is pressed first, this event is
* not fired. * not fired.
*/ */
const editor = document.getElementById(ElementIds.NoteTextEditor)! as HTMLInputElement; const editor = document.getElementById(
this.removeTabObserver = this.application.getKeyboardService().addKeyObserver({ ElementIds.NoteTextEditor
)! as HTMLInputElement;
this.removeTabObserver = this.application
.getKeyboardService()
.addKeyObserver({
element: editor, element: editor,
key: KeyboardKey.Tab, key: KeyboardKey.Tab,
onKeyDown: (event) => { onKeyDown: (event) => {
@@ -1192,8 +1168,10 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
const end = editor.selectionEnd!; const end = editor.selectionEnd!;
const spaces = ' '; const spaces = ' ';
/** Insert 4 spaces */ /** Insert 4 spaces */
editor.value = editor.value.substring(0, start) editor.value =
+ spaces + editor.value.substring(end); editor.value.substring(0, start) +
spaces +
editor.value.substring(end);
/** Place cursor 4 spaces away from where the tab key was pressed */ /** Place cursor 4 spaces away from where the tab key was pressed */
editor.selectionStart = editor.selectionEnd = start + 4; editor.selectionStart = editor.selectionEnd = start + 4;
} }
@@ -1219,7 +1197,7 @@ export class EditorView extends WebDirective {
this.restrict = 'E'; this.restrict = 'E';
this.scope = { this.scope = {
editor: '=', editor: '=',
application: '=' application: '=',
}; };
this.template = template; this.template = template;
this.replace = true; this.replace = true;

View File

@@ -1,5 +1,7 @@
editor-view( .flex-grow(
ng-repeat='editor in self.editors' ng-repeat='editor in self.editors'
)
editor-view(
application='self.application' application='self.application'
editor='editor' editor='editor'
) )

View File

@@ -706,7 +706,12 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
async onIncludeProtectedNoteTextChange(event: Event) { async onIncludeProtectedNoteTextChange(event: Event) {
this.searchBarInput?.[0].focus(); this.searchBarInput?.[0].focus();
if (this.state.noteFilter.includeProtectedNoteText) { if (this.state.noteFilter.includeProtectedNoteText) {
this.state.noteFilter.includeProtectedNoteText = false; await this.setState({
noteFilter: {
...this.state.noteFilter,
includeProtectedNoteText: false,
},
});
this.reloadNotesDisplayOptions(); this.reloadNotesDisplayOptions();
await this.reloadNotes(); await this.reloadNotes();
} else { } else {
@@ -715,7 +720,12 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
}); });
event.preventDefault(); event.preventDefault();
if (await this.application.authorizeSearchingProtectedNotesText()) { if (await this.application.authorizeSearchingProtectedNotesText()) {
this.state.noteFilter.includeProtectedNoteText = true; await this.setState({
noteFilter: {
...this.state.noteFilter,
includeProtectedNoteText: true,
},
});
this.reloadNotesDisplayOptions(); this.reloadNotesDisplayOptions();
await this.reloadNotes(); await this.reloadNotes();
} }

View File

@@ -63,7 +63,7 @@ h3 {
input, button, select, textarea { input, button, select, textarea {
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
line-height: inherit; line-height: normal;
} }
a { a {
@@ -93,7 +93,6 @@ a {
} }
p { p {
overflow: auto;
color: var(--sn-stylekit-paragraph-text-color); color: var(--sn-stylekit-paragraph-text-color);
margin: 0; margin: 0;
} }

View File

@@ -1,16 +0,0 @@
/* Generic UI controls that have yet to be extracted into Stylekit */
.sn-btn {
@extend .border-0;
@extend .bg-main;
@extend .cursor-pointer;
@extend .capitalize;
@extend .font-bold;
@extend .py-2;
@extend .px-3;
@extend .rounded;
@extend .text-info-contrast;
@extend .text-sm;
@extend .hover\:brightness-130;
}

View File

@@ -81,14 +81,6 @@ $screen-md-max: ($screen-lg-min - 1) !default;
opacity: 0.5; opacity: 0.5;
} }
.flex {
display: flex;
}
.flex-column {
flex-direction: column;
}
.self-start { .self-start {
align-self: flex-start; align-self: flex-start;
} }
@@ -226,6 +218,12 @@ $screen-md-max: ($screen-lg-min - 1) !default;
.grid-template-cols-1fr { .grid-template-cols-1fr {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.col-span-all {
grid-column: 1 / -1;
}
.grid-col-2 {
grid-column: 2;
}
.relative { .relative {
position: relative; position: relative;

View File

@@ -11,4 +11,3 @@
@import "ionicons"; @import "ionicons";
@import "reach-sub"; @import "reach-sub";
@import "sessions-modal"; @import "sessions-modal";
@import "sn";

View File

@@ -12,12 +12,15 @@
) )
.sk-panel-row .sk-panel-row
.sk-h1 Sign in or register to enable sync and end-to-end encryption. .sk-h1 Sign in or register to enable sync and end-to-end encryption.
.sk-panel-row .flex.my-1
.sk-button-group.stretch button(
.sk-button.info.featured(ng-click='self.state.formData.showLogin = true') class="sn-button info flex-grow text-base py-3 mr-1.5"
.sk-label Sign In ng-click='self.state.formData.showLogin = true'
.sk-button.info.featured(ng-click='self.showRegister()') ) Sign In
.sk-label Register button(
class="sn-button info flex-grow text-base py-3 ml-1.5"
ng-click='self.showRegister()'
) Register
.sk-panel-row.sk-p .sk-panel-row.sk-p
| Standard Notes is free on every platform, and comes | Standard Notes is free on every platform, and comes
| standard with sync and encryption. | standard with sync and encryption.
@@ -95,12 +98,10 @@
target='_blank' target='_blank'
) (Learn more) ) (Learn more)
.sk-panel-section.form-submit(ng-if='!self.state.formData.authenticating') .sk-panel-section.form-submit(ng-if='!self.state.formData.authenticating')
.sk-button-group.stretch button.sn-button.info.text-base.py-3.text-center(
.sk-button.info.featured(
ng-click='self.submitAuthForm()', ng-click='self.submitAuthForm()',
ng-disabled='self.state.formData.authenticating' ng-disabled='self.state.formData.authenticating'
) ) {{self.state.formData.showLogin ? "Sign In" : "Register"}}
.sk-label {{self.state.formData.showLogin ? "Sign In" : "Register"}}
.sk-notification.neutral(ng-if='self.state.formData.showRegister') .sk-notification.neutral(ng-if='self.state.formData.showRegister')
.sk-notification-title No Password Reset. .sk-notification-title No Password Reset.
.sk-notification-text .sk-notification-text
@@ -174,17 +175,16 @@
| or revoking an active session, require additional authentication | or revoking an active session, require additional authentication
| like entering your account password or application passcode. | like entering your account password or application passcode.
.sk-panel-row(ng-if="self.state.protectionsDisabledUntil") .sk-panel-row(ng-if="self.state.protectionsDisabledUntil")
button.sk-button.info(ng-click="self.enableProtections()") button.sn-button.info(ng-click="self.enableProtections()")
span.sk-label.capitalize Enable protections | Enable protections
.sk-panel-section .sk-panel-section
.sk-panel-section-title Passcode Lock .sk-panel-section-title Passcode Lock
div(ng-if='!self.state.hasPasscode') div(ng-if='!self.state.hasPasscode')
div(ng-if='self.state.canAddPasscode') div(ng-if='self.state.canAddPasscode')
.sk-panel-row(ng-if='!self.state.formData.showPasscodeForm') .sk-panel-row(ng-if='!self.state.formData.showPasscodeForm')
.sk-button.info( button.sn-button.info(
ng-click='self.addPasscodeClicked(); $event.stopPropagation();' ng-click='self.addPasscodeClicked(); $event.stopPropagation();'
) ) Add Passcode
.sk-label Add Passcode
p.sk-p p.sk-p
| Add a passcode to lock the application and | Add a passcode to lock the application and
| encrypt on-device key storage. | encrypt on-device key storage.
@@ -211,10 +211,8 @@
placeholder='Confirm Passcode', placeholder='Confirm Passcode',
type='password' type='password'
) )
.sk-button-group.stretch.sk-panel-row.form-submit button.sn-button.info.mt-2(type='submit') Set Passcode
button.sk-button.info(type='submit') button.sn-button.outlined.ml-2(
.sk-label Set Passcode
a.neutral.sk-a.sk-panel-row(
ng-click='self.state.formData.showPasscodeForm = false' ng-click='self.state.formData.showPasscodeForm = false'
) Cancel ) Cancel
div(ng-if='self.state.hasPasscode && !self.state.formData.showPasscodeForm') div(ng-if='self.state.hasPasscode && !self.state.formData.showPasscodeForm')
@@ -245,7 +243,6 @@
.sk-panel-section-title Data Backups .sk-panel-section-title Data Backups
.sk-p .sk-p
| Download a backup of all your data. | Download a backup of all your data.
.sk-panel-row
form.sk-panel-form.sk-panel-row(ng-if='self.state.encryptionEnabled') form.sk-panel-form.sk-panel-row(ng-if='self.state.encryptionEnabled')
.sk-input-group .sk-input-group
label.sk-horizontal-group.tight label.sk-horizontal-group.tight
@@ -265,18 +262,18 @@
) )
p.sk-p Decrypted p.sk-p Decrypted
.sk-panel-row .sk-panel-row
.sk-button-group.sk-panel-row.justify-left .flex
.sk-button.info(ng-click='self.downloadDataArchive()') button.sn-button.info(ng-click='self.downloadDataArchive()')
.sk-label Download Backup | Download Backup
label.sk-button.info label.sn-button.info.ml-2
input( input(
file-change='->', file-change='->',
handler='self.importFileSelected(files)', handler='self.importFileSelected(files)',
style='display: none;', style='display: none;',
type='file' type='file'
) )
.sk-label Import Backup | Import Backup
span(ng-if='self.isDesktopApplication()') p.mt-5(ng-if='self.isDesktopApplication()')
| Backups are automatically created on desktop and can be managed | Backups are automatically created on desktop and can be managed
| via the "Backups" top-level menu. | via the "Backups" top-level menu.
.sk-panel-row .sk-panel-row
@@ -296,8 +293,8 @@
| local storage, and a new identifier will be created should you | local storage, and a new identifier will be created should you
| decide to enable error reporting again in the future. | decide to enable error reporting again in the future.
.sk-panel-row .sk-panel-row
button(ng-click="self.toggleErrorReportingEnabled()").sk-button.info button(ng-click="self.toggleErrorReportingEnabled()").sn-button.info
span.sk-label {{ self.state.errorReportingEnabled ? 'Disable' : 'Enable'}} Error Reporting | {{ self.state.errorReportingEnabled ? 'Disable' : 'Enable'}} Error Reporting
.sk-panel-row .sk-panel-row
a(ng-click="self.openErrorReportingDialog()").sk-a What data is being sent? a(ng-click="self.openErrorReportingDialog()").sk-a What data is being sent?
.sk-panel-footer .sk-panel-footer
@@ -313,7 +310,7 @@
ng-if='self.state.formData.showLogin || self.state.formData.showRegister' ng-if='self.state.formData.showLogin || self.state.formData.showRegister'
) )
| Cancel | Cancel
a.sk-a.right.danger( a.sk-a.right.danger.capitalize(
ng-click='self.destroyLocalData()', ng-click='self.destroyLocalData()',
ng-if=` ng-if=`
!self.state.formData.showLogin && !self.state.formData.showLogin &&

View File

@@ -5,8 +5,7 @@
.sk-label.warning There was an issue loading {{ctrl.component.name}}. .sk-label.warning There was an issue loading {{ctrl.component.name}}.
.right .right
.sk-app-bar-item(ng-click='ctrl.reloadIframe()') .sk-app-bar-item(ng-click='ctrl.reloadIframe()')
.sk-button.info button.sn-button.info Reload
.sk-label Reload
.sn-component(ng-if='ctrl.expired') .sn-component(ng-if='ctrl.expired')
.sk-app-bar.no-edges.no-top-edge.dynamic-height .sk-app-bar.no-edges.no-top-edge.dynamic-height
.left .left
@@ -26,12 +25,10 @@
| Extensions are in a read-only state. | Extensions are in a read-only state.
.right .right
.sk-app-bar-item(ng-click='ctrl.reloadStatus(true)') .sk-app-bar-item(ng-click='ctrl.reloadStatus(true)')
.sk-button.info button.sn-button.info Reload
.sk-label Reload
.sk-app-bar-item .sk-app-bar-item
.sk-app-bar-item-column .sk-app-bar-item-column
.sk-button.warning a.sn-button.warning(
a.sk-label(
href='https://standardnotes.org/help/41/expired', href='https://standardnotes.org/help/41/expired',
rel='noopener', rel='noopener',
target='_blank' target='_blank'
@@ -57,11 +54,10 @@
li.sk-p li.sk-p
strong Use the Desktop application. strong Use the Desktop application.
.sk-panel-row .sk-panel-row
.sk-button.info( button.sn-button.info(
ng-click='ctrl.reloadStatus()', ng-click='ctrl.reloadStatus()',
ng-if='!ctrl.reloading' ng-if='!ctrl.reloading'
) ) Reload
.sk-label Reload
.sk-spinner.info.small(ng-if='ctrl.reloading') .sk-spinner.info.small(ng-if='ctrl.reloading')
.sn-component(ng-if="ctrl.error == 'url-missing'") .sn-component(ng-if="ctrl.error == 'url-missing'")
.sk-panel.static .sk-panel.static

View File

@@ -30,10 +30,9 @@
.sk-menu-panel-column(ng-if="ctrl.circle && ctrl.circleAlign == 'right'") .sk-menu-panel-column(ng-if="ctrl.circle && ctrl.circleAlign == 'right'")
.sk-circle.small(ng-class='ctrl.circle') .sk-circle.small(ng-class='ctrl.circle')
.sk-menu-panel-column(ng-if='ctrl.hasButton') .sk-menu-panel-column(ng-if='ctrl.hasButton')
.sk-button( button.sn-button.small(
ng-class='ctrl.buttonClass', ng-class='ctrl.buttonClass',
ng-click='ctrl.clickAccessoryButton($event)' ng-click='ctrl.clickAccessoryButton($event)'
) ) {{ctrl.buttonText}}
.sk-label {{ctrl.buttonText}}
.sk-menu-panel-column(ng-if='ctrl.spinnerClass') .sk-menu-panel-column(ng-if='ctrl.spinnerClass')
.sk-spinner.small(ng-class='ctrl.spinnerClass') .sk-spinner.small(ng-class='ctrl.spinnerClass')

View File

@@ -41,8 +41,7 @@
| Please ensure you are running the latest version of Standard Notes | Please ensure you are running the latest version of Standard Notes
| on all platforms to ensure maximum compatibility. | on all platforms to ensure maximum compatibility.
.sk-panel-footer .sk-panel-footer
.sk-button.info( button.sn-button.info(
ng-click='ctrl.nextStep()', ng-click='ctrl.nextStep()',
ng-disabled='ctrl.state.lockContinue' ng-disabled='ctrl.state.lockContinue'
) ) {{ctrl.state.continueTitle}}
.sk-label {{ctrl.state.continueTitle}}

View File

@@ -1,25 +0,0 @@
.sk-modal-background(ng-click='ctrl.deny()')
#permissions-modal.sk-modal-content
.sn-component
.sk-panel
.sk-panel-header
.sk-panel-header-title Activate Extension
a.sk-a.info.close-button(ng-click='ctrl.deny()') Cancel
.sk-panel-content
.sk-panel-section
.sk-panel-row
.sk-h2
strong {{ctrl.component.name}}
| would like to interact with your
| {{ctrl.permissionsString}}
.sk-panel-row
p.sk-p
| Extensions use an offline messaging system to communicate. Learn more at
a.sk-a.info(
href='https://standardnotes.org/permissions',
rel='noopener',
target='_blank'
) https://standardnotes.org/permissions.
.sk-panel-footer
.sk-button.info.big.block.font-bold(ng-click='ctrl.accept()')
.sk-label Continue

View File

@@ -33,17 +33,14 @@
| Please download a backup before we attempt to | Please download a backup before we attempt to
| perform a full account sync resolution. | perform a full account sync resolution.
.sk-panel-row .sk-panel-row
.sk-button-group .flex.gap-2
.sk-button.info(ng-click='ctrl.downloadBackup(true)') button.sn-button.info(ng-click='ctrl.downloadBackup(true)') Encrypted
.sk-label Encrypted button.sn-button.info(ng-click='ctrl.downloadBackup(false)') Decrypted
.sk-button.info(ng-click='ctrl.downloadBackup(false)') button.sn-button.danger(ng-click='ctrl.skipBackup()') Skip
.sk-label Decrypted
.sk-button.danger(ng-click='ctrl.skipBackup()')
.sk-label Skip
div(ng-if='ctrl.status.backupFinished') div(ng-if='ctrl.status.backupFinished')
.sk-panel-row(ng-if='!ctrl.status.resolving && !ctrl.status.attemptedResolution') .sk-panel-row(ng-if='!ctrl.status.resolving && !ctrl.status.attemptedResolution')
.sk-button.info(ng-click='ctrl.performSyncResolution()') button.sn-button.info(ng-click='ctrl.performSyncResolution()')
.sk-label Perform Sync Resolution | Perform Sync Resolution
.sk-panel-row.justify-left(ng-if='ctrl.status.resolving') .sk-panel-row.justify-left(ng-if='ctrl.status.resolving')
.sk-horizontal-group .sk-horizontal-group
.sk-spinner.small.info .sk-spinner.small.info

View File

@@ -1,6 +1,6 @@
{ {
"name": "standard-notes-web", "name": "standard-notes-web",
"version": "3.6.2", "version": "3.6.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -53,7 +53,7 @@
"pug-loader": "^2.4.0", "pug-loader": "^2.4.0",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"serve-static": "^1.14.1", "serve-static": "^1.14.1",
"sn-stylekit": "^2.2.1", "sn-stylekit": "github:standardnotes/StyleKit#1ec13454cc6d8cf97651263a039de8872be527b8",
"ts-loader": "^8.0.17", "ts-loader": "^8.0.17",
"typescript": "^4.1.5", "typescript": "^4.1.5",
"typescript-eslint": "0.0.1-alpha.0", "typescript-eslint": "0.0.1-alpha.0",
@@ -68,7 +68,7 @@
"@reach/alert-dialog": "^0.13.0", "@reach/alert-dialog": "^0.13.0",
"@reach/dialog": "^0.13.0", "@reach/dialog": "^0.13.0",
"@standardnotes/sncrypto-web": "^1.2.10", "@standardnotes/sncrypto-web": "^1.2.10",
"@standardnotes/snjs": "^2.0.67", "@standardnotes/snjs": "^2.0.70",
"mobx": "^6.1.6", "mobx": "^6.1.6",
"preact": "^10.5.12" "preact": "^10.5.12"
} }

View File

@@ -1850,10 +1850,10 @@
"@standardnotes/sncrypto-common" "^1.2.7" "@standardnotes/sncrypto-common" "^1.2.7"
libsodium-wrappers "^0.7.8" libsodium-wrappers "^0.7.8"
"@standardnotes/snjs@^2.0.67": "@standardnotes/snjs@^2.0.70":
version "2.0.67" version "2.0.70"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.67.tgz#87e29f40bb5efaa36f30ddc5905164f7dce194d9" resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.70.tgz#259a4fadc4f9b360f35a399b674b921179bd5768"
integrity sha512-XCDxlFQCh0zmV3Hc9mjU7ritZ/2Ma5JPoCbDy4CIAlkKdmVL4tu/4jCfRFILM0zpKF/kLsCTbLGdG7TgU/ReKg== integrity sha512-D11E+sCeoram2+NhQuFmn333JoHr1kGjVZrkRmZlfhGi+dYXJqZuDDDHbRn5WEJQneDg43Z8DjjAlxL+Mqhp6w==
dependencies: dependencies:
"@standardnotes/auth" "^2.0.0" "@standardnotes/auth" "^2.0.0"
"@standardnotes/sncrypto-common" "^1.2.9" "@standardnotes/sncrypto-common" "^1.2.9"
@@ -7808,10 +7808,9 @@ slice-ansi@^4.0.0:
astral-regex "^2.0.0" astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0" is-fullwidth-code-point "^3.0.0"
sn-stylekit@^2.2.1: "sn-stylekit@github:standardnotes/StyleKit#1ec13454cc6d8cf97651263a039de8872be527b8":
version "2.2.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-2.2.1.tgz#4a81a05b2b2d67a11af9d06f3964ac1ece3aa84a" resolved "https://codeload.github.com/standardnotes/StyleKit/tar.gz/1ec13454cc6d8cf97651263a039de8872be527b8"
integrity sha512-mrvUbf2HbWOfxbNglo7RXa5JBe9UV9rurupeGoX/Kh4/lVlB2n/56ZT103xk/4tp0/mVCpxjD7Dt1stKFxsvFA==
snapdragon-node@^2.0.1: snapdragon-node@^2.0.1:
version "2.1.1" version "2.1.1"