Merge branch 'develop' into feature/multiple-selection

This commit is contained in:
Antonella Sgarlatta 2021-04-28 14:53:15 -03:00
commit a1d56abd2e
No known key found for this signature in database
GPG key ID: 356A437CE85F9337
24 changed files with 392 additions and 85 deletions

12
.github/codeql/codeql-config.yml vendored Normal file
View file

@ -0,0 +1,12 @@
name: "Custom CodeQL Config"
queries:
- uses: security-and-quality
- uses: ./.github/codeql/custom-queries/javascript
paths:
- app/assets/javascripts
paths-ignore:
- bin
- node_modules

View file

@ -0,0 +1,4 @@
name: custom-javascript-queries
version: 0.0.0
libraryPathDependencies:
- codeql-javascript

68
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,68 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ develop, main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ develop ]
schedule:
- cron: '21 7 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

2
.gitignore vendored
View file

@ -46,3 +46,5 @@ dump.rdb
# Yarn
yarn-error.log
package-lock.json
codeqldb

View file

@ -37,3 +37,5 @@ package-lock.json
package.json
Rakefile
testing-server.js
.github
codeqldb

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
.github
codeqldb

View file

@ -60,6 +60,7 @@ import { NoAccountWarningDirective } from './components/NoAccountWarning';
import { NoProtectionsdNoteWarningDirective } from './components/NoProtectionsNoteWarning';
import { SearchOptionsDirective } from './components/SearchOptions';
import { MultipleSelectedNotesDirective } from './components/MultipleSelectedNotes';
import { ConfirmSignoutDirective } from './components/ConfirmSignoutModal';
function reloadHiddenFirefoxTab(): boolean {
/**
@ -149,7 +150,8 @@ const startApplication: StartApplication = async function startApplication(
.directive('noAccountWarning', NoAccountWarningDirective)
.directive('protectedNotePanel', NoProtectionsdNoteWarningDirective)
.directive('searchOptions', SearchOptionsDirective)
.directive('multipleSelectedNotesPanel', MultipleSelectedNotesDirective);
.directive('multipleSelectedNotesPanel', MultipleSelectedNotesDirective)
.directive('confirmSignout', ConfirmSignoutDirective);
// Filters
angular.module('app').filter('trusted', ['$sce', trusted]);

View file

@ -0,0 +1,119 @@
import { useEffect, useRef, useState } from 'preact/hooks';
import {
AlertDialog,
AlertDialogDescription,
AlertDialogLabel,
} from '@reach/alert-dialog';
import { STRING_SIGN_OUT_CONFIRMATION } from '@/strings';
import { WebApplication } from '@/ui_models/application';
import { toDirective } from './utils';
import { AppState } from '@/ui_models/app_state';
import { observer } from 'mobx-react-lite';
type Props = {
application: WebApplication;
appState: AppState;
};
const ConfirmSignoutContainer = observer((props: Props) => {
if (!props.appState.accountMenu.signingOut) {
return null;
}
return <ConfirmSignoutModal {...props} />;
});
const ConfirmSignoutModal = observer(({ application, appState }: Props) => {
const [deleteLocalBackups, setDeleteLocalBackups] = useState(
application.hasAccount()
);
const cancelRef = useRef<HTMLButtonElement>();
function close() {
appState.accountMenu.setSigningOut(false);
}
const [localBackupsCount, setLocalBackupsCount] = useState(0);
useEffect(() => {
application.bridge.localBackupsCount().then(setLocalBackupsCount);
}, [appState.accountMenu.signingOut, application.bridge]);
return (
<AlertDialog onDismiss={close} leastDestructiveRef={cancelRef}>
<div className="sk-modal-content">
<div className="sn-component">
<div className="sk-panel">
<div className="sk-panel-content">
<div className="sk-panel-section">
<AlertDialogLabel className="sk-h3 sk-panel-section-title capitalize">
End your session?
</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<p className="color-foreground">
{STRING_SIGN_OUT_CONFIRMATION}
</p>
</AlertDialogDescription>
{localBackupsCount > 0 && (
<div className="flex">
<div className="sk-panel-row"></div>
<label className="flex items-center">
<input
type="checkbox"
checked={deleteLocalBackups}
onChange={(event) => {
setDeleteLocalBackups(
(event.target as HTMLInputElement).checked
);
}}
/>
<span className="ml-2">
Delete {localBackupsCount} local backup file
{localBackupsCount > 1 ? 's' : ''}
</span>
</label>
<button
className="capitalize sk-a ml-1.5 p-0 rounded cursor-pointer"
onClick={() => {
application.bridge.viewlocalBackups();
}}
>
View backup files
</button>
</div>
)}
<div className="flex my-1 mt-4">
<button
className="sn-button neutral"
ref={cancelRef}
onClick={close}
>
Cancel
</button>
<button
className="sn-button danger ml-2"
onClick={() => {
if (deleteLocalBackups) {
application.signOutAndDeleteLocalBackups();
} else {
application.signOut();
}
close();
}}
>
{application.hasAccount()
? 'Sign Out'
: 'Clear Session Data'}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</AlertDialog>
);
});
export const ConfirmSignoutDirective = toDirective<Props>(
ConfirmSignoutContainer
);

View file

@ -84,6 +84,8 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
private closeFunction?: () => void;
private removeProtectionLengthObserver?: () => void;
public passcodeInput!: JQLite;
/* @ngInject */
constructor($timeout: ng.ITimeoutService, appVersion: string) {
super($timeout);
@ -144,7 +146,7 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
async $onInit() {
super.$onInit();
this.setState({
showSessions: await this.application.userCanManageSessions()
showSessions: await this.application.userCanManageSessions(),
});
const sync = this.appState.sync;
@ -379,15 +381,8 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
this.appState.openSessionsModal();
}
async destroyLocalData() {
if (
await confirmDialog({
text: STRING_SIGN_OUT_CONFIRMATION,
confirmButtonStyle: 'danger',
})
) {
this.application.signOut();
}
signOut() {
this.appState.accountMenu.setSigningOut(true);
}
showRegister() {
@ -517,17 +512,21 @@ class AccountMenuCtrl extends PureViewCtrl<unknown, AccountMenuState> {
async submitPasscodeForm() {
const passcode = this.getState().formData.passcode!;
if (passcode !== this.getState().formData.confirmPasscode!) {
this.application!.alertService!.alert(STRING_NON_MATCHING_PASSCODES);
await alertDialog({
text: STRING_NON_MATCHING_PASSCODES,
});
this.passcodeInput[0].focus();
return;
}
await preventRefreshing(
STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_CHANGE,
async () => {
if (this.application!.hasPasscode()) {
await this.application!.changePasscode(passcode);
} else {
await this.application!.addPasscode(passcode);
const successful = this.application.hasPasscode()
? await this.application.changePasscode(passcode)
: await this.application.addPasscode(passcode);
if (!successful) {
this.passcodeInput[0].focus();
}
}
);

View file

@ -313,9 +313,7 @@ class PanelResizerCtrl implements PanelResizerScope {
}
if (Math.round(width + this.lastLeft) === Math.round(parentRect.width)) {
this.panel.style.width = `calc(100% - ${this.lastLeft}px)`;
this.panel.style.flexBasis = `calc(100% - ${this.lastLeft}px)`;
} else {
this.panel.style.flexBasis = width + 'px';
this.panel.style.width = width + 'px';
}
this.lastWidth = width;
@ -344,8 +342,8 @@ class PanelResizerCtrl implements PanelResizerScope {
/**
* If an iframe is displayed adjacent to our panel, and the mouse exits over the iframe,
* document[onmouseup] is not triggered because the document is no longer the same over
* the iframe. We add an invisible overlay while resizing so that the mouse context
* document[onmouseup] is not triggered because the document is no longer the same over
* the iframe. We add an invisible overlay while resizing so that the mouse context
* remains in our main document.
*/
addInvisibleOverlay() {

View file

@ -10,9 +10,13 @@ export interface Bridge {
environment: Environment;
getKeychainValue(): Promise<unknown>;
setKeychainValue(value: any): Promise<void>;
setKeychainValue(value: unknown): Promise<void>;
clearKeychainValue(): Promise<void>;
localBackupsCount(): Promise<number>;
viewlocalBackups(): void;
deleteLocalBackups(): Promise<void>;
extensionsServerHost?: string;
syncComponents(payloads: unknown[]): void;
onMajorDataChange(): void;

View file

@ -1,4 +1,4 @@
import { Bridge } from "./bridge";
import { Bridge } from './bridge';
import { Environment } from '@standardnotes/snjs';
const KEYCHAIN_STORAGE_KEY = 'keychain';
@ -14,7 +14,7 @@ export class BrowserBridge implements Bridge {
}
}
async setKeychainValue(value: any): Promise<void> {
async setKeychainValue(value: unknown): Promise<void> {
localStorage.setItem(KEYCHAIN_STORAGE_KEY, JSON.stringify(value));
}
@ -22,9 +22,16 @@ export class BrowserBridge implements Bridge {
localStorage.removeItem(KEYCHAIN_STORAGE_KEY);
}
async localBackupsCount(): Promise<number> {
/** Browsers cannot save backups, only let you download one */
return 0;
}
/** No-ops */
/* eslint-disable @typescript-eslint/no-empty-function */
async deleteLocalBackups(): Promise<void> {}
viewlocalBackups(): void {}
syncComponents(): void {}
onMajorDataChange(): void {}
onInitialDataLoad(): void {}

View file

@ -40,6 +40,8 @@ export const STRING_UNARCHIVE_LOCKED_ATTEMPT =
"This note is locked. If you'd like to archive it, unlock it, and try again.";
export const STRING_DELETE_LOCKED_ATTEMPT =
"This note is locked. If you'd like to delete it, unlock it, and try again.";
export const STRING_EDIT_LOCKED_ATTEMPT =
"This note is locked. If you'd like to edit its options, unlock it, and try again.";
export function StringDeleteNote(title: string, permanently: boolean) {
return permanently
? `Are you sure you want to permanently delete ${title}?`
@ -52,8 +54,7 @@ export function StringEmptyTrash(count: number) {
/** @account */
export const STRING_ACCOUNT_MENU_UNCHECK_MERGE =
'Unchecking this option means any of the notes you have written while you were signed out will be deleted. Are you sure you want to discard these notes?';
export const STRING_SIGN_OUT_CONFIRMATION =
'Are you sure you want to end your session? This will delete all local items and extensions.';
export const STRING_SIGN_OUT_CONFIRMATION = 'This will delete all local items and extensions.';
export const STRING_ERROR_DECRYPTING_IMPORT =
'There was an error decrypting your items. Make sure the password you entered is correct and try again.';
export const STRING_E2E_ENABLED =

View file

@ -2,12 +2,16 @@ import { action, makeObservable, observable } from "mobx";
export class AccountMenuState {
show = false;
signingOut = false;
constructor() {
makeObservable(this, {
show: observable,
signingOut: observable,
setShow: action,
toggleShow: action,
setSigningOut: action,
});
}
@ -15,6 +19,10 @@ export class AccountMenuState {
this.show = show;
}
setSigningOut = (signingOut: boolean): void => {
this.signingOut = signingOut;
}
toggleShow = (): void => {
this.show = !this.show;
}

View file

@ -4,7 +4,7 @@ import { WebApplication } from "../application";
export class SearchOptionsState {
includeProtectedContents = false;
includeArchived = false;
includeArchived = true;
includeTrashed = false;
constructor(

View file

@ -52,7 +52,7 @@ export class WebApplication extends SNApplication {
private $compile: angular.ICompileService,
scope: angular.IScope,
defaultSyncServerHost: string,
private bridge: Bridge,
public bridge: Bridge,
) {
super(
bridge.environment,
@ -168,6 +168,11 @@ export class WebApplication extends SNApplication {
return angular.element(document.getElementById(this.identifier)!);
}
async signOutAndDeleteLocalBackups(): Promise<void> {
await this.bridge.deleteLocalBackups();
return this.signOut();
}
presentPasswordModal(callback: () => void) {
const scope = this.scope!.$new(true) as InputModalScope;
scope.type = "password";

View file

@ -34,6 +34,7 @@ import {
STRING_ELLIPSES,
STRING_DELETE_PLACEHOLDER_ATTEMPT,
STRING_DELETE_LOCKED_ATTEMPT,
STRING_EDIT_LOCKED_ATTEMPT,
StringDeleteNote,
StringEmptyTrash,
} from '@/strings';
@ -88,11 +89,15 @@ type EditorState = {
};
type EditorValues = {
title?: string;
text?: string;
title: string;
text: string;
tagsInputValue?: string;
};
function copyEditorValues(values: EditorValues) {
return Object.assign({}, values);
}
function sortAlphabetically(array: SNComponent[]): SNComponent[] {
return array.sort((a, b) =>
a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1
@ -110,7 +115,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
private saveTimeout?: ng.IPromise<void>;
private statusTimeout?: ng.IPromise<void>;
private lastEditorFocusEventSource?: EventSource;
public editorValues: EditorValues = {};
public editorValues: EditorValues = { title: '', text: '' };
onEditorLoad?: () => void;
private tags: SNTag[] = [];
@ -198,9 +203,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (!this.editorValues.text) {
this.editorValues.text = note.text;
}
if (note.lastSyncBegan) {
if (note.lastSyncBegan || note.dirty) {
if (note.lastSyncEnd) {
if (note.lastSyncBegan!.getTime() > note.lastSyncEnd!.getTime()) {
if (
note.dirty ||
note.lastSyncBegan!.getTime() > note.lastSyncEnd!.getTime()
) {
this.showSavingStatus();
} else if (
note.lastSyncEnd!.getTime() > note.lastSyncBegan!.getTime()
@ -301,6 +309,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
this.reloadPreferences();
this.reloadStackComponents();
this.reloadNoteTagsComponent();
if (note.dirty) {
this.showSavingStatus();
}
if (note.safeText().length === 0 && !showProtectedWarning) {
this.focusTitle();
}
@ -408,6 +419,10 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (this.appState.getActiveEditor()?.isTemplateNote) {
await this.appState.getActiveEditor().insertTemplatedNote();
}
if (this.note.locked) {
this.application.alertService.alert(STRING_EDIT_LOCKED_ATTEMPT);
return;
}
if (!component) {
if (!this.note.prefersPlainEditor) {
await this.application.changeItem(this.note.uuid, (mutator) => {
@ -464,26 +479,30 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
* close the editor (if we closed the editor before sync began, we'd get an exception,
* since the debouncer will be triggered on a non-existent editor)
*/
async saveNote(
async save(
note: SNNote,
editorValues: EditorValues,
bypassDebouncer = false,
isUserModified = false,
dontUpdatePreviews = false,
customMutate?: (mutator: NoteMutator) => void,
closeAfterSync = false
) {
const title = editorValues.title;
const text = editorValues.text;
const isTemplate = this.editor.isTemplateNote;
const selectedTag = this.appState.selectedTag;
if (document.hidden) {
this.application.alertService!.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
this.application.alertService.alert(STRING_SAVING_WHILE_DOCUMENT_HIDDEN);
return;
}
const note = this.note;
if (note.deleted) {
this.application.alertService!.alert(STRING_DELETED_NOTE);
this.application.alertService.alert(STRING_DELETED_NOTE);
return;
}
if (this.editor.isTemplateNote) {
if (isTemplate) {
await this.editor.insertTemplatedNote();
}
const selectedTag = this.appState.selectedTag;
if (
!selectedTag?.isSmartTag &&
!selectedTag?.hasRelationshipWithItem(note)
@ -493,7 +512,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
});
}
if (!this.application.findItem(note.uuid)) {
this.application.alertService!.alert(STRING_INVALID_NOTE);
this.application.alertService.alert(STRING_INVALID_NOTE);
return;
}
await this.application.changeItem(
@ -503,12 +522,12 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (customMutate) {
customMutate(noteMutator);
}
noteMutator.title = this.editorValues.title!;
noteMutator.text = this.editorValues.text!;
noteMutator.title = title;
noteMutator.text = text;
if (!dontUpdatePreviews) {
const text = this.editorValues.text || '';
const truncate = text.length > NOTE_PREVIEW_CHAR_LIMIT;
const substring = text.substring(0, NOTE_PREVIEW_CHAR_LIMIT);
const noteText = text || '';
const truncate = noteText.length > NOTE_PREVIEW_CHAR_LIMIT;
const substring = noteText.substring(0, NOTE_PREVIEW_CHAR_LIMIT);
const previewPlain = substring + (truncate ? STRING_ELLIPSES : '');
noteMutator.preview_plain = previewPlain;
noteMutator.preview_html = undefined;
@ -541,7 +560,8 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
syncTakingTooLong: false,
});
this.setStatus({
message: 'All changes saved' + (this.application.noAccount() ? ' offline' : ''),
message:
'All changes saved' + (this.application.noAccount() ? ' offline' : ''),
});
}
@ -583,7 +603,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
contentChanged() {
this.saveNote(false, true);
this.save(this.note, copyEditorValues(this.editorValues), false, true);
}
onTitleEnter($event: Event) {
@ -593,7 +613,13 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
onTitleChange() {
this.saveNote(false, true, true);
this.save(
this.note,
copyEditorValues(this.editorValues),
false,
true,
true
);
}
focusEditor() {
@ -653,9 +679,16 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
if (permanently) {
this.performNoteDeletion(this.note);
} else {
this.saveNote(true, false, true, (mutator) => {
mutator.trashed = true;
});
this.save(
this.note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
mutator.trashed = true;
}
);
}
}
}
@ -665,7 +698,9 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
restoreTrashedNote() {
this.saveNote(
this.save(
this.note,
copyEditorValues(this.editorValues),
true,
false,
true,
@ -698,15 +733,31 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
togglePin() {
this.saveNote(true, false, true, (mutator) => {
mutator.pinned = !this.note.pinned;
});
const note = this.note;
this.save(
note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
mutator.pinned = !note.pinned;
}
);
}
toggleLockNote() {
this.saveNote(true, false, true, (mutator) => {
mutator.locked = !this.note.locked;
});
const note = this.note;
this.save(
note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
mutator.locked = !note.locked;
}
);
}
async toggleProtectNote() {
@ -723,29 +774,40 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
toggleNotePreview() {
this.saveNote(true, false, true, (mutator) => {
mutator.hidePreview = !this.note.hidePreview;
});
const note = this.note;
this.save(
note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
mutator.hidePreview = !note.hidePreview;
}
);
}
toggleArchiveNote() {
if (this.note.locked) {
const note = this.note;
if (note.locked) {
alertDialog({
text: this.note.archived
text: note.archived
? STRING_UNARCHIVE_LOCKED_ATTEMPT
: STRING_ARCHIVE_LOCKED_ATTEMPT,
});
return;
}
this.saveNote(
this.save(
note,
copyEditorValues(this.editorValues),
true,
false,
true,
(mutator) => {
mutator.archived = !this.note.archived;
mutator.archived = !note.archived;
},
/** If we are unarchiving, and we are in the archived tag, close the editor */
this.note.archived && this.appState.selectedTag?.isArchiveTag
note.archived && this.appState.selectedTag?.isArchiveTag
);
}
@ -1176,7 +1238,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
editor.selectionStart = editor.selectionEnd = start + 4;
}
this.editorValues.text = editor.value;
this.saveNote(true);
this.save(this.note, copyEditorValues(this.editorValues), true);
},
});

View file

@ -7,7 +7,8 @@
.sk-button.contrast.wide(
ng-click='self.createNewNote()',
title='Create a new note in the selected tag'
)
aria-label="Create new note"
)
.sk-label
i.icon.ion-plus.add-button
.filter-section(role='search')

View file

@ -27,6 +27,7 @@ body {
min-height: 100%;
height: 100%;
font-size: var(--sn-stylekit-base-font-size);
line-height: normal;
margin: 0;
color: var(--sn-stylekit-foreground-color);
background-color: var(--sn-stylekit-background-color);

View file

@ -83,7 +83,7 @@
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 32px;
right: 36px;
cursor: pointer;
transition: background-color 0.15s linear;

View file

@ -49,6 +49,10 @@
outline: none;
}
.color-foreground {
color: var(--sn-stylekit-foreground-color);
}
.ring-info {
box-shadow: 0 0 0 2px var(--sn-stylekit-info-color);
}

View file

@ -30,7 +30,7 @@
)
.sk-panel-section-title
| {{self.state.formData.showLogin ? "Sign In" : "Register"}}
form.sk-panel-form(ng-submit='self.submitAuthForm()')
form.sk-panel-form(ng-submit='self.submitAuthForm()' novalidate)
.sk-panel-section
input.sk-input.contrast(
name='email',
@ -200,12 +200,13 @@
)
.sk-panel-row
input.sk-input.contrast(
ng-model='self.state.formData.passcode',
placeholder='Passcode',
should-focus='true',
sn-autofocus='true',
ng-ref='self.passcodeInput'
ng-model='self.state.formData.passcode'
placeholder='Passcode'
should-focus='true'
sn-autofocus='true'
type='password'
)
)
input.sk-input.contrast(
ng-model='self.state.formData.confirmPasscode',
placeholder='Confirm Passcode',
@ -297,6 +298,10 @@
| {{ self.state.errorReportingEnabled ? 'Disable' : 'Enable'}} Error Reporting
.sk-panel-row
a(ng-click="self.openErrorReportingDialog()").sk-a What data is being sent?
confirm-signout(
app-state='self.appState'
application='self.application'
)
.sk-panel-footer
.sk-panel-row
.sk-p.left.neutral
@ -311,7 +316,7 @@
)
| Cancel
a.sk-a.right.danger.capitalize(
ng-click='self.destroyLocalData()',
ng-click='self.signOut()',
ng-if=`
!self.state.formData.showLogin &&
!self.state.formData.showRegister`

View file

@ -1,6 +1,6 @@
{
"name": "standard-notes-web",
"version": "3.6.6",
"version": "3.6.8",
"license": "AGPL-3.0-or-later",
"repository": {
"type": "git",
@ -55,7 +55,7 @@
"pug-loader": "^2.4.0",
"sass-loader": "^8.0.2",
"serve-static": "^1.14.1",
"sn-stylekit": "github:standardnotes/StyleKit#c64573b229ac9154e480cde3b5fdab78c75b3530",
"sn-stylekit": "^4.0.3",
"ts-loader": "^8.0.17",
"typescript": "^4.1.5",
"typescript-eslint": "0.0.1-alpha.0",
@ -71,7 +71,7 @@
"@reach/checkbox": "^0.13.2",
"@reach/dialog": "^0.13.0",
"@standardnotes/sncrypto-web": "^1.2.10",
"@standardnotes/snjs": "^2.0.74",
"@standardnotes/snjs": "^2.0.75",
"mobx": "^6.1.6",
"mobx-react-lite": "^3.2.0",
"preact": "^10.5.12"

View file

@ -1936,10 +1936,10 @@
"@standardnotes/sncrypto-common" "^1.2.7"
libsodium-wrappers "^0.7.8"
"@standardnotes/snjs@^2.0.74":
version "2.0.74"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.74.tgz#042c3dcf5447006cdfc70b8cfcacf7ded92cea91"
integrity sha512-2G0jw1n4GgOnSkpXDXvrJp9R8xsImVrfNRjKNBE7RqzBg2WFynF5xt0bfqzLdRFZyA5oeuEkTG1CAU4nNPy0xw==
"@standardnotes/snjs@^2.0.75":
version "2.0.75"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.75.tgz#aeb0ead927da63dc85e28f78da2362126bb16602"
integrity sha512-QL5YgDT0aN9t95gxgURqNudXr5dteVsc1ylsKKSw0DpEGiq0bACPxbI+sUFppoWTFmprxmDh3+vc+FFcFg7Lyw==
dependencies:
"@standardnotes/auth" "^2.0.0"
"@standardnotes/sncrypto-common" "^1.2.9"
@ -7815,9 +7815,10 @@ slice-ansi@^4.0.0:
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
"sn-stylekit@github:standardnotes/StyleKit#c64573b229ac9154e480cde3b5fdab78c75b3530":
version "4.0.2"
resolved "https://codeload.github.com/standardnotes/StyleKit/tar.gz/c64573b229ac9154e480cde3b5fdab78c75b3530"
sn-stylekit@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-4.0.3.tgz#f8b86a68286bf5237dfc035c43a31464625b010c"
integrity sha512-cKsq3XndExpzJnP6qjd5khGbNhKlA724MLbxbMbgUv3aYQWZddHudzV84Lb5gx87mbUQJQc0lh0nPWZBpa2hUA==
snapdragon-node@^2.0.1:
version "2.1.1"