diff --git a/app/assets/icons/ic-account-circle.svg b/app/assets/icons/ic-account-circle.svg new file mode 100644 index 000000000..53abd5a94 --- /dev/null +++ b/app/assets/icons/ic-account-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/icons/ic-check-bold.svg b/app/assets/icons/ic-check-bold.svg index 82c81e896..01df89c32 100644 --- a/app/assets/icons/ic-check-bold.svg +++ b/app/assets/icons/ic-check-bold.svg @@ -1,3 +1,3 @@ - + diff --git a/app/assets/icons/ic-check.svg b/app/assets/icons/ic-check.svg index 93a4a4a42..ff64da1ba 100644 --- a/app/assets/icons/ic-check.svg +++ b/app/assets/icons/ic-check.svg @@ -1,3 +1,3 @@ - + diff --git a/app/assets/javascripts/components/AccountMenu/User.tsx b/app/assets/javascripts/components/AccountMenu/User.tsx index 07e5f58ac..1dc2b2af4 100644 --- a/app/assets/javascripts/components/AccountMenu/User.tsx +++ b/app/assets/javascripts/components/AccountMenu/User.tsx @@ -1,6 +1,5 @@ import { observer } from 'mobx-react-lite'; import { AppState } from '@/ui_models/app_state'; -import { PasswordWizardType } from '@/types'; import { WebApplication } from '@/ui_models/application'; import { User } from '@standardnotes/snjs/dist/@types/services/api/responses'; @@ -10,22 +9,12 @@ type Props = { } const User = observer(({ - appState, - application, - }: Props) => { - const { server, closeAccountMenu } = appState.accountMenu; + appState, + application, +}: Props) => { + const { server } = appState.accountMenu; const user = application.getUser(); - const openPasswordWizard = () => { - closeAccountMenu(); - application.presentPasswordWizard(PasswordWizardType.ChangePassword); - }; - - const openSessionsModal = () => { - closeAccountMenu(); - appState.openSessionsModal(); - }; - return (
{appState.sync.errorMessage && ( @@ -56,12 +45,6 @@ const User = observer(({
- - Change Password - - - Manage Sessions -
); }); diff --git a/app/assets/javascripts/components/AccountMenu/index.tsx b/app/assets/javascripts/components/AccountMenu/index.tsx index cf8c45b2f..14bdacecf 100644 --- a/app/assets/javascripts/components/AccountMenu/index.tsx +++ b/app/assets/javascripts/components/AccountMenu/index.tsx @@ -6,11 +6,6 @@ import { ConfirmSignoutContainer } from '@/components/ConfirmSignoutModal'; import Authentication from '@/components/AccountMenu/Authentication'; import Footer from '@/components/AccountMenu/Footer'; import User from '@/components/AccountMenu/User'; -import Encryption from '@/components/AccountMenu/Encryption'; -import Protections from '@/components/AccountMenu/Protections'; -import PasscodeLock from '@/components/AccountMenu/PasscodeLock'; -import DataBackup from '@/components/AccountMenu/DataBackup'; -import ErrorReporting from '@/components/AccountMenu/ErrorReporting'; import { useEffect } from 'preact/hooks'; type Props = { @@ -51,25 +46,12 @@ const AccountMenu = observer(({ application, appState }: Props) => { application={application} appState={appState} /> - {!showLogin && !showRegister && ( + {!showLogin && !showRegister && user && (
- {user && ( - - )} - - - - -
)} diff --git a/app/assets/javascripts/components/Button.tsx b/app/assets/javascripts/components/Button.tsx index 484983dde..6737c971e 100644 --- a/app/assets/javascripts/components/Button.tsx +++ b/app/assets/javascripts/components/Button.tsx @@ -9,9 +9,9 @@ const baseClass = `rounded px-4 py-1.75 font-bold text-sm fit-content`; type ButtonType = 'normal' | 'primary' | 'danger'; const buttonClasses: { [type in ButtonType]: string } = { - normal: `${baseClass} bg-default color-text border-solid border-gray-300 border-1 focus:bg-contrast hover:bg-contrast`, + normal: `${baseClass} bg-default color-text border-neutral border-solid border-gray-300 border-1 focus:bg-contrast hover:bg-contrast`, primary: `${baseClass} no-border bg-info color-info-contrast hover:brightness-130 focus:brightness-130`, - danger: `${baseClass} bg-default color-danger border-solid border-gray-300 border-1 focus:bg-contrast hover:bg-contrast`, + danger: `${baseClass} bg-default color-danger border-neutral border-solid border-gray-300 border-1 focus:bg-contrast hover:bg-contrast`, }; export const Button: FunctionComponent<{ diff --git a/app/assets/javascripts/components/DecoratedInput.tsx b/app/assets/javascripts/components/DecoratedInput.tsx index 9caeebfb1..fe3b67178 100644 --- a/app/assets/javascripts/components/DecoratedInput.tsx +++ b/app/assets/javascripts/components/DecoratedInput.tsx @@ -28,13 +28,13 @@ export const DecoratedInput: FunctionalComponent = ({ autocomplete = false, }) => { const baseClasses = - 'rounded py-1.5 px-3 text-input my-1 h-8 flex flex-row items-center'; + 'rounded py-1.5 px-3 text-input my-1 h-8 flex flex-row items-center bg-contrast'; const stateClasses = disabled - ? 'no-border bg-grey-5' + ? 'no-border' : 'border-solid border-1 border-gray-300'; const classes = `${baseClasses} ${stateClasses} ${className}`; - const inputBaseClasses = 'w-full no-border color-black focus:shadow-none'; + const inputBaseClasses = 'w-full no-border color-text focus:shadow-none bg-contrast'; const inputStateClasses = disabled ? 'overflow-ellipsis' : ''; return (
diff --git a/app/assets/javascripts/components/Icon.tsx b/app/assets/javascripts/components/Icon.tsx index bbd43d7f0..e72804ae2 100644 --- a/app/assets/javascripts/components/Icon.tsx +++ b/app/assets/javascripts/components/Icon.tsx @@ -28,6 +28,7 @@ import DownloadIcon from '../../icons/ic-download.svg'; import InfoIcon from '../../icons/ic-info.svg'; import CheckIcon from '../../icons/ic-check.svg'; import CheckBoldIcon from '../../icons/ic-check-bold.svg'; +import AccountCircleIcon from '../../icons/ic-account-circle.svg'; import { toDirective } from './utils'; import { FunctionalComponent } from 'preact'; @@ -61,7 +62,8 @@ const ICONS = { download: DownloadIcon, info: InfoIcon, check: CheckIcon, - "check-bold": CheckBoldIcon, + 'check-bold': CheckBoldIcon, + 'account-circle': AccountCircleIcon, }; export type IconType = keyof typeof ICONS; diff --git a/app/assets/javascripts/components/Input.tsx b/app/assets/javascripts/components/Input.tsx index 0955b632c..39fac5e08 100644 --- a/app/assets/javascripts/components/Input.tsx +++ b/app/assets/javascripts/components/Input.tsx @@ -11,9 +11,9 @@ export const Input: FunctionalComponent = ({ disabled = false, text, }) => { - const base = `rounded py-1.5 px-3 text-input my-1 h-8`; + const base = `rounded py-1.5 px-3 text-input my-1 h-8 bg-contrast`; const stateClasses = disabled - ? 'no-border bg-grey-5' + ? 'no-border' : 'border-solid border-1 border-gray-300'; const classes = `${base} ${stateClasses} ${className}`; return ( diff --git a/app/assets/javascripts/components/shared/ModalDialog.tsx b/app/assets/javascripts/components/shared/ModalDialog.tsx index c9eac7a8c..b7abb82a2 100644 --- a/app/assets/javascripts/components/shared/ModalDialog.tsx +++ b/app/assets/javascripts/components/shared/ModalDialog.tsx @@ -33,11 +33,11 @@ export const ModalDialogLabel: FunctionComponent<{ }> = ({ children, closeDialog }) => (
-
{children}
+
{children}
closeDialog()} /> @@ -61,11 +61,11 @@ export const ModalDialogButtons: FunctionComponent = ({ children }) => (
{children != undefined && Array.isArray(children) ? children.map((child, idx, arr) => ( - <> - {child} - {idx < arr.length - 1 ?
: undefined} - - )) + <> + {child} + {idx < arr.length - 1 ?
: undefined} + + )) : children}
diff --git a/app/assets/javascripts/preferences/PreferencesView.tsx b/app/assets/javascripts/preferences/PreferencesView.tsx index d9059a440..74839c310 100644 --- a/app/assets/javascripts/preferences/PreferencesView.tsx +++ b/app/assets/javascripts/preferences/PreferencesView.tsx @@ -1,7 +1,7 @@ import { RoundIconButton } from '@/components/RoundIconButton'; import { TitleBar, Title } from '@/components/TitleBar'; import { FunctionComponent } from 'preact'; -import { AccountPreferences, General, HelpAndFeedback, Security } from './panes'; +import { AccountPreferences, HelpAndFeedback, Listed, General, Security } from './panes'; import { observer } from 'mobx-react-lite'; import { PreferencesMenu } from './PreferencesMenu'; import { PreferencesMenuView } from './PreferencesMenuView'; @@ -41,7 +41,7 @@ const PaneSelector: FunctionComponent< /> ); case 'listed': - return null; + return ; case 'shortcuts': return null; case 'accessibility': diff --git a/app/assets/javascripts/preferences/components/Content.tsx b/app/assets/javascripts/preferences/components/Content.tsx index a754c3d4d..1b5bcc646 100644 --- a/app/assets/javascripts/preferences/components/Content.tsx +++ b/app/assets/javascripts/preferences/components/Content.tsx @@ -14,14 +14,15 @@ export const Text: FunctionComponent<{ className?: string }> = ({ }) =>

{children}

; const buttonClasses = `block bg-default color-text rounded border-solid \ -border-1 border-gray-300 px-4 py-1.75 font-bold text-sm fit-content mt-3 \ -focus:bg-contrast hover:bg-contrast `; +border-1 border-gray-300 px-4 py-1.75 font-bold text-sm fit-content \ +focus:bg-contrast hover:bg-contrast border-neutral`; -export const LinkButton: FunctionComponent<{ label: string; link: string }> = ({ - label, - link, -}) => ( - +export const LinkButton: FunctionComponent<{ + label: string; + link: string; + className?: string; +}> = ({ label, link, className }) => ( + {label} ); diff --git a/app/assets/javascripts/preferences/components/MenuItem.tsx b/app/assets/javascripts/preferences/components/MenuItem.tsx index fefc383ab..66b34d288 100644 --- a/app/assets/javascripts/preferences/components/MenuItem.tsx +++ b/app/assets/javascripts/preferences/components/MenuItem.tsx @@ -15,7 +15,7 @@ export const MenuItem: FunctionComponent = ({ onClick, }) => (
{ e.preventDefault(); onClick(); diff --git a/app/assets/javascripts/preferences/components/PreferencesPane.tsx b/app/assets/javascripts/preferences/components/PreferencesPane.tsx index f1a136884..3cea1daa1 100644 --- a/app/assets/javascripts/preferences/components/PreferencesPane.tsx +++ b/app/assets/javascripts/preferences/components/PreferencesPane.tsx @@ -1,7 +1,7 @@ import { FunctionComponent } from 'preact'; export const PreferencesPane: FunctionComponent = ({ children }) => ( -
+
{children != undefined && Array.isArray(children) diff --git a/app/assets/javascripts/preferences/panes/General.tsx b/app/assets/javascripts/preferences/panes/General.tsx index 2598b7a98..b4fa9ad8e 100644 --- a/app/assets/javascripts/preferences/panes/General.tsx +++ b/app/assets/javascripts/preferences/panes/General.tsx @@ -3,6 +3,7 @@ import { AppState } from '@/ui_models/app_state'; import { FunctionComponent } from 'preact'; import { PreferencesPane } from '../components'; import { ErrorReporting } from './general-segments'; +import { Tools } from './general-segments/Tools'; interface GeneralProps { appState: AppState; @@ -11,6 +12,7 @@ interface GeneralProps { export const General: FunctionComponent = (props) => ( + ); diff --git a/app/assets/javascripts/preferences/panes/HelpFeedback.tsx b/app/assets/javascripts/preferences/panes/HelpFeedback.tsx index 58063a33d..d2a1d0d19 100644 --- a/app/assets/javascripts/preferences/panes/HelpFeedback.tsx +++ b/app/assets/javascripts/preferences/panes/HelpFeedback.tsx @@ -52,7 +52,11 @@ export const HelpAndFeedback: FunctionComponent = () => ( Can’t find your question here? - + @@ -68,6 +72,7 @@ export const HelpAndFeedback: FunctionComponent = () => ( before advocating for a feature request. @@ -82,6 +87,7 @@ export const HelpAndFeedback: FunctionComponent = () => ( group for discussions on security, themes, editors and more. @@ -93,7 +99,7 @@ export const HelpAndFeedback: FunctionComponent = () => ( Send an email to help@standardnotes.com and we’ll sort it out. - + diff --git a/app/assets/javascripts/preferences/panes/Listed.tsx b/app/assets/javascripts/preferences/panes/Listed.tsx new file mode 100644 index 000000000..d1254c2af --- /dev/null +++ b/app/assets/javascripts/preferences/panes/Listed.tsx @@ -0,0 +1,116 @@ +import { + PreferencesGroup, + PreferencesPane, + PreferencesSegment, + Title, + Subtitle, + Text, + LinkButton, +} from '../components'; +import { observer } from 'mobx-react-lite'; +import { WebApplication } from '@/ui_models/application'; +import { ContentType, SNComponent } from '@standardnotes/snjs'; +import { SNItem } from '@standardnotes/snjs/dist/@types/models/core/item'; +import { useCallback, useEffect, useState } from 'preact/hooks'; +import { BlogItem } from './listed/BlogItem'; + +type Props = { + application: WebApplication; +}; + +export const Listed = observer(({ application }: Props) => { + const [items, setItems] = useState([]); + const [isDeleting, setIsDeleting] = useState(false); + + const reloadItems = useCallback(() => { + const components = application + .getItems(ContentType.ActionsExtension) + .filter( + (item) => (item as SNComponent).package_info?.name === 'Listed' + ) as SNComponent[]; + setItems(components); + }, [application]); + + useEffect(() => { + reloadItems(); + }, [reloadItems]); + + const disconnectListedBlog = (item: SNItem) => { + return new Promise((resolve, reject) => { + setIsDeleting(true); + application + .deleteItem(item) + .then(() => { + reloadItems(); + setIsDeleting(false); + resolve(true); + }) + .catch((err) => { + application.alertService.alert(err); + setIsDeleting(false); + console.error(err); + reject(err); + }); + }); + }; + + return ( + + {items.length > 0 && ( + + + + Your {items.length === 1 ? 'Blog' : 'Blogs'} on Listed + +
+ {items.map((item, index, array) => { + return ( + + ); + })} + + + )} + + + About Listed +
+ What is Listed? + + Listed is a free blogging platform that allows you to create a + public journal published directly from your notes.{' '} + + Learn more + + + + {items.length === 0 ? ( + + How to get started? + + First, you’ll need to sign up for Listed. Once you have your + Listed account, follow the instructions to connect it with your + Standard Notes account. + + + + ) : null} + + + ); +}); diff --git a/app/assets/javascripts/preferences/panes/general-segments/Tools.tsx b/app/assets/javascripts/preferences/panes/general-segments/Tools.tsx new file mode 100644 index 000000000..3cd46b114 --- /dev/null +++ b/app/assets/javascripts/preferences/panes/general-segments/Tools.tsx @@ -0,0 +1,86 @@ +import { HorizontalSeparator } from '@/components/shared/HorizontalSeparator'; +import { Switch } from '@/components/Switch'; +import { + PreferencesGroup, + PreferencesSegment, + Subtitle, + Text, + Title, +} from '@/preferences/components'; +import { WebApplication } from '@/ui_models/application'; +import { PrefKey } from '@standardnotes/snjs'; +import { observer } from 'mobx-react-lite'; +import { FunctionalComponent } from 'preact'; +import { useState } from 'preact/hooks'; + +type Props = { + application: WebApplication; +}; + +export const Tools: FunctionalComponent = observer( + ({ application }: Props) => { + const [monospaceFont, setMonospaceFont] = useState(() => + application.getPreference(PrefKey.EditorMonospaceEnabled) + ); + const [marginResizers, setMarginResizers] = useState(() => + application.getPreference(PrefKey.EditorResizersEnabled) + ); + const [spellcheck, setSpellcheck] = useState(() => + application.getPreference(PrefKey.EditorSpellcheck) + ); + + const toggleMonospaceFont = () => { + setMonospaceFont(!monospaceFont); + application.setPreference(PrefKey.EditorMonospaceEnabled, !monospaceFont); + }; + + const toggleMarginResizers = () => { + setMarginResizers(!marginResizers); + application.setPreference(PrefKey.EditorResizersEnabled, !marginResizers); + }; + + const toggleSpellcheck = () => { + setSpellcheck(!spellcheck); + application.setPreference(PrefKey.EditorSpellcheck, !spellcheck); + }; + + return ( + + + Tools +
+
+
+ Monospace Font + Toggles the font style in the Plain Text editor. +
+ +
+ +
+
+ Margin Resizers + Allows left and right editor margins to be resized. +
+ +
+ +
+
+ Spellcheck + + May degrade performance, especially with long notes. Available + in the Plain Text editor and most specialty editors. + +
+ +
+
+
+
+ ); + } +); diff --git a/app/assets/javascripts/preferences/panes/general-segments/index.ts b/app/assets/javascripts/preferences/panes/general-segments/index.ts index 619f11e36..dd28d7a2c 100644 --- a/app/assets/javascripts/preferences/panes/general-segments/index.ts +++ b/app/assets/javascripts/preferences/panes/general-segments/index.ts @@ -1 +1,2 @@ export * from './ErrorReporting'; +export * from './Tools'; diff --git a/app/assets/javascripts/preferences/panes/index.ts b/app/assets/javascripts/preferences/panes/index.ts index da5721469..56e97df76 100644 --- a/app/assets/javascripts/preferences/panes/index.ts +++ b/app/assets/javascripts/preferences/panes/index.ts @@ -1,4 +1,5 @@ export * from './HelpFeedback'; export * from './Security'; export * from './AccountPreferences'; +export * from './Listed'; export * from './General'; diff --git a/app/assets/javascripts/preferences/panes/listed/BlogItem.tsx b/app/assets/javascripts/preferences/panes/listed/BlogItem.tsx new file mode 100644 index 000000000..804a9c813 --- /dev/null +++ b/app/assets/javascripts/preferences/panes/listed/BlogItem.tsx @@ -0,0 +1,110 @@ +import { Button } from '@/components/Button'; +import { HorizontalSeparator } from '@/components/shared/HorizontalSeparator'; +import { LinkButton, Subtitle } from '@/preferences/components'; +import { WebApplication } from '@/ui_models/application'; +import { + Action, + ButtonType, + SNActionsExtension, + SNComponent, + SNItem, +} from '@standardnotes/snjs'; +import { FunctionalComponent } from 'preact'; +import { useEffect, useState } from 'preact/hooks'; + +type Props = { + item: SNComponent; + showSeparator: boolean; + disabled: boolean; + disconnect: (item: SNItem) => Promise; + application: WebApplication; +}; + +export const BlogItem: FunctionalComponent = ({ + item, + showSeparator, + disabled, + disconnect, + application, +}) => { + const [actions, setActions] = useState([]); + const [isLoadingActions, setIsLoadingActions] = useState(false); + const [isDisconnecting, setIsDisconnecting] = useState(false); + + useEffect(() => { + const loadActions = async () => { + setIsLoadingActions(true); + application.actionsManager + .loadExtensionInContextOfItem(item as SNActionsExtension, item) + .then((extension) => { + setActions(extension?.actions); + }) + .catch((err) => application.alertService.alert(err)) + .finally(() => { + setIsLoadingActions(false); + }); + }; + if (!actions || actions.length === 0) loadActions(); + }, [application.actionsManager, application.alertService, item, actions]); + + const handleDisconnect = () => { + setIsDisconnecting(true); + application.alertService + .confirm( + 'Disconnecting will result in loss of access to your blog. Ensure your Listed author key is backed up before uninstalling.', + `Disconnect blog "${item?.name}"?`, + 'Disconnect', + ButtonType.Danger + ) + .then(async (shouldDisconnect) => { + if (shouldDisconnect) { + await disconnect(item as SNItem); + } + }) + .catch((err) => { + console.error(err); + application.alertService.alert(err); + }) + .finally(() => { + setIsDisconnecting(false); + }); + }; + + return ( + <> + {item?.name} +
+ {isLoadingActions ? ( +
+ ) : null} + {actions && actions?.length > 0 ? ( + <> + action.label === 'Open Blog') + ?.url || '' + } + /> + action.label === 'Settings') + ?.url || '' + } + /> +
+ {showSeparator && } + + ); +}; diff --git a/app/assets/javascripts/preferences/panes/security-segments/Encryption.tsx b/app/assets/javascripts/preferences/panes/security-segments/Encryption.tsx index b4c9740fe..102af157c 100644 --- a/app/assets/javascripts/preferences/panes/security-segments/Encryption.tsx +++ b/app/assets/javascripts/preferences/panes/security-segments/Encryption.tsx @@ -15,7 +15,7 @@ const EncryptionEnabled: FunctionComponent<{ appState: AppState }> = observer(({ const archived = formatCount(count.archived, 'archived notes'); const deleted = formatCount(count.deleted, 'trashed notes'); - const checkIcon = ; + const checkIcon = ; const noteIcon = ; const tagIcon = ; const archiveIcon = ; diff --git a/app/assets/javascripts/preferences/panes/two-factor-auth/AuthAppInfoPopup.tsx b/app/assets/javascripts/preferences/panes/two-factor-auth/AuthAppInfoPopup.tsx index 612179c5d..2cfa766d0 100644 --- a/app/assets/javascripts/preferences/panes/two-factor-auth/AuthAppInfoPopup.tsx +++ b/app/assets/javascripts/preferences/panes/two-factor-auth/AuthAppInfoPopup.tsx @@ -16,9 +16,8 @@ const DisclosureIconButton: FunctionComponent<{ @@ -58,7 +57,7 @@ export const AuthAppInfoTooltip: FunctionComponent = () => { />
Some apps, like Google Authenticator, do not back up and restore diff --git a/app/assets/javascripts/preferences/panes/two-factor-auth/Bullet.tsx b/app/assets/javascripts/preferences/panes/two-factor-auth/Bullet.tsx index 86402fb3d..311e80517 100644 --- a/app/assets/javascripts/preferences/panes/two-factor-auth/Bullet.tsx +++ b/app/assets/javascripts/preferences/panes/two-factor-auth/Bullet.tsx @@ -3,5 +3,5 @@ import { FunctionComponent } from 'preact'; export const Bullet: FunctionComponent<{ className?: string }> = ({ className = '', }) => ( -
+
); diff --git a/app/assets/javascripts/views/editor/editor-view.pug b/app/assets/javascripts/views/editor/editor-view.pug index d0fe2249c..8c7724f55 100644 --- a/app/assets/javascripts/views/editor/editor-view.pug +++ b/app/assets/javascripts/views/editor/editor-view.pug @@ -59,42 +59,6 @@ .sn-component(ng-if='self.note') #editor-menu-bar.sk-app-bar.no-edges .left - .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='self.state.showOptionsMenu') - .sk-menu-panel-section - .sk-menu-panel-header - .sk-menu-panel-header-title Global Display - menu-row( - action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMonospace)" - circle="self.state.monospaceFont ? 'success' : 'neutral'", - desc="'Toggles the font style for the default editor'", - disabled='self.state.editorComponent', - label="'Monospace Font'", - subtitle="self.state.editorComponent ? 'Not available with editor extensions' : null" - ) - menu-row( - action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeySpellcheck)" - circle="self.state.spellcheck ? 'success' : 'neutral'", - desc="'Toggles spellcheck for the default editor'", - disabled='self.state.editorComponent', - label="'Spellcheck'", - subtitle=` - self.state.editorComponent - ? 'Not available with editor extensions' - : (self.state.isDesktop ? 'May degrade editor performance' : null) - `) - menu-row( - action="self.selectedMenuItem(true); self.toggleWebPrefKey(self.prefKeyMarginResizers)" - circle="self.state.marginResizersEnabled ? 'success' : 'neutral'", - desc="'Allows for editor left and right margins to be resized'", - label="'Margin Resizers'" - ) .sk-app-bar-item( click-outside=`self.setMenuState('showEditorMenu', false)` is-open='self.state.showEditorMenu', diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index 2c3e346af..9d6c282d8 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -1,6 +1,4 @@ -import { - STRING_SAVING_WHILE_DOCUMENT_HIDDEN, -} from './../../strings'; +import { STRING_SAVING_WHILE_DOCUMENT_HIDDEN } from './../../strings'; import { Editor } from '@/ui_models/editor'; import { WebApplication } from '@/ui_models/application'; import { PanelPuppet, WebDirective } from '@/types'; @@ -61,7 +59,6 @@ type EditorState = { isDesktop?: boolean; syncTakingTooLong: boolean; showActionsMenu: boolean; - showOptionsMenu: boolean; showEditorMenu: boolean; showHistoryMenu: boolean; spellcheck: boolean; @@ -202,7 +199,7 @@ class EditorViewCtrl extends PureViewCtrl { }); this.autorun(() => { this.setState({ - showProtectedWarning: this.appState.notes.showProtectedWarning + showProtectedWarning: this.appState.notes.showProtectedWarning, }); }); } @@ -216,7 +213,6 @@ class EditorViewCtrl extends PureViewCtrl { spellcheck: true, syncTakingTooLong: false, showActionsMenu: false, - showOptionsMenu: false, showEditorMenu: false, showHistoryMenu: false, noteStatus: undefined, @@ -272,11 +268,11 @@ class EditorViewCtrl extends PureViewCtrl { async handleEditorNoteChange() { this.cancelPendingSetStatus(); const note = this.editor.note; - const showProtectedWarning = note.protected && !this.application.hasProtectionSources(); + const showProtectedWarning = + note.protected && !this.application.hasProtectionSources(); this.setShowProtectedWarning(showProtectedWarning); await this.setState({ showActionsMenu: false, - showOptionsMenu: false, showEditorMenu: false, showHistoryMenu: false, noteStatus: undefined, @@ -364,12 +360,7 @@ class EditorViewCtrl extends PureViewCtrl { } closeAllMenus(exclude?: string) { - const allMenus = [ - 'showOptionsMenu', - 'showEditorMenu', - 'showActionsMenu', - 'showHistoryMenu', - ]; + const allMenus = ['showEditorMenu', 'showActionsMenu', 'showHistoryMenu']; const menuState: any = {}; for (const candidate of allMenus) { if (candidate !== exclude) { @@ -591,7 +582,7 @@ class EditorViewCtrl extends PureViewCtrl { } clickedTextArea() { - this.setMenuState('showOptionsMenu', false); + this.closeAllMenus(); } // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -607,12 +598,6 @@ class EditorViewCtrl extends PureViewCtrl { this.lastEditorFocusEventSource = undefined; } - selectedMenuItem(hide: boolean) { - if (hide) { - this.setMenuState('showOptionsMenu', false); - } - } - setShowProtectedWarning(show: boolean) { this.appState.notes.setShowProtectedWarning(show); } @@ -757,13 +742,10 @@ class EditorViewCtrl extends PureViewCtrl { /** @components */ registerComponentHandler() { - this.unregisterComponent = this.application.componentManager!.registerHandler( - { + this.unregisterComponent = + this.application.componentManager!.registerHandler({ identifier: 'editor', - areas: [ - ComponentArea.EditorStack, - ComponentArea.Editor, - ], + areas: [ComponentArea.EditorStack, ComponentArea.Editor], contextRequestHandler: (componentUuid) => { const currentEditor = this.state.editorComponent; if ( @@ -778,8 +760,7 @@ class EditorViewCtrl extends PureViewCtrl { this.closeAllMenus(); } }, - } - ); + }); } async reloadStackComponents() { @@ -809,9 +790,8 @@ class EditorViewCtrl extends PureViewCtrl { } async toggleStackComponentForCurrentItem(component: SNComponent) { - const hidden = this.application.componentManager!.isComponentHidden( - component - ); + const hidden = + this.application.componentManager!.isComponentHidden(component); if (hidden || !component.active) { this.application.componentManager!.setComponentHidden(component, false); await this.associateComponentWithCurrentNote(component); @@ -844,16 +824,14 @@ class EditorViewCtrl extends PureViewCtrl { } registerKeyboardShortcuts() { - this.removeTrashKeyObserver = this.application - .io - .addKeyObserver({ - key: KeyboardKey.Backspace, - notTags: ['INPUT', 'TEXTAREA'], - modifiers: [KeyboardModifier.Meta], - onKeyDown: () => { - this.deleteNote(false); - }, - }); + this.removeTrashKeyObserver = this.application.io.addKeyObserver({ + key: KeyboardKey.Backspace, + notTags: ['INPUT', 'TEXTAREA'], + modifiers: [KeyboardModifier.Meta], + onKeyDown: () => { + this.deleteNote(false); + }, + }); } setScrollPosition() { @@ -883,39 +861,37 @@ class EditorViewCtrl extends PureViewCtrl { const editor = document.getElementById( ElementIds.NoteTextEditor )! as HTMLInputElement; - this.removeTabObserver = this.application - .io - .addKeyObserver({ - element: editor, - key: KeyboardKey.Tab, - onKeyDown: (event) => { - if (document.hidden || this.note.locked || event.shiftKey) { - return; - } - event.preventDefault(); - /** Using document.execCommand gives us undo support */ - const insertSuccessful = document.execCommand( - 'insertText', - false, - '\t' - ); - if (!insertSuccessful) { - /** document.execCommand works great on Chrome/Safari but not Firefox */ - const start = editor.selectionStart!; - const end = editor.selectionEnd!; - const spaces = ' '; - /** Insert 4 spaces */ - editor.value = - editor.value.substring(0, start) + - spaces + - editor.value.substring(end); - /** Place cursor 4 spaces away from where the tab key was pressed */ - editor.selectionStart = editor.selectionEnd = start + 4; - } - this.editorValues.text = editor.value; - this.save(this.note, copyEditorValues(this.editorValues), true); - }, - }); + this.removeTabObserver = this.application.io.addKeyObserver({ + element: editor, + key: KeyboardKey.Tab, + onKeyDown: (event) => { + if (document.hidden || this.note.locked || event.shiftKey) { + return; + } + event.preventDefault(); + /** Using document.execCommand gives us undo support */ + const insertSuccessful = document.execCommand( + 'insertText', + false, + '\t' + ); + if (!insertSuccessful) { + /** document.execCommand works great on Chrome/Safari but not Firefox */ + const start = editor.selectionStart!; + const end = editor.selectionEnd!; + const spaces = ' '; + /** Insert 4 spaces */ + editor.value = + editor.value.substring(0, start) + + spaces + + editor.value.substring(end); + /** Place cursor 4 spaces away from where the tab key was pressed */ + editor.selectionStart = editor.selectionEnd = start + 4; + } + this.editorValues.text = editor.value; + this.save(this.note, copyEditorValues(this.editorValues), true); + }, + }); editor.addEventListener('scroll', this.setScrollPosition); editor.addEventListener('input', this.resetScrollPosition); diff --git a/app/assets/javascripts/views/footer/footer-view.pug b/app/assets/javascripts/views/footer/footer-view.pug index 6970a442d..a8d7183bf 100644 --- a/app/assets/javascripts/views/footer/footer-view.pug +++ b/app/assets/javascripts/views/footer/footer-view.pug @@ -1,28 +1,37 @@ .sn-component #footer-bar.sk-app-bar.no-edges.no-bottom-edge .left - .sk-app-bar-item( + .sk-app-bar-item.ml-0( click-outside='ctrl.clickOutsideAccountMenu()', is-open='ctrl.showAccountMenu', ng-click='ctrl.accountMenuPressed()' - ) - .sk-app-bar-item-column - .sk-circle.small( - ng-class="ctrl.hasError ? 'danger' : (ctrl.user ? 'info' : 'neutral')" + ) + .w-8.h-full.flex.items-center.justify-center.cursor-pointer.rounded-full( + ng-class="ctrl.showAccountMenu ? 'bg-border' : '' " + ) + .w-5.h-5( + ng-class="ctrl.hasError ? 'danger' : (ctrl.user ? 'info' : 'neutral')" ) - .sk-app-bar-item-column - .sk-label.title(ng-class='{red: ctrl.hasError}') Account + icon( + type="account-circle" + class-name="hover:color-info w-5 h-5 max-h-5" + ) account-menu( ng-click='$event.stopPropagation()', app-state='ctrl.appState' application='ctrl.application' ng-if='ctrl.showAccountMenu', ) - .sk-app-bar-item( + .sk-app-bar-item.ml-0-important( ng-click='ctrl.clickPreferences()' ng-if='ctrl.appState.enableUnfinishedFeatures' ) - .sk-label.title Preferences + .w-8.h-full.flex.items-center.justify-center.cursor-pointer + .h-5 + icon( + type="tune" + class-name="rounded hover:color-info" + ) .sk-app-bar-item a.no-decoration.sk-label.title( href='https://standardnotes.com/help', diff --git a/app/assets/stylesheets/_footer.scss b/app/assets/stylesheets/_footer.scss index eb2d65cb5..5b813b3e9 100644 --- a/app/assets/stylesheets/_footer.scss +++ b/app/assets/stylesheets/_footer.scss @@ -34,17 +34,6 @@ border-bottom: 2px solid var(--sn-stylekit-info-color); } } - - svg { - width: 12px; - height: 12px; - fill: var(--sn-stylekit-secondary-foreground-color); - - &:hover { - fill: var(--sn-stylekit-info-color) !important; - color: var(--sn-stylekit-info-color) !important; - } - } } #account-switcher-icon { diff --git a/app/assets/stylesheets/_main.scss b/app/assets/stylesheets/_main.scss index f57cc05db..b54211c3a 100644 --- a/app/assets/stylesheets/_main.scss +++ b/app/assets/stylesheets/_main.scss @@ -115,7 +115,7 @@ p { background-color: var(--sn-stylekit-background-color); } -$footer-height: 32px; +$footer-height: 2rem; #resizer-overlay { position: absolute; diff --git a/app/assets/stylesheets/_sn.scss b/app/assets/stylesheets/_sn.scss index c066f10b6..6ecdf4abe 100644 --- a/app/assets/stylesheets/_sn.scss +++ b/app/assets/stylesheets/_sn.scss @@ -154,6 +154,13 @@ @extend .font-bold; } +.ml-0-important { + margin-left: 0rem !important; +} + +.ml-3 { + margin-left: 0.75rem; +} .ml-4 { margin-left: 1rem; } @@ -222,10 +229,22 @@ min-height: 1.5rem; } +.max-h-5 { + max-height: 1.25rem; +} + .border-danger { border-color: var(--sn-stylekit-danger-color); } +.bg-inverted-default { + background-color: var(--sn-stylekit-contrast-foreground-color); +} + +.color-inverted-default { + color: var(--sn-stylekit-background-color); +} + .pt-1 { padding-top: 0.25rem; } @@ -256,3 +275,7 @@ padding-top: 2.25rem; padding-bottom: 2.25rem; } + +.select-none { + user-select: none; +} \ No newline at end of file diff --git a/package.json b/package.json index ab5ad7515..442f0aae2 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@reach/dialog": "^0.13.0", "@standardnotes/sncrypto-web": "1.5.2", "@standardnotes/features": "1.6.1", - "@standardnotes/snjs": "2.14.6", + "@standardnotes/snjs": "2.14.8", "mobx": "^6.3.2", "mobx-react-lite": "^3.2.0", "preact": "^10.5.12",