feat: warning for protected note without protection

- Use `.sn-button` everywhere
- Delete permissions modal
- Capitalize "Clear session data"
This commit is contained in:
Baptiste Grob
2021-03-22 16:51:49 +01:00
parent cd7b5cc455
commit cc474da0c3
25 changed files with 418 additions and 476 deletions

View File

@@ -43,7 +43,6 @@ import {
MenuRow,
PanelResizer,
PasswordWizard,
PermissionsModal,
RevisionPreviewModal,
HistoryMenu,
SyncResolutionMenu,
@@ -57,6 +56,7 @@ import { StartApplication } from './startApplication';
import { Bridge } from './services/bridge';
import { SessionsModalDirective } from './components/SessionsModal';
import { NoAccountWarningDirective } from './components/NoAccountWarning';
import { NoProtectionsdNoteWarningDirective } from './components/NoProtectionsNoteWarning';
function reloadHiddenFirefoxTab(): boolean {
@@ -138,12 +138,12 @@ const startApplication: StartApplication = async function startApplication(
.directive('menuRow', () => new MenuRow())
.directive('panelResizer', () => new PanelResizer())
.directive('passwordWizard', () => new PasswordWizard())
.directive('permissionsModal', () => new PermissionsModal())
.directive('revisionPreviewModal', () => new RevisionPreviewModal())
.directive('historyMenu', () => new HistoryMenu())
.directive('syncResolutionMenu', () => new SyncResolutionMenu())
.directive('sessionsModal', SessionsModalDirective)
.directive('noAccountWarning', NoAccountWarningDirective);
.directive('noAccountWarning', NoAccountWarningDirective)
.directive('protectedNotePanel', NoProtectionsdNoteWarningDirective);
// Filters
angular.module('app').filter('trusted', ['$sce', trusted]);

View File

@@ -2,7 +2,9 @@ import { toDirective, useAutorunValue } from './utils';
import Close from '../../icons/ic_close.svg';
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);
if (!canShow) {
return null;
@@ -14,7 +16,7 @@ function NoAccountWarning({ appState }: { appState: AppState }) {
Sign in or register to back up your notes.
</p>
<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) => {
event.stopPropagation();
appState.accountMenu.setShow(true);
@@ -28,12 +30,13 @@ function NoAccountWarning({ appState }: { appState: AppState }) {
}}
title="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"
>
<Close className="fill-current" />
<Close className="fill-current block" />
</button>
</div>
);
}
export const NoAccountWarningDirective = toDirective(NoAccountWarning);
export const NoAccountWarningDirective = toDirective<Props>(NoAccountWarning);

View File

@@ -0,0 +1,37 @@
import { AppState } from '@/ui_models/app_state';
import { toDirective } from './utils';
type Props = { appState: AppState; onViewNote: () => void };
function NoProtectionsNoteWarning({ appState, onViewNote }: Props) {
console.log("🚀 ~ file: NoProtectionsNoteWarning.tsx ~ line 7 ~ NoProtectionsNoteWarning ~ onViewNote", onViewNote)
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)}
</p>
<button
className="sk-button danger sk-label"
className="sn-button danger sk-label"
disabled={session.revoking}
onClick={() =>
setRevokingSessionUuid(session.uuid)
@@ -210,17 +210,16 @@ const SessionsModal: FunctionComponent<{
<AlertDialogDescription className="sk-panel-row">
<p>{SessionStrings.RevokeText}</p>
</AlertDialogDescription>
<div className="sk-panel-row">
<div className="sk-button-group">
<div className="flex my-1 gap-2">
<button
className="sk-button neutral sk-label"
className="sn-button neutral sk-label"
ref={cancelRevokeRef}
onClick={closeRevokeSessionAlert}
>
<span>{SessionStrings.RevokeCancelButton}</span>
</button>
<button
className="sk-button danger sk-label"
className="sn-button danger sk-label"
onClick={() => {
closeRevokeSessionAlert();
revokeSession(confirmRevokingSessionUuid);
@@ -234,7 +233,6 @@ const SessionsModal: FunctionComponent<{
</div>
</div>
</div>
</div>
</AlertDialog>
)}
</>

View File

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

View File

@@ -7,7 +7,6 @@ export { InputModal } from './inputModal';
export { MenuRow } from './menuRow';
export { PanelResizer } from './panelResizer';
export { PasswordWizard } from './passwordWizard';
export { PermissionsModal } from './permissionsModal';
export { RevisionPreviewModal } from './revisionPreviewModal';
export { HistoryMenu } from './historyMenu';
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 'sn-stylekit/dist/stylekit.css';
import '../stylesheets/index.css.scss';
// import '../stylesheets/_reach-sub.scss';
// Vendor
import 'angular';

View File

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

View File

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

View File

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

View File

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

View File

@@ -80,6 +80,7 @@ type EditorState = {
textareaUnloading: boolean
/** Fields that can be directly mutated by the template */
mutable: any
showEditor: boolean
}
type EditorValues = {
@@ -223,7 +224,8 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
textareaUnloading: false,
mutable: {
tagsString: ''
}
},
showEditor: false,
} as EditorState;
}
@@ -272,15 +274,17 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async handleEditorNoteChange() {
this.cancelPendingSetStatus();
const note = this.editor.note;
const showEditor = !note.protected;
await this.setState({
showActionsMenu: false,
showOptionsMenu: false,
showEditorMenu: false,
showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined
noteStatus: undefined,
showEditor,
});
const note = this.editor.note;
this.editorValues.title = note.title;
this.editorValues.text = note.text;
this.reloadEditor();
@@ -288,11 +292,18 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
this.reloadPreferences();
this.reloadStackComponents();
this.reloadNoteTagsComponent();
if (note.safeText().length === 0) {
if (note.safeText().length === 0 && showEditor) {
this.focusTitle();
}
}
async dismissProtectedWarning() {
await this.setState({
showEditor: true
});
this.focusTitle();
}
/**
* Because note.locked accesses note.content.appData,
* we do not want to expose the template to direct access to note.locked,

View File

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

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;
}
.flex {
display: flex;
}
.flex-column {
flex-direction: column;
}
.self-start {
align-self: flex-start;
}
@@ -226,6 +218,12 @@ $screen-md-max: ($screen-lg-min - 1) !default;
.grid-template-cols-1fr {
grid-template-columns: 1fr;
}
.col-span-all {
grid-column: 1 / -1;
}
.grid-col-2 {
grid-column: 2;
}
.relative {
position: relative;

View File

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

View File

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

View File

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

View File

@@ -30,10 +30,9 @@
.sk-menu-panel-column(ng-if="ctrl.circle && ctrl.circleAlign == 'right'")
.sk-circle.small(ng-class='ctrl.circle')
.sk-menu-panel-column(ng-if='ctrl.hasButton')
.sk-button(
button.sn-button.small(
ng-class='ctrl.buttonClass',
ng-click='ctrl.clickAccessoryButton($event)'
)
.sk-label {{ctrl.buttonText}}
) {{ctrl.buttonText}}
.sk-menu-panel-column(ng-if='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
| on all platforms to ensure maximum compatibility.
.sk-panel-footer
.sk-button.info(
button.sn-button.info(
ng-click='ctrl.nextStep()',
ng-disabled='ctrl.state.lockContinue'
)
.sk-label {{ctrl.state.continueTitle}}
) {{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
| perform a full account sync resolution.
.sk-panel-row
.sk-button-group
.sk-button.info(ng-click='ctrl.downloadBackup(true)')
.sk-label Encrypted
.sk-button.info(ng-click='ctrl.downloadBackup(false)')
.sk-label Decrypted
.sk-button.danger(ng-click='ctrl.skipBackup()')
.sk-label Skip
.flex.gap-2
button.sn-button.info(ng-click='ctrl.downloadBackup(true)') Encrypted
button.sn-button.info(ng-click='ctrl.downloadBackup(false)') Decrypted
button.sn-button.danger(ng-click='ctrl.skipBackup()') Skip
div(ng-if='ctrl.status.backupFinished')
.sk-panel-row(ng-if='!ctrl.status.resolving && !ctrl.status.attemptedResolution')
.sk-button.info(ng-click='ctrl.performSyncResolution()')
.sk-label Perform Sync Resolution
button.sn-button.info(ng-click='ctrl.performSyncResolution()')
| Perform Sync Resolution
.sk-panel-row.justify-left(ng-if='ctrl.status.resolving')
.sk-horizontal-group
.sk-spinner.small.info

View File

@@ -53,7 +53,7 @@
"pug-loader": "^2.4.0",
"sass-loader": "^8.0.2",
"serve-static": "^1.14.1",
"sn-stylekit": "^2.2.1",
"sn-stylekit": "github:standardnotes/StyleKit#e3bfad37d29168bcc15e96399734ffaae1e618ba",
"ts-loader": "^8.0.17",
"typescript": "^4.1.5",
"typescript-eslint": "0.0.1-alpha.0",

View File

@@ -7808,10 +7808,9 @@ slice-ansi@^4.0.0:
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
sn-stylekit@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-2.2.1.tgz#4a81a05b2b2d67a11af9d06f3964ac1ece3aa84a"
integrity sha512-mrvUbf2HbWOfxbNglo7RXa5JBe9UV9rurupeGoX/Kh4/lVlB2n/56ZT103xk/4tp0/mVCpxjD7Dt1stKFxsvFA==
"sn-stylekit@github:standardnotes/StyleKit#e3bfad37d29168bcc15e96399734ffaae1e618ba":
version "3.0.0"
resolved "https://codeload.github.com/standardnotes/StyleKit/tar.gz/e3bfad37d29168bcc15e96399734ffaae1e618ba"
snapdragon-node@^2.0.1:
version "2.1.1"