Refactors most controllers and directives into classes for more organized and maintainable code

This commit is contained in:
Mo Bitar
2020-01-30 13:37:16 -06:00
parent badadba8f8
commit 3c8c43ac7e
144 changed files with 87972 additions and 5613 deletions

View File

@@ -2,126 +2,249 @@
#account-panel.sk-panel
.sk-panel-header
.sk-panel-header-title Account
a.sk-a.info.close-button(ng-click='close()') Close
a.sk-a.info.close-button(ng-click='self.close()') Close
.sk-panel-content
.sk-panel-section.sk-panel-hero(ng-if='!user && !formData.showLogin && !formData.showRegister && !formData.mfa')
.sk-panel-section.sk-panel-hero(
ng-if=`
!self.state.user &&
!self.state.formData.showLogin &&
!self.state.formData.showRegister &&
!self.state.formData.mfa`
)
.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='formData.showLogin = true')
.sk-button.info.featured(ng-click='self.state.formData.showLogin = true')
.sk-label Sign In
.sk-button.info.featured(ng-click='formData.showRegister = true')
.sk-button.info.featured(ng-click='self.state.formData.showRegister = true')
.sk-label Register
.sk-panel-row.sk-p
| Standard Notes is free on every platform, and comes standard with sync and encryption.
.sk-panel-section(ng-if='formData.showLogin || formData.showRegister')
| Standard Notes is free on every platform, and comes
| standard with sync and encryption.
.sk-panel-section(ng-if=`
self.state.formData.showLogin ||
self.state.formData.showRegister`
)
.sk-panel-section-title
| {{formData.showLogin ? "Sign In" : "Register"}}
form.sk-panel-form(ng-submit='submitAuthForm()')
| {{self.state.formData.showLogin ? "Sign In" : "Register"}}
form.sk-panel-form(ng-submit='self.submitAuthForm()')
.sk-panel-section
input.sk-input.contrast(name='email', ng-model='formData.email', ng-model-options='{allowInvalid: true}', placeholder='Email', required='', should-focus='true', sn-autofocus='true', spellcheck='false', type='email')
input.sk-input.contrast(name='password', ng-model='formData.user_password', placeholder='Password', required='', sn-enter='submitAuthForm()', type='password')
input.sk-input.contrast(name='password', ng-if='formData.showRegister', ng-model='formData.password_conf', placeholder='Confirm Password', required='', sn-enter='submitAuthForm()', type='password')
input.sk-input.contrast(
name='email',
ng-model='self.state.formData.email',
ng-model-options='{allowInvalid: true}',
placeholder='Email',
required='',
should-focus='true',
sn-autofocus='true',
spellcheck='false',
type='email'
)
input.sk-input.contrast(
name='password',
ng-model='self.state.formData.user_password',
placeholder='Password',
required='',
sn-enter='self.submitAuthForm()',
type='password'
)
input.sk-input.contrast(
name='password',
ng-if='self.state.formData.showRegister',
ng-model='self.state.formData.password_conf',
placeholder='Confirm Password',
required='',
sn-enter='self.submitAuthForm()',
type='password'
)
.sk-panel-row
a.sk-panel-row.sk-bold(ng-click='formData.showAdvanced = !formData.showAdvanced')
a.sk-panel-row.sk-bold(
ng-click=`
self.state.formData.showAdvanced = !self.state.formData.showAdvanced
`
)
| Advanced Options
.sk-notification.unpadded.contrast.advanced-options.sk-panel-row(ng-if='formData.showAdvanced')
.sk-notification.unpadded.contrast.advanced-options.sk-panel-row(
ng-if='self.state.formData.showAdvanced'
)
.sk-panel-column.stretch
.sk-notification-title.sk-panel-row.padded-row Advanced Options
.bordered-row.padded-row
label.sk-label Sync Server Domain
input.sk-input.mt-5.sk-base(name='server', ng-model='formData.url', placeholder='Server URL', required='', type='text')
label.sk-label.padded-row(ng-if='formData.showLogin')
input.sk-input(ng-model='formData.strictSignin', type='checkbox')
input.sk-input.mt-5.sk-base(
name='server',
ng-model='self.state.formData.url',
placeholder='Server URL',
required='',
type='text'
)
label.sk-label.padded-row(ng-if='self.state.formData.showLogin')
input.sk-input(
ng-model='self.state.formData.strictSignin',
type='checkbox'
)
| Use strict sign in
span
a.info(href='https://standardnotes.org/help/security', rel='noopener', target='_blank') (Learn more)
.sk-panel-section.form-submit(ng-if='!formData.authenticating')
a.info(
href='https://standardnotes.org/help/security',
rel='noopener',
target='_blank'
) (Learn more)
.sk-panel-section.form-submit(ng-if='!self.state.formData.authenticating')
.sk-button-group.stretch
.sk-button.info.featured(ng-click='submitAuthForm()', ng-disabled='formData.authenticating')
.sk-label {{formData.showLogin ? "Sign In" : "Register"}}
.sk-notification.neutral(ng-if='formData.showRegister')
.sk-button.info.featured(
ng-click='self.submitAuthForm()',
ng-disabled='self.state.formData.authenticating'
)
.sk-label {{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
| Because your notes are encrypted using your password, Standard Notes does not have a password reset option. You cannot forget your password.
.sk-panel-section.no-bottom-pad(ng-if='formData.status')
| Because your notes are encrypted using your password,
| Standard Notes does not have a password reset option.
| You cannot forget your password.
.sk-panel-section.no-bottom-pad(ng-if='self.state.formData.status')
.sk-horizontal-group
.sk-spinner.small.neutral
.sk-label {{formData.status}}
.sk-panel-section.no-bottom-pad(ng-if='!formData.authenticating')
.sk-label {{self.state.formData.status}}
.sk-panel-section.no-bottom-pad(ng-if='!self.state.formData.authenticating')
label.sk-panel-row.justify-left
.sk-horizontal-group
input(ng-false-value='true', ng-model='formData.ephemeral', ng-true-value='false', type='checkbox')
input(
ng-false-value='true',
ng-model='self.state.formData.ephemeral',
ng-true-value='false',
type='checkbox'
)
| Stay signed in
label.sk-panel-row.justify-left(ng-if='notesAndTagsCount() > 0')
label.sk-panel-row.justify-left(ng-if='self.notesAndTagsCount() > 0')
.sk-panel-row
input(ng-bind='true', ng-change='mergeLocalChanged()', ng-model='formData.mergeLocal', type='checkbox')
| Merge local data ({{notesAndTagsCount()}} notes and tags)
.sk-panel-section(ng-if='formData.mfa')
form.sk-panel-form(ng-submit='submitMfaForm()')
.sk-p.sk-panel-row {{formData.mfa.message}}
input(
ng-bind='true',
ng-change='self.mergeLocalChanged()',
ng-model='self.state.formData.mergeLocal',
type='checkbox'
)
| Merge local data ({{self.notesAndTagsCount()}} notes and tags)
.sk-panel-section(ng-if='self.state.formData.mfa')
form.sk-panel-form(ng-submit='self.submitMfaForm()')
.sk-p.sk-panel-row {{self.state.formData.mfa.message}}
.sk-panel-row
input.sk-input.contrast(autofocus='true', name='mfa', ng-model='formData.userMfaCode', placeholder='Enter Code', required='', should-focus='true', sn-autofocus='true')
.sk-button-group.stretch.sk-panel-row.form-submit(ng-if='!formData.status')
input.sk-input.contrast(
autofocus='true',
name='mfa',
ng-model='self.state.formData.userMfaCode',
placeholder='Enter Code',
required='',
should-focus='true',
sn-autofocus='true'
)
.sk-button-group.stretch.sk-panel-row.form-submit(
ng-if='!self.state.formData.status'
)
button.sk-button.info.featured(type='submit')
.sk-label Sign In
.sk-panel-section.no-bottom-pad(ng-if='formData.status')
.sk-panel-section.no-bottom-pad(ng-if='self.state.formData.status')
.sk-panel-row
.sk-panel-row
.sk-horizontal-group
.sk-spinner.small.neutral
.sk-label {{formData.status}}
div(ng-if='!formData.showLogin && !formData.showRegister && !formData.mfa')
.sk-panel-section(ng-if='user')
.sk-notification.danger(ng-if='syncStatus.error')
.sk-label {{self.state.formData.status}}
div(
ng-if=`
!self.state.formData.showLogin &&
!self.state.formData.showRegister &&
!self.state.formData.mfa`
)
.sk-panel-section(ng-if='self.state.user')
.sk-notification.danger(ng-if='self.syncStatus.error')
.sk-notification-title Sync Unreachable
.sk-notification-text
| Hmm...we can't seem to sync your account. The reason: {{syncStatus.error.message}}
a.sk-a.info-contrast.sk-bold.sk-panel-row(href='https://standardnotes.org/help', rel='noopener', target='_blank') Need help?
| Hmm...we can't seem to sync your account.
| The reason: {{self.syncStatus.error.message}}
a.sk-a.info-contrast.sk-bold.sk-panel-row(
href='https://standardnotes.org/help',
rel='noopener',
target='_blank'
) Need help?
.sk-panel-row
.sk-panel-column
.sk-h1.sk-bold.wrap {{user.email}}
.sk-subtitle.subtle.normal {{server}}
.sk-horizontal-group(delay='1000', delay-hide='true', show='syncStatus.syncOpInProgress || syncStatus.needsMoreSync')
.sk-h1.sk-bold.wrap {{self.state.user.email}}
.sk-subtitle.subtle.normal {{self.state.server}}
.sk-horizontal-group(
delay='1000',
delay-hide='true',
show='self.syncStatus.syncOpInProgress || self.syncStatus.needsMoreSync'
)
.sk-spinner.small.info
.sk-sublabel
| {{"Syncing" + (syncStatus.total > 0 ? ":" : "")}}
span(ng-if='syncStatus.total > 0') {{syncStatus.current}}/{{syncStatus.total}}
| {{"Syncing" + (self.syncStatus.total > 0 ? ":" : "")}}
span(
ng-if='self.syncStatus.total > 0'
) {{self.syncStatus.current}}/{{self.syncStatus.total}}
.sk-panel-row
a.sk-a.info.sk-panel-row.condensed(ng-click="openPasswordWizard('change-pw')")
a.sk-a.info.sk-panel-row.condensed(
ng-click="self.openPasswordWizard('change-pw')"
)
| Change Password
a.sk-a.info.sk-panel-row.condensed(ng-click="openPrivilegesModal('')", ng-show='user')
a.sk-a.info.sk-panel-row.condensed(
ng-click="self.openPrivilegesModal('')",
ng-show='self.state.user'
)
| Manage Privileges
a.sk-panel-row.justify-left.condensed.success(ng-click="openPasswordWizard('upgrade-security')", ng-if='securityUpdateAvailable')
a.sk-panel-row.justify-left.condensed.success(
ng-click="self.openPasswordWizard('upgrade-security')",
ng-if='self.state.securityUpdateAvailable'
)
.inline.sk-circle.small.success.mr-8
.inline Security Update Available
.sk-panel-section
.sk-panel-section-title Encryption
.sk-panel-section-subtitle.info(ng-if='encryptionEnabled()')
| {{encryptionStatusForNotes()}}
.sk-panel-section-subtitle.info(ng-if='self.encryptionEnabled()')
| {{self.encryptionStatusForNotes()}}
p.sk-p
| {{encryptionStatusString()}}
| {{self.encryptionStatusString()}}
.sk-panel-section
.sk-panel-section-title Passcode Lock
div(ng-if='!hasPasscode()')
div(ng-if='canAddPasscode')
.sk-panel-row(ng-if='!formData.showPasscodeForm')
.sk-button.info(ng-click='addPasscodeClicked(); $event.stopPropagation();')
div(ng-if='!self.hasPasscode()')
div(ng-if='self.state.canAddPasscode')
.sk-panel-row(ng-if='!self.state.formData.showPasscodeForm')
.sk-button.info(
ng-click='self.addPasscodeClicked(); $event.stopPropagation();'
)
.sk-label Add Passcode
p.sk-p Add a passcode to lock the application and encrypt on-device key storage.
div(ng-if='!canAddPasscode')
p.sk-p
| Add a passcode to lock the application and
| encrypt on-device key storage.
div(ng-if='!self.state.canAddPasscode')
p.sk-p
| Adding a passcode is not supported in temporary sessions. Please sign out, then sign back in with the "Stay signed in" option checked.
form.sk-panel-form(ng-if='formData.showPasscodeForm', ng-submit='submitPasscodeForm()')
| Adding a passcode is not supported in temporary sessions. Please sign
| out, then sign back in with the "Stay signed in" option checked.
form.sk-panel-form(
ng-if='self.state.formData.showPasscodeForm',
ng-submit='self.submitPasscodeForm()'
)
.sk-panel-row
input.sk-input.contrast(ng-model='formData.passcode', placeholder='Passcode', should-focus='true', sn-autofocus='true', type='password')
input.sk-input.contrast(ng-model='formData.confirmPasscode', placeholder='Confirm Passcode', type='password')
input.sk-input.contrast(
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',
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(ng-click='formData.showPasscodeForm = false') Cancel
div(ng-if='hasPasscode() && !formData.showPasscodeForm')
a.neutral.sk-a.sk-panel-row(
ng-click='self.state.formData.showPasscodeForm = false'
) Cancel
div(ng-if='self.hasPasscode() && !self.state.formData.showPasscodeForm')
.sk-p
| Passcode lock is enabled.
.sk-notification.contrast
@@ -130,51 +253,98 @@
.sk-panel-row
.sk-horizontal-group
.sk-h4.sk-bold Autolock
a.sk-a.info(ng-class="{'boxed' : option.value == selectedAutoLockInterval}", ng-click='selectAutoLockInterval(option.value)', ng-repeat='option in passcodeAutoLockOptions')
a.sk-a.info(
ng-class=`{
'boxed' : option.value == self.state.selectedAutoLockInterval
}`,
ng-click='self.selectAutoLockInterval(option.value)',
ng-repeat='option in self.state.passcodeAutoLockOptions'
)
| {{option.label}}
.sk-p The autolock timer begins when the window or tab loses focus.
.sk-panel-row
a.sk-a.info.sk-panel-row.condensed(ng-click="openPrivilegesModal('')", ng-show='!user') Manage Privileges
a.sk-a.info.sk-panel-row.condensed(ng-click='changePasscodePressed()') Change Passcode
a.sk-a.danger.sk-panel-row.condensed(ng-click='removePasscodePressed()') Remove Passcode
.sk-panel-section(ng-if='!importData.loading')
a.sk-a.info.sk-panel-row.condensed(
ng-click="self.openPrivilegesModal('')",
ng-show='!self.state.user'
) Manage Privileges
a.sk-a.info.sk-panel-row.condensed(
ng-click='self.changePasscodePressed()'
) Change Passcode
a.sk-a.danger.sk-panel-row.condensed(
ng-click='self.removePasscodePressed()'
) Remove Passcode
.sk-panel-section(ng-if='!self.state.importData.loading')
.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='encryptedBackupsAvailable()')
form.sk-panel-form.sk-panel-row(ng-if='self.encryptedBackupsAvailable()')
.sk-input-group
label
input(ng-change='archiveFormData.encrypted = true', ng-model='archiveFormData.encrypted', ng-value='true', type='radio')
input(
ng-change='self.state.mutable.backupEncrypted = true',
ng-model='self.state.mutable.backupEncrypted',
ng-value='true',
type='radio'
)
| Encrypted
label
input(ng-change='archiveFormData.encrypted = false', ng-model='archiveFormData.encrypted', ng-value='false', type='radio')
input(
ng-change='self.state.mutable.backupEncrypted = false',
ng-model='self.state.mutable.backupEncrypted',
ng-value='false',
type='radio'
)
| Decrypted
.sk-button-group.sk-panel-row.justify-left
.sk-button.info(ng-click='downloadDataArchive()')
.sk-button.info(ng-click='self.downloadDataArchive()')
.sk-label Download Backup
label.sk-button.info
input(file-change='->', handler='importFileSelected(files)', style='display: none;', type='file')
input(
file-change='->',
handler='self.importFileSelected(files)',
style='display: none;',
type='file'
)
.sk-label Import Backup
span(ng-if='isDesktopApplication()')
| Backups are automatically created on desktop and can be managed via the "Backups" top-level menu.
#import-password-request(ng-if='importData.requestPassword')
form.sk-panel-form.stretch(ng-submit='submitImportPassword()')
span(ng-if='self.isDesktopApplication()')
| Backups are automatically created on desktop and can be managed
| via the "Backups" top-level menu.
#import-password-request(ng-if='self.state.importData.requestPassword')
form.sk-panel-form.stretch(ng-submit='self.submitImportPassword()')
p Enter the account password associated with the import file.
input.sk-input.contrast.mt-5(autofocus='true', ng-model='importData.password', placeholder='Enter File Account Password', type='password')
input.sk-input.contrast.mt-5(
autofocus='true',
ng-model='self.state.importData.password',
placeholder='Enter File Account Password',
type='password'
)
.sk-button-group.stretch.sk-panel-row.form-submit
button.sk-button.info(type='submit')
.sk-label Decrypt & Import
p
| Importing from backup will not overwrite existing data, but instead create a duplicate of any differing data.
| Importing from backup will not overwrite existing data,
| but instead create a duplicate of any differing data.
p
| If you'd like to import only a selection of items instead of the whole file, please use the Batch Manager extension.
| If you'd like to import only a selection of items instead of
| the whole file, please use the Batch Manager extension.
.sk-panel-row
.sk-spinner.small.info(ng-if='importData.loading')
.sk-spinner.small.info(ng-if='self.state.importData.loading')
.sk-panel-footer
.sk-panel-row
.sk-p.left.neutral.faded {{appVersion}}
a.sk-a.right(ng-click='formData.showLogin = false; formData.showRegister = false;', ng-if='formData.showLogin || formData.showRegister')
.sk-p.left.neutral.faded {{self.state.appVersion}}
a.sk-a.right(
ng-click=`
self.state.formData.showLogin = false;
self.state.formData.showRegister = false;
`,
ng-if='self.state.formData.showLogin || self.state.formData.showRegister'
)
| Cancel
a.sk-a.right.danger(ng-click='destroyLocalData()', ng-if='!formData.showLogin && !formData.showRegister')
| {{ user ? "Sign out and clear local data" : "Clear all local data" }}
a.sk-a.right.danger(
ng-click='self.destroyLocalData()',
ng-if=`
!self.state.formData.showLogin &&
!self.state.formData.showRegister`
)
| {{ self.state.user ? "Sign out and clear local data" : "Clear all local data" }}

View File

@@ -1,16 +1,35 @@
.sn-component
.sk-menu-panel.dropdown-menu
a.no-decoration(href='https://standardnotes.org/extensions', ng-if='extensions.length == 0', rel='noopener', target='blank')
a.no-decoration(
href='https://standardnotes.org/extensions',
ng-if='self.state.extensions.length == 0',
rel='noopener',
target='blank'
)
menu-row(label="'Download Actions'")
div(ng-repeat='extension in extensions')
.sk-menu-panel-header(ng-click='extension.hide = !extension.hide; $event.stopPropagation();')
div(ng-repeat='extension in self.state.extensions')
.sk-menu-panel-header(
ng-click='extension.hide = !extension.hide; $event.stopPropagation();'
)
.sk-menu-panel-column
.sk-menu-panel-header-title {{extension.name}}
.sk-spinner.small.loading(ng-if='extension.loading')
div(ng-if='extension.hide') …
menu-row(action='executeAction(action, extension);', label='action.label', ng-if='!extension.hide', ng-repeat='action in extension.actionsWithContextForItem(item)', spinner-class="action.running ? 'info' : null", sub-rows='action.subrows', subtitle='action.desc')
menu-row(
action='self.executeAction(action, extension);',
label='action.label',
ng-if='!extension.hide',
ng-repeat='action in extension.actionsWithContextForItem(self.props.item)',
spinner-class="action.running ? 'info' : null",
sub-rows='action.subrows',
subtitle='action.desc'
)
.sk-sublabel(ng-if="action.access_type")
| Uses
strong {{action.access_type}}
| access to this note.
menu-row(faded='true', label="'No Actions Available'", ng-if='extension.actionsWithContextForItem(item).length == 0')
menu-row(
faded='true',
label="'No Actions Available'",
ng-if='extension.actionsWithContextForItem(self.props.item).length == 0'
)

View File

@@ -1,9 +1,15 @@
.sk-modal-background(ng-click="dismiss()")
.sk-modal-content(ng-attr-id="component-content-outer-{{component.uuid}}")
.sk-modal-background(ng-click="ctrl.dismiss()")
.sk-modal-content(
ng-attr-id="component-content-outer-{{ctrl.component.uuid}}"
)
.sn-component
.sk-panel(ng-attr-id="component-content-inner-{{component.uuid}}")
.sk-panel(
ng-attr-id="component-content-inner-{{ctrl.component.uuid}}"
)
.sk-panel-header
.sk-panel-header-title
| {{component.name}}
a.sk-a.info.close-button(ng-click="dismiss()") Close
component-view.component-view(component="component")
| {{ctrl.component.name}}
a.sk-a.info.close-button(ng-click="ctrl.dismiss()") Close
component-view.component-view(
component="ctrl.component"
)

View File

@@ -1,23 +1,23 @@
.sn-component(ng-if='issueLoading')
.sn-component(ng-if='ctrl.issueLoading')
.sk-app-bar.no-edges.no-top-edge.dynamic-height
.left
.sk-app-bar-item
.sk-label.warning There was an issue loading {{component.name}}.
.sk-label.warning There was an issue loading {{ctrl.component.name}}.
.right
.sk-app-bar-item(ng-click='reloadComponent()')
.sk-app-bar-item(ng-click='ctrl.reloadComponent()')
.sk-button.info
.sk-label Reload
.sn-component(ng-if='showNoThemesMessage')
.sn-component(ng-if='ctrl.showNoThemesMessage')
.sk-app-bar.no-edges.no-top-edge.dynamic-height
.left
.sk-app-bar-item
.sk-label.warning This extension does not support themes.
.right
.sk-app-bar-item(ng-click='noThemesMessageDismiss()')
.sk-app-bar-item(ng-click='ctrl.dismissNoThemesMessage()')
.sk-label Dismiss
.sk-app-bar-item(ng-click='disableActiveTheme()')
.sk-app-bar-item(ng-click='ctrl.disableActiveTheme()')
.sk-label Disable Active Theme
.sn-component(ng-if='expired')
.sn-component(ng-if='ctrl.expired')
.sk-app-bar.no-edges.no-top-edge.dynamic-height
.left
.sk-app-bar-item
@@ -25,19 +25,29 @@
.sk-circle.danger.small
.sk-app-bar-item-column
div
a.sk-label.sk-base(href='https://dashboard.standardnotes.org', rel='noopener', target='_blank')
| Your Extended subscription expired on {{component.dateToLocalizedString(component.valid_until)}}.
a.sk-label.sk-base(
href='https://dashboard.standardnotes.org',
rel='noopener',
target='_blank'
)
| Your Extended subscription expired on
| {{ctrl.component.dateToLocalizedString(ctrl.component.valid_until)}}.
.sk-p
| Extensions are in a read-only state.
.right
.sk-app-bar-item(ng-click='reloadComponent()')
.sk-app-bar-item(ng-click='ctrl.reloadComponent()')
.sk-button.info
.sk-label Reload
.sk-app-bar-item
.sk-app-bar-item-column
.sk-button.warning
a.sk-label(href='https://standardnotes.org/help/41/expired', rel='noopener', target='_blank') Help
.sn-component(ng-if="error == 'offline-restricted'")
a.sk-label(
href='https://standardnotes.org/help/41/expired',
rel='noopener',
target='_blank'
) Help
.sn-component(ng-if="ctrl.error == 'offline-restricted'")
.sk-panel.static
.sk-panel-content
.sk-panel-section.stretch
@@ -51,22 +61,35 @@
ul
li.sk-p
strong Enable the Hosted option
| for this extension by opening the 'Extensions' menu and toggling 'Use hosted when local is unavailable' under this extension's options. Then press Reload below.
| for this extension by opening the 'Extensions' menu and
| toggling 'Use hosted when local is unavailable' under this
| extension's options. Then press Reload below.
li.sk-p
strong Use the Desktop application.
.sk-panel-row
.sk-button.info(ng-click='reloadStatus()', ng-if='!reloading')
.sk-button.info(
ng-click='ctrl.reloadStatus()',
ng-if='!ctrl.reloading'
)
.sk-label Reload
.sk-spinner.info.small(ng-if='reloading')
.sn-component(ng-if="error == 'url-missing'")
.sk-spinner.info.small(ng-if='ctrl.reloading')
.sn-component(ng-if="ctrl.error == 'url-missing'")
.sk-panel.static
.sk-panel-content
.sk-panel-section.stretch
.sk-panel-section-title This extension is not installed correctly.
p Please uninstall {{component.name}}, then re-install it.
p Please uninstall {{ctrl.component.name}}, then re-install it.
p
| This issue can occur if you access Standard Notes using an older version of the app.
| This issue can occur if you access Standard Notes using an older
| version of the app.
| Ensure you are running at least version 2.1 on all platforms.
iframe(data-component-id='{{component.uuid}}', frameborder='0', ng-attr-id='component-iframe-{{component.uuid}}', ng-if='component && componentValid', ng-src='{{getUrl() | trusted}}', sandbox='allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals allow-forms')
iframe(
data-component-id='{{ctrl.component.uuid}}',
frameborder='0',
ng-attr-id='component-iframe-{{ctrl.component.uuid}}',
ng-if='ctrl.component && ctrl.componentValid',
ng-src='{{ctrl.getUrl() | trusted}}',
sandbox='allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals allow-forms'
)
| Loading
.loading-overlay(ng-if='loading')
.loading-overlay(ng-if='ctrl.loading')

View File

@@ -6,21 +6,26 @@
.sk-panel-header
h1.sk-panel-header-title Conflicted items — choose which version to keep
.sk-horizontal-group
a.sk-a.info.close-button(ng-click="keepItem1()") Keep left
a.sk-a.info.close-button(ng-click="keepItem2()") Keep right
a.sk-a.info.close-button(ng-click="keepBoth()") Keep both
a.sk-a.info.close-button(ng-click="export()") Export
a.sk-a.info.close-button(ng-click="dismiss(); $event.stopPropagation()") Close
a.sk-a.info.close-button(ng-click="ctrl.keepItem1()") Keep left
a.sk-a.info.close-button(ng-click="ctrl.keepItem2()") Keep right
a.sk-a.info.close-button(ng-click="ctrl.keepBoth()") Keep both
a.sk-a.info.close-button(ng-click="ctrl.export()") Export
a.sk-a.info.close-button(
ng-click="ctrl.dismiss(); $event.stopPropagation()"
) Close
.sk-panel-content.selectable
.sk-panel-section
h3
strong Content type:
| {{contentType}}
| {{ctrl.contentType}}
p
| You may wish to look at the "created_at" and "updated_at" fields of the items to gain better context in deciding which to keep.
| You may wish to look at the "created_at" and "updated_at" fields
| of the items to gain better context in deciding which to keep.
#items
#item1.sk-panel.static.item
p.normal(style="white-space: pre-wrap; font-size: 16px;") {{item1Content}}
p.normal(style="white-space: pre-wrap; font-size: 16px;")
| {{ctrl.item1Content}}
.border
#item2.sk-panel.static.item
p.normal(style="white-space: pre-wrap; font-size: 16px;") {{item2Content}}
p.normal(style="white-space: pre-wrap; font-size: 16px;")
| {{ctrl.item2Content}}

View File

@@ -3,10 +3,34 @@
.sk-menu-panel-section
.sk-menu-panel-header
.sk-menu-panel-header-title Note Editor
menu-row(action='selectComponent(null)', circle="selectedEditor == null && 'success'", label="'Plain Editor'")
menu-row(action='selectComponent(editor)', button-action='toggleDefaultForEditor(editor)', button-class="defaultEditor == editor ? 'warning' : 'info'", button-text="defaultEditor == editor ? 'Undefault' : 'Set Default'", circle="selectedEditor === editor && 'success'", has-button='selectedEditor == editor || defaultEditor == editor', label='editor.name', ng-repeat='editor in editors')
.sk-menu-panel-column(ng-if='component.content.conflict_of || shouldDisplayRunningLocallyLabel(editor)')
strong.danger.medium-text(ng-if='editor.content.conflict_of') Conflicted copy
.sk-sublabel(ng-if='shouldDisplayRunningLocallyLabel(editor)') Running Locally
a.no-decoration(href='https://standardnotes.org/extensions', ng-if='editors.length == 0', rel='noopener', target='blank')
menu-row(
action='self.selectComponent(null)',
circle="self.selectedEditor == null && 'success'",
label="'Plain Editor'"
)
menu-row(
ng-repeat='editor in self.state.editors'
action='self.selectComponent(editor)',
button-action='self.toggleDefaultForEditor(editor)',
button-class="self.state.defaultEditor == editor ? 'warning' : 'info'",
button-text="self.state.defaultEditor == editor ? 'Undefault' : 'Set Default'",
circle="self.selectedEditor === editor && 'success'",
has-button='self.selectedEditor == editor || self.state.defaultEditor == editor',
label='editor.name',
)
.sk-menu-panel-column(
ng-if='editor.content.conflict_of || self.shouldDisplayRunningLocallyLabel(editor)'
)
strong.danger.medium-text(
ng-if='editor.content.conflict_of'
) Conflicted copy
.sk-sublabel(
ng-if='self.shouldDisplayRunningLocallyLabel(editor)'
) Running Locally
a.no-decoration(
href='https://standardnotes.org/extensions',
ng-if='self.state.editors.length == 0',
rel='noopener',
target='blank'
)
menu-row(label="'Download More Editors'")

View File

@@ -5,15 +5,21 @@
.sn-component
.sk-panel
.sk-panel-header
.sk-h1.sk-panel-header-title {{title}}
a.sk-a.info.close-button(ng-click="dismiss()") Close
.sk-h1.sk-panel-header-title {{ctrl.title}}
a.sk-a.info.close-button(ng-click="ctrl.dismiss()") Close
.sk-panel-content
.sk-panel-section
.sk-p.sk-panel-row {{message}}
.sk-p.sk-panel-row {{ctrl.message}}
.sk-panel-row
.sk-panel-column.stretch
form(ng-submit="submit()")
input.sk-input.contrast(ng-model="formData.input" placeholder="{{placeholder}}" should-focus="true" sn-autofocus="true" type="{{type}}")
form(ng-submit="ctrl.submit()")
input.sk-input.contrast(
ng-model="ctrl.formData.input"
placeholder="{{ctrl.placeholder}}"
should-focus="true"
sn-autofocus="true"
type="{{ctrl.type}}"
)
.sk-panel-footer
a.sk-a.info.right(ng-click="submit()")
a.sk-a.info.right(ng-click="ctrl.submit()")
| Submit

View File

@@ -1,20 +1,39 @@
.sk-menu-panel-row.row(ng-attr-title='{{desc}}', ng-click='onClick($event)')
.sk-menu-panel-row.row(
ng-attr-title='{{ctrl.desc}}',
ng-click='ctrl.onClick($event)'
)
.sk-menu-panel-column
.left
.sk-menu-panel-column(ng-if="circle && (!circleAlign || circleAlign == 'left')")
.sk-circle.small(ng-class='circle')
.sk-menu-panel-column(ng-class="{'faded' : faded || disabled}")
.sk-label(ng-class='stylekitClass')
| {{label}}
.sk-sublabel(ng-if='subtitle')
| {{subtitle}}
.sk-menu-panel-column(
ng-if=`
ctrl.circle &&
(!ctrl.circleAlign || ctrl.circleAlign == 'left')
`
)
.sk-circle.small(ng-class='ctrl.circle')
.sk-menu-panel-column(
ng-class="{'faded' : ctrl.faded || ctrl.disabled}"
)
.sk-label(ng-class='ctrl.stylekitClass')
| {{ctrl.label}}
.sk-sublabel(ng-if='ctrl.subtitle')
| {{ctrl.subtitle}}
ng-transclude
.sk-menu-panel-subrows(ng-if='subRows && subRows.length > 0')
menu-row(action='row.onClick()', label='row.label', ng-repeat='row in subRows', spinner-class='row.spinnerClass', subtitle='row.subtitle')
.sk-menu-panel-column(ng-if="circle && circleAlign == 'right'")
.sk-circle.small(ng-class='circle')
.sk-menu-panel-column(ng-if='hasButton')
.sk-button(ng-class='buttonClass', ng-click='clickButton($event)')
.sk-label {{buttonText}}
.sk-menu-panel-column(ng-if='spinnerClass')
.sk-spinner.small(ng-class='spinnerClass')
.sk-menu-panel-subrows(ng-if='ctrl.subRows && ctrl.subRows.length > 0')
menu-row(
ng-repeat='row in ctrl.subRows',
action='row.onClick()',
label='row.label',
spinner-class='row.spinnerClass',
subtitle='row.subtitle'
)
.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(
ng-class='ctrl.buttonClass',
ng-click='ctrl.clickAccessoryButton($event)'
)
.sk-label {{ctrl.buttonText}}
.sk-menu-panel-column(ng-if='ctrl.spinnerClass')
.sk-spinner.small(ng-class='ctrl.spinnerClass')

View File

@@ -5,89 +5,133 @@
.sn-component
.sk-panel
.sk-panel-header
.sk-panel-header-title {{title}}
a.sk-a.info.close-button(ng-click='dismiss()') Close
.sk-panel-header-title {{ctrl.title}}
a.sk-a.info.close-button(ng-click='ctrl.dismiss()') Close
.sk-panel-content
div(ng-if='step == 0')
div(ng-if='changePassword')
div(ng-if='ctrl.step == 0')
div(ng-if='ctrl.changePassword')
p.sk-p.sk-panel-row
| Changing your password involves changing your encryption key, which requires your data to be re-encrypted and synced.
| Changing your password involves changing your encryption key,
| which requires your data to be re-encrypted and synced.
| If you have many items, syncing your data can take several minutes.
p.sk-p.sk-panel-row You must keep the application window open during this process.
div(ng-if='securityUpdate')
p.sk-p.sk-panel-row
| You must keep the application window open during this process.
div(ng-if='ctrl.securityUpdate')
p.sk-p.sk-panel-row
| A new update is available for your account. Updates address improvements and enhancements to our security specification.
| This process will guide you through the update, and perform the steps necessary with your supervision.
| A new update is available for your account. Updates address
| improvements and enhancements to our security specification.
| This process will guide you through the update, and perform the
| steps necessary with your supervision.
.sk-panel-row
.sk-panel-column
p.sk-p For more information about security updates, please visit
a.sk-a.info(href='https://standardnotes.org/help/security', rel='noopener', target='_blank') standardnotes.org/help/security.
a.sk-a.info(
href='https://standardnotes.org/help/security',
rel='noopener',
target='_blank'
) standardnotes.org/help/security.
p.sk-panel-row.sk-p
.info Press Continue to proceed.
p
.sk-panel-section(ng-if='step > 0')
.sk-panel-section-title Step {{step}} — {{titleForStep(step)}}
div(ng-if='step == 1')
.sk-panel-section(ng-if='ctrl.step > 0')
.sk-panel-section-title Step {{ctrl.step}} — {{ctrl.titleForStep(ctrl.step)}}
div(ng-if='ctrl.step == 1')
p.sk-panel-row.sk-p
| As a result of this process, the entirety of your data will be re-encrypted and synced to your account. This is a generally safe process,
| but unforeseen factors like poor network connectivity or a sudden shutdown of your computer may cause this process to fail.
| It's best to be on the safe side before large operations such as this one.
| As a result of this process, the entirety of your data will be
| re-encrypted and synced to your account. This is a generally safe
| process, but unforeseen factors like poor network connectivity or a
| sudden shutdown of your computer may cause this process to fail. It's
| best to be on the safe side before large operations such as this one.
.sk-panel-row
.sk-panel-row
.sk-button-group
.sk-button.info(ng-click='downloadBackup(true)')
.sk-button.info(ng-click='ctrl.downloadBackup(true)')
.sk-label Download Encrypted Backup
.sk-button.info(ng-click='downloadBackup(false)')
.sk-button.info(ng-click='ctrl.downloadBackup(false)')
.sk-label Download Decrypted Backup
div(ng-if='step == 2')
div(ng-if='ctrl.step == 2')
p.sk-p.sk-panel-row
| As a result of this process, your encryption keys will change.
| Any device on which you use Standard Notes will need to end its session. After this process completes, you will be asked to sign back in.
p.sk-p.bold.sk-panel-row.info-i Please sign out of all applications (excluding this one), including:
| As a result of this process, your encryption keys will change. Any
| device on which you use Standard Notes will need to end its session.
| After this process completes, you will be asked to sign back in.
p.sk-p.bold.sk-panel-row.info-i
| Please sign out of all applications (excluding this one), including:
ul
li.sk-p Desktop
li.sk-p Web (Chrome, Firefox, Safari)
li.sk-p Mobile (iOS and Android)
p.sk-p.sk-panel-row
| If you do not currently have access to a device you're signed in on, you may proceed,
| but must make signing out and back in the first step upon gaining access to that device.
p.sk-p.sk-panel-row Press Continue only when you have completed signing out of all your devices.
div(ng-if='step == 3')
div(ng-if='changePassword')
div(ng-if='securityUpdate')
| If you do not currently have access to a device you're signed in on,
| you may proceed, but must make signing out and back in the first step
| upon gaining access to that device.
p.sk-p.sk-panel-row
| Press Continue only when you have
| completed signing out of all your devices.
div(ng-if='ctrl.step == 3')
div(ng-if='ctrl.changePassword')
div(ng-if='ctrl.securityUpdate')
p.sk-panel-row
| Enter your current password. We'll run this through our encryption scheme to generate strong new encryption keys.
| Enter your current password. We'll run this through our encryption
| scheme to generate strong new encryption keys.
.sk-panel-row
.sk-panel-row
.sk-panel-column.stretch
form.sk-panel-form
input.sk-input.contrast(ng-model='formData.currentPassword', placeholder='Current Password', should-focus='true', sn-autofocus='true', type='password')
input.sk-input.contrast(ng-if='changePassword', ng-model='formData.newPassword', placeholder='New Password', type='password')
input.sk-input.contrast(ng-if='changePassword', ng-model='formData.newPasswordConfirmation', placeholder='Confirm New Password', type='password')
div(ng-if='step == 4')
input.sk-input.contrast(
ng-model='ctrl.formData.currentPassword',
placeholder='Current Password',
should-focus='true',
sn-autofocus='true',
type='password'
)
input.sk-input.contrast(
ng-if='ctrl.changePassword',
ng-model='ctrl.formData.newPassword',
placeholder='New Password',
type='password'
)
input.sk-input.contrast(
ng-if='ctrl.changePassword',
ng-model='ctrl.formData.newPasswordConfirmation',
placeholder='Confirm New Password',
type='password'
)
div(ng-if='ctrl.step == 4')
p.sk-panel-row
| Your data is being re-encrypted with your new keys and synced to your account.
p.sk-panel-row.danger(ng-if='lockContinue')
| Your data is being re-encrypted with your new
| keys and synced to your account.
p.sk-panel-row.danger(ng-if='ctrl.lockContinue')
| Do not close this window until this process completes.
.sk-panel-row
.sk-panel-column
.sk-spinner.small.inline.info.mr-5(ng-if='formData.processing')
.inline.bold(ng-class="{'info' : !formData.statusError, 'error' : formData.statusError}")
| {{formData.status}}
.sk-panel-column(delay='1000', delay-hide='true', show='syncStatus.syncOpInProgress || syncStatus.needsMoreSync')
.sk-spinner.small.inline.info.mr-5(ng-if='ctrl.formData.processing')
.inline.bold(
ng-class="{'info' : !ctrl.formData.statusError, 'error' : ctrl.formData.statusError}"
)
| {{ctrl.formData.status}}
.sk-panel-column(
delay='1000',
delay-hide='true',
show='ctrl.syncStatus.syncOpInProgress || ctrl.syncStatus.needsMoreSync'
)
p.info
| Syncing {{syncStatus.current}}/{{syncStatus.total}}
div(ng-if='step == 5')
div(ng-if='changePassword')
| Syncing {{ctrl.syncStatus.current}}/{{ctrl.syncStatus.total}}
div(ng-if='ctrl.step == 5')
div(ng-if='ctrl.changePassword')
p.sk-p.sk-panel-row.info-i Your password has been successfully changed.
div(ng-if='securityUpdate')
div(ng-if='ctrl.securityUpdate')
p.sk-p.sk-panel-row.info-i
| The security update has been successfully applied to your account.
p.sk-p.sk-panel-row
| Please ensure you are running the latest version of Standard Notes on all platforms to ensure maximum compatibility.
p.sk-p.sk-panel-row You may now sign back in on all your devices and close this window.
| Please ensure you are running the latest version of Standard Notes
| on all platforms to ensure maximum compatibility.
p.sk-p.sk-panel-row
| You may now sign back in on all your devices and close this window.
.sk-panel-footer
.empty
a.sk-a.info.right(ng-class="{'disabled' : lockContinue}", ng-click='continue()', ng-disabled='lockContinue')
.sk-spinner.small.inline.info.mr-5(ng-if='showSpinner')
| {{continueTitle}}
a.sk-a.info.right(
ng-class="{'disabled' : ctrl.lockContinue}",
ng-click='ctrl.nextStep()',
ng-disabled='ctrl.lockContinue')
.sk-spinner.small.inline.info.mr-5(ng-if='ctrl.showSpinner')
| {{ctrl.continueTitle}}

View File

@@ -1,21 +1,25 @@
.sk-modal-background(ng-click='deny()')
.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='deny()') Cancel
a.sk-a.info.close-button(ng-click='ctrl.deny()') Cancel
.sk-panel-content
.sk-panel-section
.sk-panel-row
.sk-h2
strong {{component.name}}
strong {{ctrl.component.name}}
| would like to interact with your
| {{permissionsString}}
| {{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.
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.bold(ng-click='accept()')
.sk-button.info.big.block.bold(ng-click='ctrl.accept()')
.sk-label Continue

View File

@@ -1,25 +1,37 @@
.sk-modal-background(ng-click="cancel()")
.sk-modal-background(ng-click="ctrl.cancel()")
#privileges-modal.sk-modal-content
.sn-component
.sk-panel
.sk-panel-header
.sk-panel-header-title Authentication Required
a.close-button.info(ng-click="cancel()") Cancel
a.close-button.info(ng-click="ctrl.cancel()") Cancel
.sk-panel-content
.sk-panel-section
div(ng-repeat="credential in requiredCredentials")
div(ng-repeat="credential in ctrl.requiredCredentials")
.sk-p.sk-bold.sk-panel-row
strong {{promptForCredential(credential)}}
strong {{ctrl.promptForCredential(credential)}}
.sk-panel-row
input.sk-input.contrast(ng-model="authenticationParameters[credential]" should-focus="$index == 0" sn-autofocus="true" sn-enter="submit()" type="password")
input.sk-input.contrast(
ng-model="ctrl.authParameters[credential]"
should-focus="$index == 0"
sn-autofocus="true"
sn-enter="ctrl.submit()"
type="password"
)
.sk-panel-row
label.sk-label.danger(ng-if="isCredentialInFailureState(credential)") Invalid authentication. Please try again.
label.sk-label.danger(
ng-if="ctrl.isCredentialInFailureState(credential)"
) Invalid authentication. Please try again.
.sk-panel-row
.sk-panel-row
.sk-horizontal-group
.sk-p.sk-bold Remember For
a.sk-a.info(ng-class="{'boxed' : option.value == selectedSessionLength}" ng-click="selectSessionLength(option.value)" ng-repeat="option in sessionLengthOptions")
a.sk-a.info(
ng-repeat="option in ctrl.sessionLengthOptions"
ng-class="{'boxed' : option.value == ctrl.selectedSessionLength}"
ng-click="ctrl.selectSessionLength(option.value)"
)
| {{option.label}}
.sk-panel-footer.extra-padding
.sk-button.info.big.block.bold(ng-click="submit()")
.sk-button.info.big.block.bold(ng-click="ctrl.submit()")
.sk-label Submit

View File

@@ -1,39 +1,51 @@
.sk-modal-background(ng-click='cancel()')
.sk-modal-background(ng-click='ctrl.cancel()')
#privileges-modal.sk-modal-content
.sn-component
.sk-panel
.sk-panel-header
.sk-panel-header-title Manage Privileges
a.sk-a.close-button.info(ng-click='cancel()') Done
a.sk-a.close-button.info(ng-click='ctrl.cancel()') Done
.sk-panel-content
.sk-panel-section
table.sk-table
thead
tr
th
th(ng-repeat='cred in availableCredentials')
th(ng-repeat='cred in ctrl.availableCredentials')
.priv-header
strong {{credentialDisplayInfo[cred].label}}
.sk-p.font-small(ng-show='!credentialDisplayInfo[cred].availability', style='margin-top: 2px') Not Configured
strong {{ctrl.credentialDisplayInfo[cred].label}}
.sk-p.font-small(
ng-show='!ctrl.credentialDisplayInfo[cred].availability',
style='margin-top: 2px'
) Not Configured
tbody
tr(ng-repeat='action in availableActions')
tr(ng-repeat='action in ctrl.availableActions')
td
.sk-p {{displayInfoForAction(action)}}
th(ng-repeat='credential in availableCredentials')
input(ng-checked='isCredentialRequiredForAction(action, credential)', ng-click='checkboxValueChanged(action, credential)', ng-disabled='!credentialDisplayInfo[credential].availability', type='checkbox')
.sk-panel-section(ng-if='sessionExpirey && !sessionExpired')
.sk-p.sk-panel-row You will not be asked to authenticate until {{sessionExpirey}}.
a.sk-a.sk-panel-row.info(ng-click='clearSession()') Clear Session
.sk-p {{ctrl.displayInfoForAction(action)}}
th(ng-repeat='credential in ctrl.availableCredentials')
input(
ng-checked='ctrl.isCredentialRequiredForAction(action, credential)',
ng-click='ctrl.checkboxValueChanged(action, credential)',
ng-disabled='!ctrl.credentialDisplayInfo[credential].availability',
type='checkbox'
)
.sk-panel-section(ng-if='ctrl.sessionExpirey && !ctrl.sessionExpired')
.sk-p.sk-panel-row
| You will not be asked to authenticate until {{ctrl.sessionExpirey}}.
a.sk-a.sk-panel-row.info(ng-click='ctrl.clearSession()') Clear Session
.sk-panel-footer
.sk-h2.sk-bold About Privileges
.sk-panel-section.no-bottom-pad
.sk-panel-row
.text-content
.sk-p
| Privileges represent interface level authentication for accessing certain items and features.
| Note that when your application is unlocked, your data exists in temporary memory in an unencrypted state.
| Privileges are meant to protect against unwanted access in the event of an unlocked application, but do not affect data encryption state.
| Privileges represent interface level authentication for accessing
| certain items and features. Note that when your application is unlocked,
| your data exists in temporary memory in an unencrypted state.
| Privileges are meant to protect against unwanted access in the event of
| an unlocked application, but do not affect data encryption state.
p.sk-p
| Privileges sync across your other devices; however, note that if you require
| a "Local Passcode" privilege, and another device does not have a local passcode set up, the local passcode
| requirement will be ignored on that device.
| Privileges sync across your other devices; however, note that if you
| require a "Local Passcode" privilege, and another device does not have
| a local passcode set up, the local passcode requirement will be ignored
| on that device.

View File

@@ -7,10 +7,21 @@
.sk-panel-header
.sk-panel-header-title Preview
.sk-horizontal-group
a.sk-a.info.close-button(ng-click="restore(false)") Restore
a.sk-a.info.close-button(ng-click="restore(true)") Restore as copy
a.sk-a.info.close-button(ng-click="dismiss(); $event.stopPropagation()") Close
.sk-panel-content.selectable(ng-if="!editor")
.sk-h2 {{content.title}}
p.normal.sk-p(style="white-space: pre-wrap; font-size: 16px;") {{content.text}}
component-view.component-view(component="editor" ng-if="editor")
a.sk-a.info.close-button(
ng-click="ctrl.restore(false)"
) Restore
a.sk-a.info.close-button(
ng-click="ctrl.restore(true)"
) Restore as copy
a.sk-a.info.close-button(
ng-click="ctrl.dismiss(); $event.stopPropagation()"
) Close
.sk-panel-content.selectable(ng-if="!ctrl.editor")
.sk-h2 {{ctrl.content.title}}
p.normal.sk-p(
style="white-space: pre-wrap; font-size: 16px;"
) {{ctrl.content.text}}
component-view.component-view(
component="ctrl.editor"
ng-if="ctrl.editor"
)

View File

@@ -1,17 +1,35 @@
#session-history-menu.sn-component
.sk-menu-panel.dropdown-menu
.sk-menu-panel-header
.sk-menu-panel-header-title {{history.entries.length || 'No'}} revisions
a.sk-a.info.sk-h5(ng-click='showOptions = !showOptions; $event.stopPropagation();') Options
div(ng-if='showOptions')
menu-row(action='clearItemHistory()', label="'Clear note local history'")
menu-row(action='clearAllHistory()', label="'Clear all local history'")
menu-row(action='toggleAutoOptimize()', label="(autoOptimize ? 'Disable' : 'Enable') + ' auto cleanup'")
.sk-menu-panel-header-title {{ctrl.history.entries.length || 'No'}} revisions
a.sk-a.info.sk-h5(
ng-click='ctrl.showOptions = !ctrl.showOptions; $event.stopPropagation();'
) Options
div(ng-if='ctrl.showOptions')
menu-row(
action='ctrl.clearItemHistory()'
label="'Clear note local history'"
)
menu-row(
action='ctrl.clearAllHistory()'
label="'Clear all local history'"
)
menu-row(
action='ctrl.toggleAutoOptimize()'
label="(ctrl.autoOptimize ? 'Disable' : 'Enable') + ' auto cleanup'")
.sk-sublabel
| Automatically cleans up small revisions to conserve space.
menu-row(action='toggleDiskSaving()', label="(diskEnabled ? 'Disable' : 'Enable') + ' saving history to disk'")
menu-row(
action='ctrl.toggleDiskSaving()'
label="(ctrl.diskEnabled ? 'Disable' : 'Enable') + ' saving history to disk'"
)
.sk-sublabel
| Saving to disk is not recommended. Decreases performance and increases app loading time and memory footprint.
menu-row(action='openRevision(revision);', label='revision.previewTitle()', ng-repeat='revision in entries')
.sk-sublabel.opaque(ng-class='classForRevision(revision)')
| Saving to disk is not recommended. Decreases performance and increases app
| loading time and memory footprint.
menu-row(
ng-repeat='revision in ctrl.entries'
action='ctrl.openRevision(revision);'
label='revision.previewTitle()'
)
.sk-sublabel.opaque(ng-class='ctrl.classForRevision(revision)')
| {{revision.previewSubTitle()}}

View File

@@ -2,54 +2,59 @@
#sync-resolution-menu.sk-panel.sk-panel-right
.sk-panel-header
.sk-panel-header-title Out of Sync
a.sk-a.info.close-button(ng-click='close()') Close
a.sk-a.info.close-button(ng-click='ctrl.close()') Close
.sk-panel-content
.sk-panel-section
.sk-panel-row.sk-p
| We've detected that the data on the server may not match the data in the current application session.
| We've detected that the data on the server may not match
| the data in the current application session.
.sk-p.sk-panel-row
.sk-panel-column
strong.sk-panel-row Option 1 — Restart App:
.sk-p Quit the application and re-open it. Sometimes, this may resolve the issue.
.sk-p
| Quit the application and re-open it.
| Sometimes, this may resolve the issue.
.sk-p.sk-panel-row
.sk-panel-column
strong.sk-panel-row Option 2 (recommended) — Sign Out:
.sk-p
| Sign out of your account, then sign back in. This will ensure your data is consistent with the server.
| Sign out of your account, then sign back in.
| This will ensure your data is consistent with the server.
| Be sure to download a backup of your data before doing so.
.sk-p.sk-panel-row
.sk-panel-column
strong.sk-panel-row Option 3 — Sync Resolution:
.sk-p
| We can attempt to reconcile changes by downloading all data from the server.
| No existing data will be overwritten. If the local contents of an item differ from what the server has,
| a conflicted copy will be created.
div(ng-if='!status.backupFinished')
| We can attempt to reconcile changes by downloading all data from the
| server. No existing data will be overwritten. If the local contents of
| an item differ from what the server has, a conflicted copy will be created.
div(ng-if='!ctrl.status.backupFinished')
.sk-p.sk-panel-row
| Please download a backup before we attempt to perform a full account sync resolution.
| 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='downloadBackup(true)')
.sk-button.info(ng-click='ctrl.downloadBackup(true)')
.sk-label Encrypted
.sk-button.info(ng-click='downloadBackup(false)')
.sk-button.info(ng-click='ctrl.downloadBackup(false)')
.sk-label Decrypted
.sk-button.danger(ng-click='skipBackup()')
.sk-button.danger(ng-click='ctrl.skipBackup()')
.sk-label Skip
div(ng-if='status.backupFinished')
.sk-panel-row(ng-if='!status.resolving && !status.attemptedResolution')
.sk-button.info(ng-click='performSyncResolution()')
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
.sk-panel-row.justify-left(ng-if='status.resolving')
.sk-panel-row.justify-left(ng-if='ctrl.status.resolving')
.sk-horizontal-group
.sk-spinner.small.info
.sk-label Attempting sync resolution...
.sk-panel-column(ng-if='status.fail')
.sk-panel-column(ng-if='ctrl.status.fail')
.sk-panel-row.sk-label.danger Sync Resolution Failed
.sk-p.sk-panel-row
| We attempted to reconcile local content and server content, but were unable to do so.
| At this point, we recommend signing out of your account and signing back in. You may
| wish to download a data backup before doing so.
.sk-panel-column(ng-if='status.success')
| We attempted to reconcile local content and server content, but were
| unable to do so. At this point, we recommend signing out of your account
| and signing back in. You may wish to download a data backup before doing so.
.sk-panel-column(ng-if='ctrl.status.success')
.sk-panel-row.sk-label.success Sync Resolution Success
.sk-p.sk-panel-row
| Your local data is now in sync with the server. You may close this window.

View File

@@ -1,72 +1,253 @@
#editor-column.section.editor.sn-component(aria-label='Note')
.sn-component
.sk-app-bar.no-edges(ng-if='ctrl.note.locked', ng-init="ctrl.lockText = 'Note Locked'", ng-mouseleave="ctrl.lockText = 'Note Locked'", ng-mouseover="ctrl.lockText = 'Unlock'")
.sk-app-bar.no-edges(
ng-if='self.state.note.locked',
ng-init="self.lockText = 'Note Locked'",
ng-mouseleave="self.lockText = 'Note Locked'",
ng-mouseover="self.lockText = 'Unlock'"
)
.left
.sk-app-bar-item(ng-click='ctrl.toggleLockNote()')
.sk-app-bar-item(ng-click='self.toggleLockNote()')
.sk-label.warning
i.icon.ion-locked
| {{ctrl.lockText}}
#editor-title-bar.section-title-bar(ng-class="{'locked' : ctrl.note.locked}", ng-show='ctrl.note && !ctrl.note.errorDecrypting')
| {{self.lockText}}
#editor-title-bar.section-title-bar(
ng-class="{'locked' : self.state.note.locked}",
ng-show='self.state.note && !self.state.note.errorDecrypting'
)
.title
input#note-title-editor.input(ng-blur='ctrl.onNameBlur()', ng-change='ctrl.onTitleChange()', ng-disabled='ctrl.note.locked', ng-focus='ctrl.onNameFocus()', ng-keyup='$event.keyCode == 13 && ctrl.onTitleEnter($event)', ng-model='ctrl.note.title', select-on-click='true', spellcheck='false')
input#note-title-editor.input(
ng-blur='self.onNameBlur()',
ng-change='self.onTitleChange()',
ng-disabled='self.state.note.locked',
ng-focus='self.onNameFocus()',
ng-keyup='$event.keyCode == 13 && self.onTitleEnter($event)',
ng-model='self.state.note.title',
select-on-click='true',
spellcheck='false')
#save-status
.message(ng-class="{'warning sk-bold': ctrl.syncTakingTooLong, 'danger sk-bold': ctrl.saveError}") {{ctrl.noteStatus.message}}
.desc(ng-show='ctrl.noteStatus.desc') {{ctrl.noteStatus.desc}}
.message(
ng-class="{'warning sk-bold': self.state.syncTakingTooLong, 'danger sk-bold': self.state.saveError}"
) {{self.state.noteStatus.message}}
.desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}}
.editor-tags
#note-tags-component-container(ng-if='ctrl.tagsComponent')
component-view.component-view(component='ctrl.tagsComponent', ng-class="{'locked' : ctrl.note.locked}", ng-style="ctrl.note.locked && {'pointer-events' : 'none'}")
input.tags-input(ng-blur='ctrl.updateTagsFromTagsString($event, ctrl.tagsString)', ng-disabled='ctrl.note.locked', ng-if='!(ctrl.tagsComponent && ctrl.tagsComponent.active)', ng-keyup='$event.keyCode == 13 && $event.target.blur();', ng-model='ctrl.tagsString', placeholder='#tags', spellcheck='false', type='text')
.sn-component(ng-if='ctrl.note')
#note-tags-component-container(ng-if='self.state.tagsComponent')
component-view.component-view(
component='self.state.tagsComponent',
ng-class="{'locked' : self.state.note.locked}",
ng-style="self.state.note.locked && {'pointer-events' : 'none'}"
)
input.tags-input(
ng-blur='self.updateTagsFromTagsString($event, self.state.tagsString)',
ng-disabled='self.state.note.locked',
ng-if='!(self.state.tagsComponent && self.state.tagsComponent.active)',
ng-keyup='$event.keyCode == 13 && $event.target.blur();',
ng-model='self.state.tagsString',
placeholder='#tags',
spellcheck='false',
type='text'
)
.sn-component(ng-if='self.state.note')
#editor-menu-bar.sk-app-bar.no-edges
.left
.sk-app-bar-item(click-outside='ctrl.showMenu = false;', is-open='ctrl.showMenu', ng-class="{'selected' : ctrl.showMenu}", ng-click="ctrl.toggleMenu('showMenu')")
.sk-app-bar-item(
click-outside=`self.setMenuState('showOptionsMenu', false)`,
is-open='self.state.showOptionsMenu',
ng-class="{'selected' : self.state.showOptionsMenu}",
ng-click="self.toggleMenu('showOptionsMenu')"
)
.sk-label Options
.sk-menu-panel.dropdown-menu(ng-if='ctrl.showMenu')
.sk-menu-panel.dropdown-menu(ng-if='self.state.showOptionsMenu')
.sk-menu-panel-section
.sk-menu-panel-header
.sk-menu-panel-header-title Note Options
menu-row(action='ctrl.selectedMenuItem(true); ctrl.togglePin()', desc="'Pin or unpin a note from the top of your list'", label="ctrl.note.pinned ? 'Unpin' : 'Pin'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.toggleArchiveNote()', desc="'Archive or unarchive a note from your Archived system tag'", label="ctrl.note.archived ? 'Unarchive' : 'Archive'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.toggleLockNote()', desc="'Locking notes prevents unintentional editing'", label="ctrl.note.locked ? 'Unlock' : 'Lock'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.toggleProtectNote()', desc="'Protecting a note will require credentials to view it (Manage Privileges via Account menu)'", label="ctrl.note.content.protected ? 'Unprotect' : 'Protect'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.toggleNotePreview()', circle="ctrl.note.content.hidePreview ? 'danger' : 'success'", circle-align="'right'", desc="'Hide or unhide the note preview from the list of notes'", label="'Preview'")
menu-row(action='ctrl.selectedMenuItem(); ctrl.deleteNote()', desc="'Send this note to the trash'", label="'Move to Trash'", ng-show='!ctrl.altKeyDown && !ctrl.note.content.trashed && !ctrl.note.errorDecrypting', stylekit-class="'warning'")
menu-row(action='ctrl.selectedMenuItem(); ctrl.deleteNotePermanantely()', desc="'Delete this note permanently from all your devices'", label="'Delete Permanently'", ng-show='!ctrl.note.content.trashed && ctrl.note.errorDecrypting', stylekit-class="'danger'")
div(ng-if='ctrl.note.content.trashed || ctrl.altKeyDown')
menu-row(action='ctrl.selectedMenuItem(true); ctrl.restoreTrashedNote()', desc="'Undelete this note and restore it back into your notes'", label="'Restore'", ng-show='ctrl.note.content.trashed', stylekit-class="'info'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.deleteNotePermanantely()', desc="'Delete this note permanently from all your devices'", label="'Delete Permanently'", stylekit-class="'danger'")
menu-row(action='ctrl.selectedMenuItem(true); ctrl.emptyTrash()', desc="'Permanently delete all notes in the trash'", label="'Empty Trash'", ng-show='ctrl.note.content.trashed || !ctrl.altKeyDown', stylekit-class="'danger'", subtitle="ctrl.getTrashCount() + ' notes in trash'")
menu-row(
action='self.selectedMenuItem(true); self.togglePin()',
desc="'Pin or unpin a note from the top of your list'",
label="self.state.note.pinned ? 'Unpin' : 'Pin'"
)
menu-row(
action='self.selectedMenuItem(true); self.toggleArchiveNote()',
desc="'Archive or unarchive a note from your Archived system tag'",
label="self.state.note.archived ? 'Unarchive' : 'Archive'"
)
menu-row(
action='self.selectedMenuItem(true); self.toggleLockNote()',
desc="'Locking notes prevents unintentional editing'",
label="self.state.note.locked ? 'Unlock' : 'Lock'"
)
menu-row(
action='self.selectedMenuItem(true); self.toggleProtectNote()',
desc=`'Protecting a note will require credentials to view
it (Manage Privileges via Account menu)'`,
label="self.state.note.content.protected ? 'Unprotect' : 'Protect'"
)
menu-row(
action='self.selectedMenuItem(true); self.toggleNotePreview()',
circle="self.state.note.content.hidePreview ? 'danger' : 'success'",
circle-align="'right'",
desc="'Hide or unhide the note preview from the list of notes'",
label="'Preview'"
)
menu-row(
action='self.selectedMenuItem(); self.deleteNote()',
desc="'Send this note to the trash'",
label="'Move to Trash'",
ng-show='!self.state.altKeyDown && !self.state.note.content.trashed && !self.state.note.errorDecrypting',
stylekit-class="'warning'"
)
menu-row(
action='self.selectedMenuItem(); self.deleteNotePermanantely()',
desc="'Delete this note permanently from all your devices'",
label="'Delete Permanently'",
ng-show='!self.state.note.content.trashed && self.state.note.errorDecrypting',
stylekit-class="'danger'"
)
div(ng-if='self.state.note.content.trashed || self.state.altKeyDown')
menu-row(
action='self.selectedMenuItem(true); self.restoreTrashedNote()',
desc="'Undelete this note and restore it back into your notes'",
label="'Restore'",
ng-show='self.state.note.content.trashed',
stylekit-class="'info'"
)
menu-row(
action='self.selectedMenuItem(true); self.deleteNotePermanantely()',
desc="'Delete this note permanently from all your devices'",
label="'Delete Permanently'",
stylekit-class="'danger'"
)
menu-row(
action='self.selectedMenuItem(true); self.emptyTrash()',
desc="'Permanently delete all notes in the trash'",
label="'Empty Trash'",
ng-show='self.state.note.content.trashed || !self.state.altKeyDown',
stylekit-class="'danger'",
subtitle="self.getTrashCount() + ' notes in trash'"
)
.sk-menu-panel-section
.sk-menu-panel-header
.sk-menu-panel-header-title Global Display
menu-row(action="ctrl.selectedMenuItem(true); ctrl.toggleKey('monospaceFont')", circle="ctrl.monospaceFont ? 'success' : 'neutral'", desc="'Toggles the font style for the default editor'", disabled='ctrl.selectedEditor', label="'Monospace Font'", subtitle="ctrl.selectedEditor ? 'Not available with editor extensions' : null")
menu-row(action="ctrl.selectedMenuItem(true); ctrl.toggleKey('spellcheck')", circle="ctrl.spellcheck ? 'success' : 'neutral'", desc="'Toggles spellcheck for the default editor'", disabled='ctrl.selectedEditor', label="'Spellcheck'", subtitle="ctrl.selectedEditor ? 'Not available with editor extensions' : (ctrl.isDesktop ? 'May degrade editor performance' : null)")
menu-row(action="ctrl.selectedMenuItem(true); ctrl.toggleKey('marginResizersEnabled')", circle="ctrl.marginResizersEnabled ? 'success' : 'neutral'", desc="'Allows for editor left and right margins to be resized'", faded='!ctrl.marginResizersEnabled', label="'Margin Resizers'")
.sk-app-bar-item(click-outside='ctrl.showEditorMenu = false;', is-open='ctrl.showEditorMenu', ng-class="{'selected' : ctrl.showEditorMenu}", ng-click="ctrl.toggleMenu('showEditorMenu')")
menu-row(
action="self.selectedMenuItem(true); self.toggleKey(self.prefKeyMonospace)",
circle="self.state.monospaceEnabled ? 'success' : 'neutral'",
desc="'Toggles the font style for the default editor'",
disabled='self.state.selectedEditor',
label="'Monospace Font'",
subtitle="self.state.selectedEditor ? 'Not available with editor extensions' : null"
)
menu-row(
action="self.selectedMenuItem(true); self.toggleKey(self.prefKeySpellcheck)",
circle="self.state.spellcheck ? 'success' : 'neutral'",
desc="'Toggles spellcheck for the default editor'",
disabled='self.state.selectedEditor',
label="'Spellcheck'",
subtitle=`
self.state.selectedEditor
? 'Not available with editor extensions'
: (self.state.isDesktop ? 'May degrade editor performance' : null)
`)
menu-row(
action="self.selectedMenuItem(true); self.toggleKey(self.prefKeyMarginResizers)",
circle="self.state.marginResizersEnabled ? 'success' : 'neutral'",
desc="'Allows for editor left and right margins to be resized'",
faded='!self.state.marginResizersEnabled',
label="'Margin Resizers'"
)
.sk-app-bar-item(
click-outside=`self.setMenuState('showEditorMenu', false)`
is-open='self.state.showEditorMenu',
ng-class="{'selected' : self.state.showEditorMenu}",
ng-click="self.toggleMenu('showEditorMenu')"
)
.sk-label Editor
editor-menu(callback='ctrl.editorMenuOnSelect', current-item='ctrl.note', ng-if='ctrl.showEditorMenu', selected-editor='ctrl.selectedEditor')
.sk-app-bar-item(click-outside='ctrl.showExtensions = false;', is-open='ctrl.showExtensions', ng-class="{'selected' : ctrl.showExtensions}", ng-click="ctrl.toggleMenu('showExtensions')")
editor-menu(
callback='self.editorMenuOnSelect',
current-item='self.state.note',
ng-if='self.state.showEditorMenu',
selected-editor='self.state.selectedEditor'
)
.sk-app-bar-item(
click-outside=`self.setMenuState('showExtensions', false)`,
is-open='self.state.showExtensions',
ng-class="{'selected' : self.state.showExtensions}",
ng-click="self.toggleMenu('showExtensions')"
)
.sk-label Actions
actions-menu(item='ctrl.note', ng-if='ctrl.showExtensions')
.sk-app-bar-item(click-outside='ctrl.showSessionHistory = false;', is-open='ctrl.showSessionHistory', ng-click="ctrl.toggleMenu('showSessionHistory')")
actions-menu(
item='self.state.note',
ng-if='self.state.showExtensions'
)
.sk-app-bar-item(
click-outside=`self.setMenuState('showSessionHistory', false)`,
is-open='self.state.showSessionHistory',
ng-click="self.toggleMenu('showSessionHistory')"
)
.sk-label Session History
session-history-menu(item='ctrl.note', ng-if='ctrl.showSessionHistory')
#editor-content.editor-content(ng-if='ctrl.noteReady && !ctrl.note.errorDecrypting')
panel-resizer.left(control='ctrl.leftResizeControl', hoverable='true', min-width='300', ng-if='ctrl.marginResizersEnabled', on-resize-finish='ctrl.onPanelResizeFinish', panel-id="'editor-content'", property="'left'")
component-view.component-view(component='ctrl.selectedEditor', ng-if='ctrl.selectedEditor', on-load='ctrl.onEditorLoad')
textarea#note-text-editor.editable(dir='auto', ng-attr-spellcheck='{{ctrl.spellcheck}}', ng-change='ctrl.contentChanged()', ng-click='ctrl.clickedTextArea()', ng-focus='ctrl.onContentFocus()', ng-if='!ctrl.selectedEditor', ng-model='ctrl.note.text', ng-model-options='{ debounce: ctrl.EditorNgDebounce}', ng-readonly='ctrl.note.locked', ng-trim='false')
| {{ctrl.onSystemEditorLoad()}}
panel-resizer(control='ctrl.rightResizeControl', hoverable='true', min-width='300', ng-if='ctrl.marginResizersEnabled', on-resize-finish='ctrl.onPanelResizeFinish', panel-id="'editor-content'", property="'right'")
.section(ng-show='ctrl.note.errorDecrypting')
session-history-menu(
item='self.state.note',
ng-if='self.state.showSessionHistory'
)
#editor-content.editor-content(
ng-if='self.state.noteReady && !self.state.note.errorDecrypting'
)
panel-resizer.left(
control='self.leftResizeControl',
hoverable='true',
min-width='300',
ng-if='self.state.marginResizersEnabled',
on-resize-finish='self.onPanelResizeFinish',
panel-id="'editor-content'",
property="'left'"
)
component-view.component-view(
component='self.state.selectedEditor',
ng-if='self.state.selectedEditor',
on-load='self.onEditorLoad'
)
textarea#note-text-editor.editable(
dir='auto',
ng-attr-spellcheck='{{self.state.spellcheck}}',
ng-change='self.contentChanged()',
ng-click='self.clickedTextArea()',
ng-focus='self.onContentFocus()',
ng-if='!self.state.selectedEditor',
ng-model='self.state.note.text',
ng-model-options='{ debounce: self.state.editorDebounce}',
ng-readonly='self.state.note.locked',
ng-trim='false'
)
| {{self.onSystemEditorLoad()}}
panel-resizer(
control='self.rightResizeControl',
hoverable='true', min-width='300',
ng-if='self.state.marginResizersEnabled',
on-resize-finish='self.onPanelResizeFinish',
panel-id="'editor-content'",
property="'right'"
)
.section(ng-show='self.state.note.errorDecrypting')
p.medium-padding(style='padding-top: 0 !important;')
| There was an error decrypting this item. Ensure you are running the latest version of this app, then sign out and sign back in to try again.
#editor-pane-component-stack(ng-show='ctrl.note')
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='ctrl.componentStack.length')
| There was an error decrypting this item. Ensure you are running the
| latest version of this app, then sign out and sign back in to try again.
#editor-pane-component-stack(ng-show='self.state.note')
#component-stack-menu-bar.sk-app-bar.no-edges(ng-if='self.componentStack.length')
.left
.sk-app-bar-item(ng-click='ctrl.toggleStackComponentForCurrentItem(component)', ng-repeat='component in ctrl.componentStack')
.sk-app-bar-item(
ng-click='self.toggleStackComponentForCurrentItem(component)',
ng-repeat='component in self.componentStack'
)
.sk-app-bar-item-column
.sk-circle.small(ng-class="{'info' : !component.hidden && component.active, 'neutral' : component.hidden || !component.active}")
.sk-circle.small(
ng-class="{'info' : !component.hidden && component.active, 'neutral' : component.hidden || !component.active}"
)
.sk-app-bar-item-column
.sk-label {{component.name}}
.sn-component
component-view.component-view.component-stack-item(component='component', manual-dealloc='true', ng-if='component.active', ng-repeat='component in ctrl.componentStack', ng-show='!component.hidden')
component-view.component-view.component-stack-item(
component='component',
manual-dealloc='true',
ng-if='component.active',
ng-repeat='component in self.componentStack',
ng-show='!component.hidden'
)

View File

@@ -1,35 +1,68 @@
.sn-component
#footer-bar.sk-app-bar.no-edges.no-bottom-edge
.left
.sk-app-bar-item(click-outside='ctrl.clickOutsideAccountMenu()', is-open='ctrl.showAccountMenu', ng-click='ctrl.accountMenuPressed()')
.sk-app-bar-item(
click-outside='ctrl.clickOutsideAccountMenu()',
is-open='ctrl.showAccountMenu',
ng-click='ctrl.accountMenuPressed()'
)
.sk-app-bar-item-column
.sk-circle.small(ng-class="ctrl.error ? 'danger' : (ctrl.getUser() ? 'info' : 'neutral')")
.sk-circle.small(
ng-class="ctrl.error ? 'danger' : (ctrl.getUser() ? 'info' : 'neutral')"
)
.sk-app-bar-item-column
.sk-label.title(ng-class='{red: ctrl.error}') Account
account-menu(close-function='ctrl.closeAccountMenu', ng-click='$event.stopPropagation()', ng-if='ctrl.showAccountMenu', on-successful-auth='ctrl.onAuthSuccess')
account-menu(
close-function='ctrl.closeAccountMenu',
ng-click='$event.stopPropagation()',
ng-if='ctrl.showAccountMenu',
)
.sk-app-bar-item
a.no-decoration.sk-label.title(href='https://standardnotes.org/help', rel='noopener', target='_blank')
a.no-decoration.sk-label.title(
href='https://standardnotes.org/help',
rel='noopener',
target='_blank'
)
| Help
.sk-app-bar-item.border
.sk-app-bar-item(ng-repeat='room in ctrl.rooms track by room.uuid')
.sk-app-bar-item-column(ng-click='ctrl.selectRoom(room)')
.sk-label {{room.name}}
component-modal(component='room', ng-if='room.showRoom', on-dismiss='ctrl.onRoomDismiss')
component-modal(
component='room',
ng-if='room.showRoom',
on-dismiss='ctrl.onRoomDismiss'
)
.center
.sk-app-bar-item(ng-show='ctrl.arbitraryStatusMessage')
.sk-app-bar-item-column
span.neutral.sk-label {{ctrl.arbitraryStatusMessage}}
.right
.sk-app-bar-item(ng-click='ctrl.openSecurityUpdate()', ng-show='ctrl.securityUpdateAvailable')
.sk-app-bar-item(
ng-click='ctrl.openSecurityUpdate()',
ng-show='ctrl.securityUpdateAvailable'
)
span.success.sk-label Security update available.
.sk-app-bar-item(ng-click='ctrl.clickedNewUpdateAnnouncement()', ng-show='ctrl.newUpdateAvailable == true')
.sk-app-bar-item(
ng-click='ctrl.clickedNewUpdateAnnouncement()',
ng-show='ctrl.newUpdateAvailable == true'
)
span.info.sk-label New update available.
.sk-app-bar-item.no-pointer(ng-if='ctrl.lastSyncDate && !ctrl.isRefreshing')
.sk-app-bar-item.no-pointer(
ng-if='ctrl.lastSyncDate && !ctrl.isRefreshing'
)
.sk-label.subtle
| Last refreshed {{ctrl.lastSyncDate | appDateTime}}
.sk-app-bar-item(ng-click='ctrl.toggleSyncResolutionMenu()', ng-if='(ctrl.outOfSync && !ctrl.isRefreshing) || ctrl.showSyncResolution')
.sk-app-bar-item(
ng-click='ctrl.toggleSyncResolutionMenu()',
ng-if='(ctrl.outOfSync && !ctrl.isRefreshing) || ctrl.showSyncResolution'
)
.sk-label.warning(ng-if='ctrl.outOfSync') Potentially Out of Sync
sync-resolution-menu(close-function='ctrl.toggleSyncResolutionMenu', ng-click='$event.stopPropagation();', ng-if='ctrl.showSyncResolution')
sync-resolution-menu(
close-function='ctrl.toggleSyncResolutionMenu',
ng-click='$event.stopPropagation();',
ng-if='ctrl.showSyncResolution'
)
.sk-app-bar-item(ng-if='ctrl.lastSyncDate && ctrl.isRefreshing')
.sk-spinner.small
.sk-app-bar-item(ng-if='ctrl.offline')
@@ -38,12 +71,24 @@
.sk-label Refresh
.sk-app-bar-item.border(ng-if='ctrl.dockShortcuts.length > 0')
.sk-app-bar-item.dock-shortcut(ng-repeat='shortcut in ctrl.dockShortcuts')
.sk-app-bar-item-column(ng-class="{'underline': shortcut.component.active}", ng-click='ctrl.selectShortcut(shortcut)')
.sk-app-bar-item-column(
ng-class="{'underline': shortcut.component.active}",
ng-click='ctrl.selectShortcut(shortcut)'
)
.div(ng-if="shortcut.icon.type == 'circle'", title='{{shortcut.name}}')
.sk-circle.small(ng-style="{'background-color': shortcut.icon.background_color, 'border-color': shortcut.icon.border_color}")
.sk-circle.small(
ng-style="{'background-color': shortcut.icon.background_color, 'border-color': shortcut.icon.border_color}"
)
.div(ng-if="shortcut.icon.type == 'svg'", title='{{shortcut.name}}')
.svg-item(elem-ready='ctrl.initSvgForShortcut(shortcut)', ng-attr-id='dock-svg-{{shortcut.component.uuid}}')
.svg-item(
elem-ready='ctrl.initSvgForShortcut(shortcut)',
ng-attr-id='dock-svg-{{shortcut.component.uuid}}'
)
.sk-app-bar-item.border(ng-if='ctrl.hasPasscode()')
#lock-item.sk-app-bar-item(ng-click='ctrl.lockApp()', ng-if='ctrl.hasPasscode()', title='Locks application and wipes unencrypted data from memory.')
#lock-item.sk-app-bar-item(
ng-click='ctrl.lockApp()',
ng-if='ctrl.hasPasscode()',
title='Locks application and wipes unencrypted data from memory.'
)
.sk-label
i#footer-lock-icon.icon.ion-locked

View File

@@ -1,7 +0,0 @@
.main-ui-view(ng-class='platform')
lock-screen(ng-if='needsUnlock', on-success='onSuccessfulUnlock')
#app.app(ng-class='appClass', ng-if='!needsUnlock')
tags-panel(add-new='tagsAddNew', remove-tag='removeTag', save='tagsSave', selection-made='tagsSelectionMade')
notes-panel(add-new='notesAddNew', selection-made='notesSelectionMade', tag='selectedTag')
editor-panel(note='selectedNote', remove='deleteNote', update-tags='updateTagsForNote')
footer(ng-if='!needsUnlock')

View File

@@ -4,18 +4,31 @@
.sk-panel-header-title Passcode Required
.sk-panel-content
.sk-panel-section
form.sk-panel-form.sk-panel-row(ng-submit='submitPasscodeForm()')
form.sk-panel-form.sk-panel-row(ng-submit='ctrl.submitPasscodeForm($event)')
.sk-panel-column.stretch
input#passcode-input.center-text.sk-input.contrast(autocomplete='new-password', autofocus='true', ng-model='formData.passcode', placeholder='Enter Passcode', should-focus='true', sn-autofocus='true', type='password')
input#passcode-input.center-text.sk-input.contrast(
autocomplete='new-password',
autofocus='true',
ng-model='ctrl.formData.passcode',
placeholder='Enter Passcode',
should-focus='true',
sn-autofocus='true',
type='password'
)
.sk-button-group.stretch.sk-panel-row.form-submit
button.sk-button.info(type='submit')
.sk-label Unlock
.sk-panel-footer
#passcode-reset
a.sk-a.neutral(ng-click='forgotPasscode()', ng-if='!formData.showRecovery') Forgot?
div(ng-if='formData.showRecovery')
a.sk-a.neutral(
ng-click='ctrl.forgotPasscode()',
ng-if='!ctrl.formData.showRecovery'
) Forgot?
div(ng-if='ctrl.formData.showRecovery')
.sk-p
| If you forgot your local passcode, your only option is to clear your local data from this device
| and sign back in to your account.
| If you forgot your local passcode, your only option is to clear
| your local data from this device and sign back in to your account.
.sk-panel-row
a.sk-a.danger.center-text(ng-click='beginDeleteData()') Delete Local Data
a.sk-a.danger.center-text(
ng-click='ctrl.beginDeleteData()'
) Delete Local Data

View File

@@ -3,53 +3,149 @@
#notes-title-bar.section-title-bar
.padded
.section-title-bar-header
.title {{ctrl.panelTitle}}
.sk-button.contrast.wide(ng-click='ctrl.createNewNote()', title='Create a new note in the selected tag')
.title {{self.state.panelTitle}}
.sk-button.contrast.wide(
ng-click='self.createNewNote()',
title='Create a new note in the selected tag'
)
.sk-label
i.icon.ion-plus.add-button
.filter-section(role='search')
input#search-bar.filter-bar(lowercase='true', ng-blur='ctrl.onFilterEnter()', ng-change='ctrl.filterTextChanged()', ng-keyup='$event.keyCode == 13 && ctrl.onFilterEnter();', ng-model='ctrl.noteFilter.text', placeholder='Search', select-on-click='true', title='Searches notes in the currently selected tag')
#search-clear-button(ng-click='ctrl.clearFilterText();', ng-show='ctrl.noteFilter.text') ✕
input#search-bar.filter-bar(
lowercase='true',
ng-blur='self.onFilterEnter()',
ng-change='self.filterTextChanged()',
ng-keyup='$event.keyCode == 13 && self.onFilterEnter();',
ng-model='self.state.noteFilter.text',
placeholder='Search',
select-on-click='true',
title='Searches notes in the currently selected tag'
)
#search-clear-button(
ng-click='self.clearFilterText();',
ng-show='self.state.noteFilter.text'
) ✕
#notes-menu-bar.sn-component
.sk-app-bar.no-edges
.left
.sk-app-bar-item(ng-class="{'selected' : ctrl.showMenu}", ng-click='ctrl.showMenu = !ctrl.showMenu')
.sk-app-bar-item(
ng-class="{'selected' : self.state.mutable.showMenu}",
ng-click='self.state.mutable.showMenu = !self.state.mutable.showMenu'
)
.sk-app-bar-item-column
.sk-label
| Options
.sk-app-bar-item-column
.sk-sublabel {{ctrl.optionsSubtitle()}}
#notes-options-menu.sk-menu-panel.dropdown-menu(ng-show='ctrl.showMenu')
.sk-sublabel {{self.optionsSubtitle()}}
#notes-options-menu.sk-menu-panel.dropdown-menu(
ng-show='self.state.mutable.showMenu'
)
.sk-menu-panel-header
.sk-menu-panel-header-title Sort By
a.info.sk-h5(ng-click='ctrl.toggleReverseSort()')
| {{ctrl.sortReverse === true ? 'Disable Reverse Sort' : 'Enable Reverse Sort'}}
menu-row(action="ctrl.selectedMenuItem(); ctrl.selectedSortByCreated()" circle="ctrl.sortBy == 'created_at' && 'success'" desc="'Sort notes by newest first'" label="'Date Added'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.selectedSortByUpdated()" circle="ctrl.sortBy == 'client_updated_at' && 'success'" desc="'Sort notes with the most recently updated first'" label="'Date Modified'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.selectedSortByTitle()" circle="ctrl.sortBy == 'title' && 'success'" desc="'Sort notes alphabetically by their title'" label="'Title'")
a.info.sk-h5(ng-click='self.toggleReverseSort()')
| {{self.state.sortReverse === true ? 'Disable Reverse Sort' : 'Enable Reverse Sort'}}
menu-row(
action="self.selectedMenuItem(); self.selectedSortByCreated()"
circle="self.state.sortBy == 'created_at' && 'success'"
desc="'Sort notes by newest first'"
label="'Date Added'"
)
menu-row(
action="self.selectedMenuItem(); self.selectedSortByUpdated()"
circle="self.state.sortBy == 'client_updated_at' && 'success'"
desc="'Sort notes with the most recently updated first'"
label="'Date Modified'"
)
menu-row(
action="self.selectedMenuItem(); self.selectedSortByTitle()"
circle="self.state.sortBy == 'title' && 'success'"
desc="'Sort notes alphabetically by their title'"
label="'Title'"
)
.sk-menu-panel-section
.sk-menu-panel-header
.sk-menu-panel-header-title Display
menu-row(action="ctrl.selectedMenuItem(); ctrl.togglePrefKey('showArchived')" circle="ctrl.showArchived ? 'success' : 'danger'" desc="'Archived notes are usually hidden. You can explicitly show them with this option.'" faded="!ctrl.showArchived" label="'Archived Notes'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.togglePrefKey('hidePinned')" circle="ctrl.hidePinned ? 'danger' : 'success'" desc="'Pinned notes always appear on top. You can hide them temporarily with this option so you can focus on other notes in the list.'" faded="ctrl.hidePinned" label="'Pinned Notes'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.togglePrefKey('hideNotePreview')" circle="ctrl.hideNotePreview ? 'danger' : 'success'" desc="'Hide the note preview for a more condensed list of notes'" faded="ctrl.hideNotePreview" label="'Note Preview'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.togglePrefKey('hideDate')" circle="ctrl.hideDate ? 'danger' : 'success'" desc="'Hide the date displayed in each row'" faded="ctrl.hideDate" label="'Date'")
menu-row(action="ctrl.selectedMenuItem(); ctrl.togglePrefKey('hideTags')" circle="ctrl.hideTags ? 'danger' : 'success'" desc="'Hide the list of tags associated with each note'" faded="ctrl.hideTags" label="'Tags'")
menu-row(
action="self.selectedMenuItem(); self.togglePrefKey('showArchived')"
circle="self.state.showArchived ? 'success' : 'danger'"
desc=`'Archived notes are usually hidden.
You can explicitly show them with this option.'`
faded="!self.state.showArchived"
label="'Archived Notes'"
)
menu-row(
action="self.selectedMenuItem(); self.togglePrefKey('hidePinned')"
circle="self.state.hidePinned ? 'danger' : 'success'"
desc=`'Pinned notes always appear on top. You can hide them temporarily
with this option so you can focus on other notes in the list.'`
faded="self.state.hidePinned"
label="'Pinned Notes'"
)
menu-row(
action="self.selectedMenuItem(); self.togglePrefKey('hideNotePreview')"
circle="self.state.hideNotePreview ? 'danger' : 'success'"
desc="'Hide the note preview for a more condensed list of notes'"
faded="self.state.hideNotePreview"
label="'Note Preview'"
)
menu-row(
action="self.selectedMenuItem(); self.togglePrefKey('hideDate')"
circle="self.state.hideDate ? 'danger' : 'success'"
desc="'Hide the date displayed in each row'"
faded="self.state.hideDate"
label="'Date'"
)
menu-row(
action="self.selectedMenuItem(); self.togglePrefKey('hideTags')"
circle="self.state.hideTags ? 'danger' : 'success'"
desc="'Hide the list of tags associated with each note'"
faded="self.state.hideTags"
label="'Tags'"
)
.scrollable
#notes-scrollable.infinite-scroll(can-load='true', infinite-scroll='ctrl.paginate()', threshold='200')
.note(ng-class="{'selected' : ctrl.selectedNote == note}", ng-click='ctrl.selectNote(note, true)', ng-repeat='note in (ctrl.renderedNotes = (ctrl.notes | limitTo:ctrl.notesToDisplay)) track by note.uuid')
#notes-scrollable.infinite-scroll(
can-load='true',
infinite-scroll='self.paginate()',
threshold='200'
)
.note(
ng-class="{'selected' : self.state.selectedNote == note}",
ng-click='self.selectNote(note, true)',
ng-repeat='note in self.state.renderedNotes track by note.uuid'
)
.note-flags(ng-show='note.flags.length > 0')
.flag(ng-class='flag.class', ng-repeat='flag in note.flags')
.label {{flag.text}}
.name(ng-show='note.title')
| {{note.title}}
.note-preview(ng-if='!ctrl.hideNotePreview && !note.content.hidePreview && !note.content.protected')
.html-preview(ng-bind-html='note.content.preview_html', ng-show='note.content.preview_html')
.plain-preview(ng-show='!note.content.preview_html && note.content.preview_plain') {{note.content.preview_plain}}
.default-preview(ng-show='!note.content.preview_html && !note.content.preview_plain') {{note.text}}
.date.faded(ng-show='!ctrl.hideDate')
span(ng-show="ctrl.sortBy == 'client_updated_at'") Modified {{note.cachedUpdatedAtString || 'Now'}}
span(ng-show="ctrl.sortBy != 'client_updated_at'") {{note.cachedCreatedAtString || 'Now'}}
.note-preview(
ng-if=`
!self.state.hideNotePreview &&
!note.content.hidePreview &&
!note.content.protected`
)
.html-preview(
ng-bind-html='note.content.preview_html',
ng-show='note.content.preview_html'
)
.plain-preview(
ng-show='!note.content.preview_html && note.content.preview_plain'
) {{note.content.preview_plain}}
.default-preview(
ng-show='!note.content.preview_html && !note.content.preview_plain'
) {{note.text}}
.date.faded(ng-show='!self.state.hideDate')
span(ng-show="self.state.sortBy == 'client_updated_at'")
| Modified {{note.cachedUpdatedAtString || 'Now'}}
span(ng-show="self.state.sortBy != 'client_updated_at'")
| {{note.cachedCreatedAtString || 'Now'}}
.tags-string(ng-show='note.shouldShowTags')
.faded {{note.savedTagsString || note.tagsString()}}
panel-resizer(collapsable="true" control="ctrl.panelController" default-width="300" hoverable="true" on-resize-finish="ctrl.onPanelResize" panel-id="'notes-column'")
panel-resizer(
collapsable="true"
control="self.panelController"
default-width="300"
hoverable="true"
on-resize-finish="self.onPanelResize"
panel-id="'notes-column'"
)

View File

@@ -0,0 +1,18 @@
.main-ui-view(
ng-class='platform'
)
lock-screen(
ng-if='needsUnlock',
on-success='onSuccessfulUnlock'
)
#app.app(
ng-class='appClass',
ng-if='!needsUnlock'
)
tags-panel
notes-panel
editor-panel
footer(
ng-if='!needsUnlock'
)

View File

@@ -1,35 +1,64 @@
#tags-column.sn-component.section.tags(aria-label='Tags')
.component-view-container(ng-if='ctrl.component.active')
component-view.component-view(component='ctrl.component')
#tags-content.content(ng-if='!(ctrl.component && ctrl.component.active)')
.component-view-container(ng-if='self.component.active')
component-view.component-view(component='self.component')
#tags-content.content(ng-if='!(self.component && self.component.active)')
.tags-title-section.section-title-bar
.section-title-bar-header
.sk-h3.title
span.sk-bold Views
.sk-button.sk-secondary-contrast.wide(ng-click='ctrl.clickedAddNewTag()', title='Create a new tag')
.sk-button.sk-secondary-contrast.wide(
ng-click='self.clickedAddNewTag()',
title='Create a new tag'
)
.sk-label
i.icon.ion-plus.add-button
.scrollable
.infinite-scroll
.tag(ng-class="{'selected' : ctrl.selectedTag == tag, 'faded' : !tag.content.isAllTag}", ng-click='ctrl.selectTag(tag)', ng-repeat='tag in ctrl.smartTags')
.tag(
ng-class="{'selected' : self.state.selectedTag == tag, 'faded' : !tag.content.isAllTag}",
ng-click='self.selectTag(tag)',
ng-repeat='tag in self.state.smartTags'
)
.tag-info
input.title(ng-disabled='true', ng-model='tag.title')
.count(ng-show='tag.content.isAllTag') {{tag.cachedNoteCount}}
.count(ng-show='tag.content.isAllTag') {{self.state.noteCounts[tag.uuid]}}
.tags-title-section.section-title-bar
.section-title-bar-header
.sk-h3.title
span.sk-bold Tags
.tag(ng-class="{'selected' : ctrl.selectedTag == tag}", ng-click='ctrl.selectTag(tag)', ng-repeat='tag in ctrl.tags track by tag.uuid')
.tag(
ng-class="{'selected' : self.state.selectedTag == tag}",
ng-click='self.selectTag(tag)',
ng-repeat='tag in self.state.tags track by tag.uuid'
)
.tag-info
.tag-icon #
input.title(ng-attr-id='tag-{{tag.uuid}}', ng-blur='ctrl.saveTag($event, tag)', ng-change='ctrl.tagTitleDidChange(tag)', ng-class="{'editing' : ctrl.editingTag == tag}", ng-click='ctrl.selectTag(tag)', ng-keyup='$event.keyCode == 13 && $event.target.blur()', ng-model='tag.title', should-focus='ctrl.newTag || ctrl.editingTag == tag', sn-autofocus='true', spellcheck='false')
.count {{tag.cachedNoteCount}}
input.title(
ng-attr-id='tag-{{tag.uuid}}',
ng-blur='self.saveTag($event, tag)',
ng-change='self.tagTitleDidChange(tag)',
ng-class="{'editing' : self.state.editingTag == tag}",
ng-click='self.selectTag(tag)',
ng-keyup='$event.keyCode == 13 && $event.target.blur()',
ng-model='tag.title',
should-focus='self.state.newTag || self.state.editingTag == tag',
sn-autofocus='true',
spellcheck='false'
)
.count {{self.state.noteCounts[tag.uuid]}}
.danger.small-text.bold(ng-show='tag.content.conflict_of') Conflicted Copy
.danger.small-text.bold(ng-show='tag.errorDecrypting') Missing Keys
.menu(ng-show='ctrl.selectedTag == tag')
a.item(ng-click='ctrl.selectedRenameTag($event, tag)', ng-show='!ctrl.editingTag') Rename
a.item(ng-click='ctrl.saveTag($event, tag)', ng-show='ctrl.editingTag') Save
a.item(ng-click='ctrl.selectedDeleteTag(tag)') Delete
.no-tags-placeholder(ng-show='ctrl.tags.length == 0')
.menu(ng-show='self.state.selectedTag == tag')
a.item(ng-click='self.selectedRenameTag($event, tag)', ng-show='!self.state.editingTag') Rename
a.item(ng-click='self.saveTag($event, tag)', ng-show='self.state.editingTag') Save
a.item(ng-click='self.selectedDeleteTag(tag)') Delete
.no-tags-placeholder(ng-show='self.state.tags.length == 0')
| No tags. Create one using the add button above.
panel-resizer(collapsable='true', control='ctrl.panelController', default-width='150', hoverable='true', on-resize-finish='ctrl.onPanelResize', panel-id="'tags-column'")
panel-resizer(
collapsable='true',
control='self.panelController',
default-width='150',
hoverable='true',
on-resize-finish='self.onPanelResize',
panel-id="'tags-column'"
)