>
@@ -36,20 +34,6 @@ export abstract class PureComponent void): void {
this.reactionDisposers.push(autorun(view))
}
diff --git a/app/assets/javascripts/Components/AccountMenu/AccountMenu.tsx b/app/assets/javascripts/Components/AccountMenu/AccountMenu.tsx
index 400eff7d7..1e5d60069 100644
--- a/app/assets/javascripts/Components/AccountMenu/AccountMenu.tsx
+++ b/app/assets/javascripts/Components/AccountMenu/AccountMenu.tsx
@@ -2,15 +2,10 @@ import { observer } from 'mobx-react-lite'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/UIModels/Application'
-import { useCallback, useRef, useState } from 'preact/hooks'
-import { GeneralAccountMenu } from './GeneralAccountMenu'
-import { FunctionComponent } from 'preact'
-import { SignInPane } from './SignIn'
-import { CreateAccount } from './CreateAccount'
-import { ConfirmPassword } from './ConfirmPassword'
-import { JSXInternal } from 'preact/src/jsx'
+import { useCallback, useRef, FunctionComponent, KeyboardEventHandler } from 'react'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AccountMenuPane } from './AccountMenuPane'
+import MenuPaneSelector from './MenuPaneSelector'
type Props = {
appState: AppState
@@ -19,114 +14,61 @@ type Props = {
mainApplicationGroup: ApplicationGroup
}
-type PaneSelectorProps = {
- appState: AppState
- application: WebApplication
- mainApplicationGroup: ApplicationGroup
- menuPane: AccountMenuPane
- setMenuPane: (pane: AccountMenuPane) => void
- closeMenu: () => void
+const AccountMenu: FunctionComponent = ({ application, appState, onClickOutside, mainApplicationGroup }) => {
+ const { currentPane, shouldAnimateCloseMenu } = appState.accountMenu
+
+ const closeAccountMenu = useCallback(() => {
+ appState.accountMenu.closeAccountMenu()
+ }, [appState])
+
+ const setCurrentPane = useCallback(
+ (pane: AccountMenuPane) => {
+ appState.accountMenu.setCurrentPane(pane)
+ },
+ [appState],
+ )
+
+ const ref = useRef(null)
+ useCloseOnClickOutside(ref, () => {
+ onClickOutside()
+ })
+
+ const handleKeyDown: KeyboardEventHandler = useCallback(
+ (event) => {
+ switch (event.key) {
+ case 'Escape':
+ if (currentPane === AccountMenuPane.GeneralMenu) {
+ closeAccountMenu()
+ } else if (currentPane === AccountMenuPane.ConfirmPassword) {
+ setCurrentPane(AccountMenuPane.Register)
+ } else {
+ setCurrentPane(AccountMenuPane.GeneralMenu)
+ }
+ break
+ }
+ },
+ [closeAccountMenu, currentPane, setCurrentPane],
+ )
+
+ return (
+
+ )
}
-const MenuPaneSelector: FunctionComponent = observer(
- ({ application, appState, menuPane, setMenuPane, closeMenu, mainApplicationGroup }) => {
- const [email, setEmail] = useState('')
- const [password, setPassword] = useState('')
-
- switch (menuPane) {
- case AccountMenuPane.GeneralMenu:
- return (
-
- )
- case AccountMenuPane.SignIn:
- return
- case AccountMenuPane.Register:
- return (
-
- )
- case AccountMenuPane.ConfirmPassword:
- return (
-
- )
- }
- },
-)
-
-export const AccountMenu: FunctionComponent = observer(
- ({ application, appState, onClickOutside, mainApplicationGroup }) => {
- const { currentPane, shouldAnimateCloseMenu } = appState.accountMenu
-
- const closeAccountMenu = useCallback(() => {
- appState.accountMenu.closeAccountMenu()
- }, [appState])
-
- const setCurrentPane = useCallback(
- (pane: AccountMenuPane) => {
- appState.accountMenu.setCurrentPane(pane)
- },
- [appState],
- )
-
- const ref = useRef(null)
- useCloseOnClickOutside(ref, () => {
- onClickOutside()
- })
-
- const handleKeyDown: JSXInternal.KeyboardEventHandler = useCallback(
- (event) => {
- switch (event.key) {
- case 'Escape':
- if (currentPane === AccountMenuPane.GeneralMenu) {
- closeAccountMenu()
- } else if (currentPane === AccountMenuPane.ConfirmPassword) {
- setCurrentPane(AccountMenuPane.Register)
- } else {
- setCurrentPane(AccountMenuPane.GeneralMenu)
- }
- break
- }
- },
- [closeAccountMenu, currentPane, setCurrentPane],
- )
-
- return (
-
- )
- },
-)
+export default observer(AccountMenu)
diff --git a/app/assets/javascripts/Components/AccountMenu/AdvancedOptions.tsx b/app/assets/javascripts/Components/AccountMenu/AdvancedOptions.tsx
index 97b900d2a..a0d6bda88 100644
--- a/app/assets/javascripts/Components/AccountMenu/AdvancedOptions.tsx
+++ b/app/assets/javascripts/Components/AccountMenu/AdvancedOptions.tsx
@@ -1,11 +1,10 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useState } from 'preact/hooks'
-import { Checkbox } from '@/Components/Checkbox/Checkbox'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
-import { Icon } from '@/Components/Icon/Icon'
+import { ChangeEventHandler, FunctionComponent, useCallback, useEffect, useState } from 'react'
+import Checkbox from '@/Components/Checkbox/Checkbox'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
+import Icon from '@/Components/Icon/Icon'
type Props = {
application: WebApplication
@@ -15,170 +14,177 @@ type Props = {
onStrictSignInChange?: (isStrictSignIn: boolean) => void
}
-export const AdvancedOptions: FunctionComponent = observer(
- ({ appState, application, disabled = false, onPrivateWorkspaceChange, onStrictSignInChange, children }) => {
- const { server, setServer, enableServerOption, setEnableServerOption } = appState.accountMenu
- const [showAdvanced, setShowAdvanced] = useState(false)
+const AdvancedOptions: FunctionComponent = ({
+ appState,
+ application,
+ disabled = false,
+ onPrivateWorkspaceChange,
+ onStrictSignInChange,
+ children,
+}) => {
+ const { server, setServer, enableServerOption, setEnableServerOption } = appState.accountMenu
+ const [showAdvanced, setShowAdvanced] = useState(false)
- const [isPrivateWorkspace, setIsPrivateWorkspace] = useState(false)
- const [privateWorkspaceName, setPrivateWorkspaceName] = useState('')
- const [privateWorkspaceUserphrase, setPrivateWorkspaceUserphrase] = useState('')
+ const [isPrivateWorkspace, setIsPrivateWorkspace] = useState(false)
+ const [privateWorkspaceName, setPrivateWorkspaceName] = useState('')
+ const [privateWorkspaceUserphrase, setPrivateWorkspaceUserphrase] = useState('')
- const [isStrictSignin, setIsStrictSignin] = useState(false)
+ const [isStrictSignin, setIsStrictSignin] = useState(false)
- useEffect(() => {
- const recomputePrivateWorkspaceIdentifier = async () => {
- const identifier = await application.computePrivateWorkspaceIdentifier(
- privateWorkspaceName,
- privateWorkspaceUserphrase,
- )
+ useEffect(() => {
+ const recomputePrivateWorkspaceIdentifier = async () => {
+ const identifier = await application.computePrivateWorkspaceIdentifier(
+ privateWorkspaceName,
+ privateWorkspaceUserphrase,
+ )
- if (!identifier) {
- if (privateWorkspaceName?.length > 0 && privateWorkspaceUserphrase?.length > 0) {
- application.alertService.alert('Unable to compute private workspace name.').catch(console.error)
- }
- return
+ if (!identifier) {
+ if (privateWorkspaceName?.length > 0 && privateWorkspaceUserphrase?.length > 0) {
+ application.alertService.alert('Unable to compute private workspace name.').catch(console.error)
}
- onPrivateWorkspaceChange?.(true, identifier)
+ return
}
+ onPrivateWorkspaceChange?.(true, identifier)
+ }
- if (privateWorkspaceName && privateWorkspaceUserphrase) {
- recomputePrivateWorkspaceIdentifier().catch(console.error)
+ if (privateWorkspaceName && privateWorkspaceUserphrase) {
+ recomputePrivateWorkspaceIdentifier().catch(console.error)
+ }
+ }, [privateWorkspaceName, privateWorkspaceUserphrase, application, onPrivateWorkspaceChange])
+
+ useEffect(() => {
+ onPrivateWorkspaceChange?.(isPrivateWorkspace)
+ }, [isPrivateWorkspace, onPrivateWorkspaceChange])
+
+ const handleIsPrivateWorkspaceChange = useCallback(() => {
+ setIsPrivateWorkspace(!isPrivateWorkspace)
+ }, [isPrivateWorkspace])
+
+ const handlePrivateWorkspaceNameChange = useCallback((name: string) => {
+ setPrivateWorkspaceName(name)
+ }, [])
+
+ const handlePrivateWorkspaceUserphraseChange = useCallback((userphrase: string) => {
+ setPrivateWorkspaceUserphrase(userphrase)
+ }, [])
+
+ const handleServerOptionChange: ChangeEventHandler = useCallback(
+ (e) => {
+ if (e.target instanceof HTMLInputElement) {
+ setEnableServerOption(e.target.checked)
}
- }, [privateWorkspaceName, privateWorkspaceUserphrase, application, onPrivateWorkspaceChange])
+ },
+ [setEnableServerOption],
+ )
- useEffect(() => {
- onPrivateWorkspaceChange?.(isPrivateWorkspace)
- }, [isPrivateWorkspace, onPrivateWorkspaceChange])
+ const handleSyncServerChange = useCallback(
+ (server: string) => {
+ setServer(server)
+ application.setCustomHost(server).catch(console.error)
+ },
+ [application, setServer],
+ )
- const handleIsPrivateWorkspaceChange = useCallback(() => {
- setIsPrivateWorkspace(!isPrivateWorkspace)
- }, [isPrivateWorkspace])
+ const handleStrictSigninChange = useCallback(() => {
+ const newValue = !isStrictSignin
+ setIsStrictSignin(newValue)
+ onStrictSignInChange?.(newValue)
+ }, [isStrictSignin, onStrictSignInChange])
- const handlePrivateWorkspaceNameChange = useCallback((name: string) => {
- setPrivateWorkspaceName(name)
- }, [])
+ const toggleShowAdvanced = useCallback(() => {
+ setShowAdvanced(!showAdvanced)
+ }, [showAdvanced])
- const handlePrivateWorkspaceUserphraseChange = useCallback((userphrase: string) => {
- setPrivateWorkspaceUserphrase(userphrase)
- }, [])
+ return (
+ <>
+
+ {showAdvanced ? (
+
+ {children}
- const handleServerOptionChange = useCallback(
- (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setEnableServerOption(e.target.checked)
- }
- },
- [setEnableServerOption],
- )
-
- const handleSyncServerChange = useCallback(
- (server: string) => {
- setServer(server)
- application.setCustomHost(server).catch(console.error)
- },
- [application, setServer],
- )
-
- const handleStrictSigninChange = useCallback(() => {
- const newValue = !isStrictSignin
- setIsStrictSignin(newValue)
- onStrictSignInChange?.(newValue)
- }, [isStrictSignin, onStrictSignInChange])
-
- const toggleShowAdvanced = useCallback(() => {
- setShowAdvanced(!showAdvanced)
- }, [showAdvanced])
-
- return (
- <>
-
)
}
+
+export default EditingDisabledBanner
diff --git a/app/assets/javascripts/Components/NoteView/NoteView.test.ts b/app/assets/javascripts/Components/NoteView/NoteView.test.ts
index 2e6317cce..0ec6d0a1e 100644
--- a/app/assets/javascripts/Components/NoteView/NoteView.test.ts
+++ b/app/assets/javascripts/Components/NoteView/NoteView.test.ts
@@ -12,7 +12,7 @@ import {
SNNote,
} from '@standardnotes/snjs'
-import { NoteView } from './NoteView'
+import NoteView from './NoteView'
describe('NoteView', () => {
let noteViewController: NoteViewController
diff --git a/app/assets/javascripts/Components/NoteView/NoteView.tsx b/app/assets/javascripts/Components/NoteView/NoteView.tsx
index 7e44b11be..2be437fe7 100644
--- a/app/assets/javascripts/Components/NoteView/NoteView.tsx
+++ b/app/assets/javascripts/Components/NoteView/NoteView.tsx
@@ -1,4 +1,4 @@
-import { createRef, JSX, RefObject } from 'preact'
+import { ChangeEventHandler, createRef, KeyboardEventHandler, RefObject } from 'react'
import {
ApplicationEvent,
isPayloadSourceRetrieved,
@@ -19,16 +19,16 @@ import { KeyboardModifier, KeyboardKey } from '@/Services/IOService'
import { STRING_DELETE_PLACEHOLDER_ATTEMPT, STRING_DELETE_LOCKED_ATTEMPT, StringDeleteNote } from '@/Strings'
import { confirmDialog } from '@/Services/AlertService'
import { PureComponent } from '@/Components/Abstract/PureComponent'
-import { ProtectedNoteOverlay } from '@/Components/ProtectedNoteOverlay/ProtectedNoteOverlay'
-import { PinNoteButton } from '@/Components/PinNoteButton/PinNoteButton'
-import { NotesOptionsPanel } from '@/Components/NotesOptions/NotesOptionsPanel'
-import { NoteTagsContainer } from '@/Components/NoteTags/NoteTagsContainer'
-import { ComponentView } from '@/Components/ComponentView/ComponentView'
-import { PanelSide, PanelResizer, PanelResizeType } from '@/Components/PanelResizer/PanelResizer'
+import ProtectedNoteOverlay from '@/Components/ProtectedNoteOverlay/ProtectedNoteOverlay'
+import PinNoteButton from '@/Components/PinNoteButton/PinNoteButton'
+import NotesOptionsPanel from '@/Components/NotesOptions/NotesOptionsPanel'
+import NoteTagsContainer from '@/Components/NoteTags/NoteTagsContainer'
+import ComponentView from '@/Components/ComponentView/ComponentView'
+import PanelResizer, { PanelSide, PanelResizeType } from '@/Components/PanelResizer/PanelResizer'
import { ElementIds } from '@/ElementIDs'
-import { ChangeEditorButton } from '@/Components/ChangeEditor/ChangeEditorButton'
-import { AttachedFilesButton } from '@/Components/AttachedFilesPopover/AttachedFilesButton'
-import { EditingDisabledBanner } from './EditingDisabledBanner'
+import ChangeEditorButton from '@/Components/ChangeEditor/ChangeEditorButton'
+import AttachedFilesButton from '@/Components/AttachedFilesPopover/AttachedFilesButton'
+import EditingDisabledBanner from './EditingDisabledBanner'
import {
transactionForAssociateComponentWithCurrentNote,
transactionForDisassociateComponentWithCurrentNote,
@@ -78,7 +78,7 @@ type State = {
rightResizerOffset: number
}
-export class NoteView extends PureComponent {
+class NoteView extends PureComponent {
readonly controller!: NoteViewController
private statusTimeout?: NodeJS.Timeout
@@ -528,7 +528,7 @@ export class NoteView extends PureComponent {
}
}
- onTextAreaChange = ({ currentTarget }: JSX.TargetedEvent) => {
+ onTextAreaChange: ChangeEventHandler = ({ currentTarget }) => {
const text = currentTarget.value
this.setState({
editorText: text,
@@ -548,12 +548,16 @@ export class NoteView extends PureComponent {
.catch(console.error)
}
- onTitleEnter = ({ currentTarget }: JSX.TargetedEvent) => {
+ onTitleEnter: KeyboardEventHandler = ({ key, currentTarget }) => {
+ if (key !== KeyboardKey.Enter) {
+ return
+ }
+
currentTarget.blur()
this.focusEditor()
}
- onTitleChange = ({ currentTarget }: JSX.TargetedEvent) => {
+ onTitleChange: ChangeEventHandler = ({ currentTarget }) => {
const title = currentTarget.value
this.setState({
editorTitle: title,
@@ -911,12 +915,12 @@ export class NoteView extends PureComponent {
id={ElementIds.NoteTitleEditor}
onChange={this.onTitleChange}
onFocus={(event) => {
- ;(event.target as HTMLTextAreaElement).select()
+ event.target.select()
}}
- onKeyUp={(event) => event.keyCode == 13 && this.onTitleEnter(event)}
- spellcheck={false}
+ onKeyUp={this.onTitleEnter}
+ spellCheck={false}
value={this.state.editorTitle}
- autocomplete="off"
+ autoComplete="off"
/>
@@ -996,15 +1000,15 @@ export class NoteView extends PureComponent {
{this.state.editorStateDidLoad && !this.state.editorComponentViewer && !this.state.textareaUnloading && (
)}
@@ -1059,7 +1063,7 @@ export class NoteView extends PureComponent {
{this.state.stackComponentViewers.map((viewer) => {
return (
-
+
{
)
}
}
+
+export default NoteView
diff --git a/app/assets/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx b/app/assets/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx
index d3968d2ab..33f0a1be6 100644
--- a/app/assets/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx
+++ b/app/assets/javascripts/Components/NotesContextMenu/NotesContextMenu.tsx
@@ -2,8 +2,8 @@ import { AppState } from '@/UIModels/AppState'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { observer } from 'mobx-react-lite'
-import { NotesOptions } from '@/Components/NotesOptions/NotesOptions'
-import { useCallback, useEffect, useRef } from 'preact/hooks'
+import NotesOptions from '@/Components/NotesOptions/NotesOptions'
+import { useCallback, useEffect, useRef } from 'react'
import { WebApplication } from '@/UIModels/Application'
type Props = {
@@ -11,7 +11,7 @@ type Props = {
appState: AppState
}
-export const NotesContextMenu = observer(({ application, appState }: Props) => {
+const NotesContextMenu = ({ application, appState }: Props) => {
const { contextMenuOpen, contextMenuPosition, contextMenuMaxHeight } = appState.notes
const contextMenuRef = useRef(null)
@@ -42,4 +42,6 @@ export const NotesContextMenu = observer(({ application, appState }: Props) => {
) : null
-})
+}
+
+export default observer(NotesContextMenu)
diff --git a/app/assets/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx b/app/assets/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx
new file mode 100644
index 000000000..afd41da6d
--- /dev/null
+++ b/app/assets/javascripts/Components/NotesOptions/AccordionMenuGroup.tsx
@@ -0,0 +1,8 @@
+import { IconType } from '@standardnotes/snjs'
+
+export type AccordionMenuGroup
= {
+ icon?: IconType
+ iconClassName?: string
+ title: string
+ items: Array
+}
diff --git a/app/assets/javascripts/Components/NotesOptions/AddTagOption.tsx b/app/assets/javascripts/Components/NotesOptions/AddTagOption.tsx
index f409eb62a..1eb63d3f7 100644
--- a/app/assets/javascripts/Components/NotesOptions/AddTagOption.tsx
+++ b/app/assets/javascripts/Components/NotesOptions/AddTagOption.tsx
@@ -2,16 +2,15 @@ import { AppState } from '@/UIModels/AppState'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
-import { Icon } from '@/Components/Icon/Icon'
+import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type Props = {
appState: AppState
}
-export const AddTagOption: FunctionComponent = observer(({ appState }) => {
+const AddTagOption: FunctionComponent = ({ appState }) => {
const menuContainerRef = useRef(null)
const menuRef = useRef(null)
const menuButtonRef = useRef(null)
@@ -87,7 +86,7 @@ export const AddTagOption: FunctionComponent = observer(({ appState }) =>
>
{appState.tags.tags.map((tag) => (
{
@@ -108,4 +107,6 @@ export const AddTagOption: FunctionComponent = observer(({ appState }) =>
)
-})
+}
+
+export default observer(AddTagOption)
diff --git a/app/assets/javascripts/Components/NotesOptions/ChangeEditorOption.tsx b/app/assets/javascripts/Components/NotesOptions/ChangeEditorOption.tsx
index 344661488..4d6ab456e 100644
--- a/app/assets/javascripts/Components/NotesOptions/ChangeEditorOption.tsx
+++ b/app/assets/javascripts/Components/NotesOptions/ChangeEditorOption.tsx
@@ -2,11 +2,10 @@ import { KeyboardKey } from '@/Services/IOService'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
-import { IconType, SNComponent, SNNote } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
-import { Icon } from '@/Components/Icon/Icon'
-import { ChangeEditorMenu } from '@/Components/ChangeEditor/ChangeEditorMenu'
+import { SNNote } from '@standardnotes/snjs'
+import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
+import Icon from '@/Components/Icon/Icon'
+import ChangeEditorMenu from '@/Components/ChangeEditor/ChangeEditorMenu'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
@@ -16,22 +15,7 @@ type ChangeEditorOptionProps = {
note: SNNote
}
-type AccordionMenuGroup
= {
- icon?: IconType
- iconClassName?: string
- title: string
- items: Array
-}
-
-export type EditorMenuItem = {
- name: string
- component?: SNComponent
- isEntitled: boolean
-}
-
-export type EditorMenuGroup = AccordionMenuGroup
-
-export const ChangeEditorOption: FunctionComponent = ({ application, note }) => {
+const ChangeEditorOption: FunctionComponent = ({ application, note }) => {
const [isOpen, setIsOpen] = useState(false)
const [isVisible, setIsVisible] = useState(false)
const [menuStyle, setMenuStyle] = useState({
@@ -121,3 +105,5 @@ export const ChangeEditorOption: FunctionComponent = ({
)
}
+
+export default ChangeEditorOption
diff --git a/app/assets/javascripts/Components/NotesOptions/EditorMenuGroup.tsx b/app/assets/javascripts/Components/NotesOptions/EditorMenuGroup.tsx
new file mode 100644
index 000000000..cf541458b
--- /dev/null
+++ b/app/assets/javascripts/Components/NotesOptions/EditorMenuGroup.tsx
@@ -0,0 +1,4 @@
+import { EditorMenuItem } from './EditorMenuItem'
+import { AccordionMenuGroup } from './AccordionMenuGroup'
+
+export type EditorMenuGroup = AccordionMenuGroup
diff --git a/app/assets/javascripts/Components/NotesOptions/EditorMenuItem.tsx b/app/assets/javascripts/Components/NotesOptions/EditorMenuItem.tsx
new file mode 100644
index 000000000..d39a2850d
--- /dev/null
+++ b/app/assets/javascripts/Components/NotesOptions/EditorMenuItem.tsx
@@ -0,0 +1,7 @@
+import { SNComponent } from '@standardnotes/snjs'
+
+export type EditorMenuItem = {
+ name: string
+ component?: SNComponent
+ isEntitled: boolean
+}
diff --git a/app/assets/javascripts/Components/NotesOptions/ListedActionsOption.tsx b/app/assets/javascripts/Components/NotesOptions/ListedActionsOption.tsx
index 176bd9d4e..985bebb3c 100644
--- a/app/assets/javascripts/Components/NotesOptions/ListedActionsOption.tsx
+++ b/app/assets/javascripts/Components/NotesOptions/ListedActionsOption.tsx
@@ -2,9 +2,8 @@ import { WebApplication } from '@/UIModels/Application'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { Action, ListedAccount, SNNote } from '@standardnotes/snjs'
-import { Fragment, FunctionComponent } from 'preact'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
-import { Icon } from '@/Components/Icon/Icon'
+import { Fragment, FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type Props = {
@@ -206,7 +205,7 @@ const ListedActionsMenu: FunctionComponent = ({ applicat
)
}
-export const ListedActionsOption: FunctionComponent = ({ application, note }) => {
+const ListedActionsOption: FunctionComponent = ({ application, note }) => {
const menuContainerRef = useRef(null)
const menuRef = useRef(null)
const menuButtonRef = useRef(null)
@@ -273,3 +272,5 @@ export const ListedActionsOption: FunctionComponent = ({ application, not
)
}
+
+export default ListedActionsOption
diff --git a/app/assets/javascripts/Components/NotesOptions/NotesOptions.tsx b/app/assets/javascripts/Components/NotesOptions/NotesOptions.tsx
index 793f2d27d..0fbb9af06 100644
--- a/app/assets/javascripts/Components/NotesOptions/NotesOptions.tsx
+++ b/app/assets/javascripts/Components/NotesOptions/NotesOptions.tsx
@@ -1,23 +1,16 @@
import { AppState } from '@/UIModels/AppState'
-import { Icon } from '@/Components/Icon/Icon'
-import { Switch } from '@/Components/Switch/Switch'
+import Icon from '@/Components/Icon/Icon'
+import Switch from '@/Components/Switch/Switch'
import { observer } from 'mobx-react-lite'
-import { useState, useEffect, useMemo, useCallback } from 'preact/hooks'
+import { useState, useEffect, useMemo, useCallback, FunctionComponent } from 'react'
import { SNApplication, SNNote } from '@standardnotes/snjs'
-import { WebApplication } from '@/UIModels/Application'
import { KeyboardModifier } from '@/Services/IOService'
-import { FunctionComponent } from 'preact'
-import { ChangeEditorOption } from './ChangeEditorOption'
+import ChangeEditorOption from './ChangeEditorOption'
import { BYTES_IN_ONE_MEGABYTE } from '@/Constants'
-import { ListedActionsOption } from './ListedActionsOption'
-import { AddTagOption } from './AddTagOption'
+import ListedActionsOption from './ListedActionsOption'
+import AddTagOption from './AddTagOption'
import { addToast, dismissToast, ToastType } from '@standardnotes/stylekit'
-
-export type NotesOptionsProps = {
- application: WebApplication
- appState: AppState
- closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
-}
+import { NotesOptionsProps } from './NotesOptionsProps'
type DeletePermanentlyButtonProps = {
closeOnBlur: NotesOptionsProps['closeOnBlur']
@@ -176,7 +169,7 @@ const NoteSizeWarning: FunctionComponent<{
) : null
}
-export const NotesOptions = observer(({ application, appState, closeOnBlur }: NotesOptionsProps) => {
+const NotesOptions = ({ application, appState, closeOnBlur }: NotesOptionsProps) => {
const [altKeyDown, setAltKeyDown] = useState(false)
const toggleOn = (condition: (note: SNNote) => boolean) => {
@@ -440,4 +433,6 @@ export const NotesOptions = observer(({ application, appState, closeOnBlur }: No
) : null}
>
)
-})
+}
+
+export default observer(NotesOptions)
diff --git a/app/assets/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx b/app/assets/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx
index 33c26269b..23b0a50bc 100644
--- a/app/assets/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx
+++ b/app/assets/javascripts/Components/NotesOptions/NotesOptionsPanel.tsx
@@ -1,11 +1,11 @@
import { AppState } from '@/UIModels/AppState'
-import { Icon } from '@/Components/Icon/Icon'
+import Icon from '@/Components/Icon/Icon'
import VisuallyHidden from '@reach/visually-hidden'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
-import { useRef, useState } from 'preact/hooks'
+import { useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
-import { NotesOptions } from './NotesOptions'
+import NotesOptions from './NotesOptions'
import { WebApplication } from '@/UIModels/Application'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
@@ -15,7 +15,7 @@ type Props = {
onClickPreprocessing?: () => Promise
}
-export const NotesOptionsPanel = observer(({ application, appState, onClickPreprocessing }: Props) => {
+const NotesOptionsPanel = ({ application, appState, onClickPreprocessing }: Props) => {
const [open, setOpen] = useState(false)
const [position, setPosition] = useState({
top: 0,
@@ -83,4 +83,6 @@ export const NotesOptionsPanel = observer(({ application, appState, onClickPrepr
)
-})
+}
+
+export default observer(NotesOptionsPanel)
diff --git a/app/assets/javascripts/Components/NotesOptions/NotesOptionsProps.ts b/app/assets/javascripts/Components/NotesOptions/NotesOptionsProps.ts
new file mode 100644
index 000000000..2a969165c
--- /dev/null
+++ b/app/assets/javascripts/Components/NotesOptions/NotesOptionsProps.ts
@@ -0,0 +1,8 @@
+import { WebApplication } from '@/UIModels/Application'
+import { AppState } from '@/UIModels/AppState'
+
+export type NotesOptionsProps = {
+ application: WebApplication
+ appState: AppState
+ closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
+}
diff --git a/app/assets/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx b/app/assets/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx
index b5fa46311..c10ce1f16 100644
--- a/app/assets/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx
+++ b/app/assets/javascripts/Components/OtherSessionsSignOut/OtherSessionsSignOut.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useRef } from 'preact/hooks'
+import { useCallback, useRef } from 'react'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
@@ -9,13 +9,6 @@ type Props = {
appState: AppState
}
-export const OtherSessionsSignOutContainer = observer((props: Props) => {
- if (!props.appState.accountMenu.otherSessionsSignOut) {
- return null
- }
- return
-})
-
const ConfirmOtherSessionsSignOut = observer(({ application, appState }: Props) => {
const cancelRef = useRef(null)
@@ -65,3 +58,14 @@ const ConfirmOtherSessionsSignOut = observer(({ application, appState }: Props)
)
})
+
+ConfirmOtherSessionsSignOut.displayName = 'ConfirmOtherSessionsSignOut'
+
+const OtherSessionsSignOutContainer = (props: Props) => {
+ if (!props.appState.accountMenu.otherSessionsSignOut) {
+ return null
+ }
+ return
+}
+
+export default observer(OtherSessionsSignOutContainer)
diff --git a/app/assets/javascripts/Components/PanelResizer/PanelResizer.tsx b/app/assets/javascripts/Components/PanelResizer/PanelResizer.tsx
index d150bb6bd..6de7a49ab 100644
--- a/app/assets/javascripts/Components/PanelResizer/PanelResizer.tsx
+++ b/app/assets/javascripts/Components/PanelResizer/PanelResizer.tsx
@@ -1,4 +1,4 @@
-import { Component, createRef } from 'preact'
+import { Component, createRef, MouseEventHandler } from 'react'
import { debounce } from '@/Utils'
export type ResizeFinishCallback = (
@@ -38,7 +38,7 @@ type State = {
pressed: boolean
}
-export class PanelResizer extends Component {
+class PanelResizer extends Component {
private overlay?: HTMLDivElement
private resizerElementRef = createRef()
private debouncedResizeHandler: () => void
@@ -76,6 +76,10 @@ export class PanelResizer extends Component {
}
}
+ override componentDidMount() {
+ this.resizerElementRef.current?.addEventListener('dblclick', this.onDblClick)
+ }
+
override componentDidUpdate(prevProps: Props) {
if (this.props.width != prevProps.width) {
this.setWidth(this.props.width)
@@ -92,6 +96,7 @@ export class PanelResizer extends Component {
}
override componentWillUnmount() {
+ this.resizerElementRef.current?.removeEventListener('dblclick', this.onDblClick)
document.removeEventListener('mouseup', this.onMouseUp)
document.removeEventListener('mousemove', this.onMouseMove)
window.removeEventListener('resize', this.debouncedResizeHandler)
@@ -241,7 +246,7 @@ export class PanelResizer extends Component {
this.finishSettingWidth()
}
- onMouseDown = (event: MouseEvent) => {
+ onMouseDown: MouseEventHandler = (event) => {
this.addInvisibleOverlay()
this.lastDownX = event.clientX
this.startWidth = this.props.panel.scrollWidth
@@ -299,16 +304,17 @@ export class PanelResizer extends Component {
}
}
- render() {
+ override render() {
return (
)
}
}
+
+export default PanelResizer
diff --git a/app/assets/javascripts/Components/PasswordWizard/PasswordWizard.tsx b/app/assets/javascripts/Components/PasswordWizard/PasswordWizard.tsx
index ad020ccaa..2cb0d1180 100644
--- a/app/assets/javascripts/Components/PasswordWizard/PasswordWizard.tsx
+++ b/app/assets/javascripts/Components/PasswordWizard/PasswordWizard.tsx
@@ -1,9 +1,10 @@
import { WebApplication } from '@/UIModels/Application'
-import { createRef, JSX } from 'preact'
+import { ChangeEventHandler, createRef } from 'react'
import { PureComponent } from '@/Components/Abstract/PureComponent'
interface Props {
application: WebApplication
+ dismissModal: () => void
}
type State = {
@@ -31,7 +32,7 @@ type FormData = {
status?: string
}
-export class PasswordWizard extends PureComponent {
+class PasswordWizard extends PureComponent {
private currentPasswordInput = createRef()
constructor(props: Props) {
@@ -188,7 +189,7 @@ export class PasswordWizard extends PureComponent {
if (this.state.lockContinue) {
this.application.alertService.alert('Cannot close window until pending tasks are complete.').catch(console.error)
} else {
- this.dismissModal()
+ this.props.dismissModal()
}
}
@@ -201,19 +202,19 @@ export class PasswordWizard extends PureComponent {
})
}
- handleCurrentPasswordInputChange = ({ currentTarget }: JSX.TargetedEvent) => {
+ handleCurrentPasswordInputChange: ChangeEventHandler = ({ currentTarget }) => {
this.setFormDataState({
currentPassword: currentTarget.value,
}).catch(console.error)
}
- handleNewPasswordInputChange = ({ currentTarget }: JSX.TargetedEvent) => {
+ handleNewPasswordInputChange: ChangeEventHandler = ({ currentTarget }) => {
this.setFormDataState({
newPassword: currentTarget.value,
}).catch(console.error)
}
- handleNewPasswordConfirmationInputChange = ({ currentTarget }: JSX.TargetedEvent) => {
+ handleNewPasswordConfirmationInputChange: ChangeEventHandler = ({ currentTarget }) => {
this.setFormDataState({
newPasswordConfirmation: currentTarget.value,
}).catch(console.error)
@@ -310,3 +311,5 @@ export class PasswordWizard extends PureComponent {
)
}
}
+
+export default PasswordWizard
diff --git a/app/assets/javascripts/Components/PermissionsModal/PermissionsModal.tsx b/app/assets/javascripts/Components/PermissionsModal/PermissionsModal.tsx
index c9f146c57..0682c8960 100644
--- a/app/assets/javascripts/Components/PermissionsModal/PermissionsModal.tsx
+++ b/app/assets/javascripts/Components/PermissionsModal/PermissionsModal.tsx
@@ -1,45 +1,27 @@
import { WebApplication } from '@/UIModels/Application'
import { SNComponent } from '@standardnotes/snjs'
-import { Component } from 'preact'
-import { findDOMNode, unmountComponentAtNode } from 'preact/compat'
+import { Component } from 'react'
interface Props {
application: WebApplication
callback: (approved: boolean) => void
+ dismiss: () => void
component: SNComponent
permissionsString: string
}
-export class PermissionsModal extends Component {
- getElement(): Element | null {
- return findDOMNode(this)
- }
-
- dismiss = () => {
- const elem = this.getElement()
- if (!elem) {
- return
- }
-
- const parent = elem.parentElement
- if (!parent) {
- return
- }
- parent.remove()
- unmountComponentAtNode(parent)
- }
-
+class PermissionsModal extends Component {
accept = () => {
this.props.callback(true)
- this.dismiss()
+ this.props.dismiss()
}
deny = () => {
this.props.callback(false)
- this.dismiss()
+ this.props.dismiss()
}
- render() {
+ override render() {
return (
@@ -88,3 +70,5 @@ export class PermissionsModal extends Component
{
)
}
}
+
+export default PermissionsModal
diff --git a/app/assets/javascripts/Components/PermissionsModal/PermissionsModalWrapper.tsx b/app/assets/javascripts/Components/PermissionsModal/PermissionsModalWrapper.tsx
new file mode 100644
index 000000000..308074fff
--- /dev/null
+++ b/app/assets/javascripts/Components/PermissionsModal/PermissionsModalWrapper.tsx
@@ -0,0 +1,56 @@
+import { WebApplication } from '@/UIModels/Application'
+import { ApplicationEvent, PermissionDialog } from '@standardnotes/snjs'
+import { FunctionComponent, useCallback, useEffect, useState } from 'react'
+import PermissionsModal from './PermissionsModal'
+
+type Props = {
+ application: WebApplication
+}
+
+const PermissionsModalWrapper: FunctionComponent = ({ application }) => {
+ const [dialog, setDialog] = useState()
+
+ const presentPermissionsDialog = useCallback((permissionDialog: PermissionDialog) => {
+ setDialog(permissionDialog)
+ }, [])
+
+ const dismissPermissionsDialog = useCallback(() => {
+ setDialog(undefined)
+ }, [])
+
+ const onAppStart = useCallback(() => {
+ application.componentManager.presentPermissionsDialog = presentPermissionsDialog
+
+ return () => {
+ ;(application.componentManager.presentPermissionsDialog as unknown) = undefined
+ }
+ }, [application, presentPermissionsDialog])
+
+ useEffect(() => {
+ if (application.isStarted()) {
+ onAppStart()
+ }
+
+ const removeAppObserver = application.addEventObserver(async (eventName) => {
+ if (eventName === ApplicationEvent.Started) {
+ onAppStart()
+ }
+ })
+
+ return () => {
+ removeAppObserver()
+ }
+ }, [application, onAppStart])
+
+ return dialog ? (
+
+ ) : null
+}
+
+export default PermissionsModalWrapper
diff --git a/app/assets/javascripts/Components/PinNoteButton/PinNoteButton.tsx b/app/assets/javascripts/Components/PinNoteButton/PinNoteButton.tsx
index 75c5d9929..6738391a5 100644
--- a/app/assets/javascripts/Components/PinNoteButton/PinNoteButton.tsx
+++ b/app/assets/javascripts/Components/PinNoteButton/PinNoteButton.tsx
@@ -1,10 +1,8 @@
import { AppState } from '@/UIModels/AppState'
import VisuallyHidden from '@reach/visually-hidden'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { Icon } from '@/Components/Icon/Icon'
-import { useCallback } from 'preact/hooks'
-import { isStateDealloced } from '@/UIModels/AppState/AbstractState'
+import { FunctionComponent, useCallback } from 'react'
+import Icon from '@/Components/Icon/Icon'
type Props = {
appState: AppState
@@ -12,34 +10,27 @@ type Props = {
onClickPreprocessing?: () => Promise
}
-export const PinNoteButton: FunctionComponent = observer(
- ({ appState, className = '', onClickPreprocessing }: Props) => {
- if (isStateDealloced(appState)) {
- return null
+const PinNoteButton: FunctionComponent = ({ appState, className = '', onClickPreprocessing }: Props) => {
+ const notes = appState.notes.selectedNotes
+ const pinned = notes.some((note) => note.pinned)
+
+ const togglePinned = useCallback(async () => {
+ if (onClickPreprocessing) {
+ await onClickPreprocessing()
}
+ if (!pinned) {
+ appState.notes.setPinSelectedNotes(true)
+ } else {
+ appState.notes.setPinSelectedNotes(false)
+ }
+ }, [appState, onClickPreprocessing, pinned])
- const notes = appState.notes.selectedNotes
- const pinned = notes.some((note) => note.pinned)
+ return (
+
+ Pin selected notes
+
+
+ )
+}
- const togglePinned = useCallback(async () => {
- if (onClickPreprocessing) {
- await onClickPreprocessing()
- }
- if (!pinned) {
- appState.notes.setPinSelectedNotes(true)
- } else {
- appState.notes.setPinSelectedNotes(false)
- }
- }, [appState, onClickPreprocessing, pinned])
-
- return (
-
- Pin selected notes
-
-
- )
- },
-)
+export default observer(PinNoteButton)
diff --git a/app/assets/javascripts/Components/Preferences/PaneSelector.tsx b/app/assets/javascripts/Components/Preferences/PaneSelector.tsx
new file mode 100644
index 000000000..3452816da
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/PaneSelector.tsx
@@ -0,0 +1,60 @@
+import { FunctionComponent } from 'react'
+import { observer } from 'mobx-react-lite'
+import { PreferencesMenu } from './PreferencesMenu'
+import Backups from '@/Components/Preferences/Panes/Backups/Backups'
+import Appearance from './Panes/Appearance'
+import General from './Panes/General/General'
+import AccountPreferences from './Panes/Account/AccountPreferences'
+import Security from './Panes/Security/Security'
+import Listed from './Panes/Listed/Listed'
+import HelpAndFeedback from './Panes/HelpFeedback'
+import { PreferencesProps } from './PreferencesProps'
+
+const PaneSelector: FunctionComponent = ({
+ menu,
+ appState,
+ application,
+ mfaProvider,
+ userProvider,
+}) => {
+ switch (menu.selectedPaneId) {
+ case 'general':
+ return (
+
+ )
+ case 'account':
+ return
+ case 'appearance':
+ return
+ case 'security':
+ return (
+
+ )
+ case 'backups':
+ return
+ case 'listed':
+ return
+ case 'shortcuts':
+ return null
+ case 'accessibility':
+ return null
+ case 'get-free-month':
+ return null
+ case 'help-feedback':
+ return
+ default:
+ return (
+
+ )
+ }
+}
+
+export default observer(PaneSelector)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx
index bed91f9a0..6e832c9c9 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/AccountPreferences.tsx
@@ -1,20 +1,20 @@
-import { PreferencesPane } from '@/Components/Preferences/PreferencesComponents'
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
-import { Authentication } from './Authentication'
-import { Credentials } from './Credentials'
-import { Sync } from './Sync'
-import { Subscription } from './Subscription/Subscription'
-import { SignOutWrapper } from './SignOutView'
-import { FilesSection } from './Files'
+import Authentication from './Authentication'
+import Credentials from './Credentials'
+import Sync from './Sync'
+import Subscription from './Subscription/Subscription'
+import SignOutWrapper from './SignOutView'
+import FilesSection from './Files'
+import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
type Props = {
application: WebApplication
appState: AppState
}
-export const AccountPreferences = observer(({ application, appState }: Props) => (
+const AccountPreferences = ({ application, appState }: Props) => (
{!application.hasAccount() ? (
@@ -28,4 +28,6 @@ export const AccountPreferences = observer(({ application, appState }: Props) =>
{application.hasAccount() && appState.features.hasFiles && }
-))
+)
+
+export default observer(AccountPreferences)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Advanced.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Advanced.tsx
index ce00ff781..ed16a7af5 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Advanced.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Advanced.tsx
@@ -1,20 +1,21 @@
-import { FunctionalComponent } from 'preact'
-import { PreferencesGroup, PreferencesSegment } from '@/Components/Preferences/PreferencesComponents'
-import { OfflineSubscription } from '@/Components/Preferences/Panes/Account/OfflineSubscription'
+import { FunctionComponent } from 'react'
+import OfflineSubscription from '@/Components/Preferences/Panes/Account/OfflineSubscription'
import { WebApplication } from '@/UIModels/Application'
import { observer } from 'mobx-react-lite'
import { AppState } from '@/UIModels/AppState'
-import { Extensions } from '@/Components/Preferences/Panes/Extensions/Extensions'
+import Extensions from '@/Components/Preferences/Panes/Extensions/Extensions'
import { ExtensionsLatestVersions } from '@/Components/Preferences/Panes/Extensions/ExtensionsLatestVersions'
-import { AccordionItem } from '@/Components/Shared/AccordionItem'
+import AccordionItem from '@/Components/Shared/AccordionItem'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
-interface IProps {
+type Props = {
application: WebApplication
appState: AppState
extensionsLatestVersions: ExtensionsLatestVersions
}
-export const Advanced: FunctionalComponent = observer(({ application, appState, extensionsLatestVersions }) => {
+const Advanced: FunctionComponent = ({ application, appState, extensionsLatestVersions }) => {
return (
@@ -33,4 +34,6 @@ export const Advanced: FunctionalComponent = observer(({ application, ap
)
-})
+}
+
+export default observer(Advanced)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Authentication.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Authentication.tsx
index 4d40cb020..f12cb7628 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Authentication.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Authentication.tsx
@@ -1,16 +1,20 @@
-import { Button } from '@/Components/Button/Button'
-import { PreferencesGroup, PreferencesSegment, Text, Title } from '@/Components/Preferences/PreferencesComponents'
+import Button from '@/Components/Button/Button'
+import { Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { AccountIllustration } from '@standardnotes/icons'
import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
-export const Authentication: FunctionComponent<{
+type Props = {
application: WebApplication
appState: AppState
-}> = observer(({ appState }) => {
+}
+
+const Authentication: FunctionComponent = ({ appState }) => {
const clickSignIn = () => {
appState.preferences.closePreferences()
appState.accountMenu.setCurrentPane(AccountMenuPane.SignIn)
@@ -43,4 +47,6 @@ export const Authentication: FunctionComponent<{
)
-})
+}
+
+export default observer(Authentication)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail.tsx
index 4ca8e618a..217e6df42 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail.tsx
@@ -1,16 +1,13 @@
-import { useState } from '@node_modules/preact/hooks'
-import {
- ModalDialog,
- ModalDialogButtons,
- ModalDialogDescription,
- ModalDialogLabel,
-} from '@/Components/Shared/ModalDialog'
-import { Button } from '@/Components/Button/Button'
-import { FunctionalComponent } from 'preact'
+import ModalDialog from '@/Components/Shared/ModalDialog'
+import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons'
+import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
+import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
+import Button from '@/Components/Button/Button'
+import { FunctionComponent, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { useBeforeUnload } from '@/Hooks/useBeforeUnload'
-import { ChangeEmailForm } from './ChangeEmailForm'
-import { ChangeEmailSuccess } from './ChangeEmailSuccess'
+import ChangeEmailForm from './ChangeEmailForm'
+import ChangeEmailSuccess from './ChangeEmailSuccess'
import { isEmailValid } from '@/Utils'
enum SubmitButtonTitles {
@@ -29,7 +26,7 @@ type Props = {
application: WebApplication
}
-export const ChangeEmail: FunctionalComponent = ({ onCloseDialog, application }) => {
+const ChangeEmail: FunctionComponent = ({ onCloseDialog, application }) => {
const [currentPassword, setCurrentPassword] = useState('')
const [newEmail, setNewEmail] = useState('')
const [isContinuing, setIsContinuing] = useState(false)
@@ -158,3 +155,5 @@ export const ChangeEmail: FunctionalComponent = ({ onCloseDialog, applica
)
}
+
+export default ChangeEmail
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailForm.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailForm.tsx
index 6f94004b6..6526fdbb1 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailForm.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailForm.tsx
@@ -1,16 +1,15 @@
-import { StateUpdater } from 'preact/hooks'
-import { FunctionalComponent } from 'preact'
+import { Dispatch, SetStateAction, FunctionComponent } from 'react'
type Props = {
- setNewEmail: StateUpdater
- setCurrentPassword: StateUpdater
+ setNewEmail: Dispatch>
+ setCurrentPassword: Dispatch>
}
const labelClassName = 'block mb-1'
const inputClassName = 'sk-input contrast'
-export const ChangeEmailForm: FunctionalComponent = ({ setNewEmail, setCurrentPassword }) => {
+const ChangeEmailForm: FunctionComponent = ({ setNewEmail, setCurrentPassword }) => {
return (
@@ -42,3 +41,5 @@ export const ChangeEmailForm: FunctionalComponent
= ({ setNewEmail, setCu
)
}
+
+export default ChangeEmailForm
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailSuccess.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailSuccess.tsx
index 1e735eae0..f6ca3f81b 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailSuccess.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmailSuccess.tsx
@@ -1,6 +1,6 @@
-import { FunctionalComponent } from 'preact'
+import { FunctionComponent } from 'react'
-export const ChangeEmailSuccess: FunctionalComponent = () => {
+const ChangeEmailSuccess: FunctionComponent = () => {
return (
Your email has been successfully changed.
@@ -11,3 +11,5 @@ export const ChangeEmailSuccess: FunctionalComponent = () => {
)
}
+
+export default ChangeEmailSuccess
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx
new file mode 100644
index 000000000..da3764d50
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/ClearSessionDataView.tsx
@@ -0,0 +1,30 @@
+import Button from '@/Components/Button/Button'
+import { AppState } from '@/UIModels/AppState'
+import { observer } from 'mobx-react-lite'
+import { FunctionComponent } from 'react'
+import { Title, Text } from '../../PreferencesComponents/Content'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+
+const ClearSessionDataView: FunctionComponent<{
+ appState: AppState
+}> = ({ appState }) => {
+ return (
+
+
+ Clear workspace
+ Remove all data related to the current workspace from the application.
+
+ {
+ appState.accountMenu.setSigningOut(true)
+ }}
+ />
+
+
+ )
+}
+
+export default observer(ClearSessionDataView)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Credentials.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Credentials.tsx
index 05f35951e..4c30f0b00 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Credentials.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Credentials.tsx
@@ -1,28 +1,24 @@
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { observer } from '@node_modules/mobx-react-lite'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { dateToLocalizedString } from '@standardnotes/snjs'
-import { useCallback, useState } from 'preact/hooks'
-import { ChangeEmail } from '@/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail'
-import { FunctionComponent, render } from 'preact'
+import { useCallback, useState, FunctionComponent } from 'react'
+import ChangeEmail from '@/Components/Preferences/Panes/Account/ChangeEmail/ChangeEmail'
import { AppState } from '@/UIModels/AppState'
-import { PasswordWizard } from '@/Components/PasswordWizard/PasswordWizard'
+import PasswordWizard from '@/Components/PasswordWizard/PasswordWizard'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
}
-export const Credentials: FunctionComponent
= observer(({ application }: Props) => {
+const Credentials: FunctionComponent = ({ application }: Props) => {
const [isChangeEmailDialogOpen, setIsChangeEmailDialogOpen] = useState(false)
+ const [shouldShowPasswordWizard, setShouldShowPasswordWizard] = useState(false)
const user = application.getUser()
@@ -30,35 +26,46 @@ export const Credentials: FunctionComponent = observer(({ application }:
const passwordCreatedOn = dateToLocalizedString(passwordCreatedAtTimestamp)
const presentPasswordWizard = useCallback(() => {
- render(, document.body.appendChild(document.createElement('div')))
- }, [application])
+ setShouldShowPasswordWizard(true)
+ }, [])
+
+ const dismissPasswordWizard = useCallback(() => {
+ setShouldShowPasswordWizard(false)
+ }, [])
return (
-
-
- Credentials
- Email
-
- You're signed in as {user?.email}
-
- {
- setIsChangeEmailDialogOpen(true)
- }}
- />
-
- Password
-
- Current password was set on {passwordCreatedOn}
-
-
- {isChangeEmailDialogOpen && (
- setIsChangeEmailDialogOpen(false)} application={application} />
- )}
-
-
+ <>
+
+
+ Credentials
+ Email
+
+ You're signed in as {user?.email}
+
+ {
+ setIsChangeEmailDialogOpen(true)
+ }}
+ />
+
+ Password
+
+ Current password was set on {passwordCreatedOn}
+
+
+ {isChangeEmailDialogOpen && (
+ setIsChangeEmailDialogOpen(false)} application={application} />
+ )}
+
+
+ {shouldShowPasswordWizard ? (
+
+ ) : null}
+ >
)
-})
+}
+
+export default observer(Credentials)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Files.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Files.tsx
index c1e84e0ee..c9d6d1fb0 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Files.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Files.tsx
@@ -1,15 +1,16 @@
import { WebApplication } from '@/UIModels/Application'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { SubscriptionSettingName } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useEffect, useState } from 'preact/hooks'
-import { PreferencesGroup, PreferencesSegment, Subtitle, Title } from '../../PreferencesComponents'
+import { FunctionComponent, useEffect, useState } from 'react'
+import { Subtitle, Title } from '../../PreferencesComponents/Content'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const FilesSection: FunctionComponent = ({ application }) => {
+const FilesSection: FunctionComponent = ({ application }) => {
const [isLoading, setIsLoading] = useState(true)
const [filesQuotaUsed, setFilesQuotaUsed] = useState(0)
const [filesQuotaTotal, setFilesQuotaTotal] = useState(0)
@@ -63,3 +64,5 @@ export const FilesSection: FunctionComponent = ({ application }) => {
)
}
+
+export default FilesSection
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/OfflineSubscription.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/OfflineSubscription.tsx
index 6a2e3eca6..41cedb1e8 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/OfflineSubscription.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/OfflineSubscription.tsx
@@ -1,21 +1,20 @@
-import { FunctionalComponent } from 'preact'
-import { Subtitle } from '@/Components/Preferences/PreferencesComponents'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
-import { Button } from '@/Components/Button/Button'
-import { useEffect, useState } from 'preact/hooks'
+import React, { FunctionComponent, useEffect, useState } from 'react'
+import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
import { STRING_REMOVE_OFFLINE_KEY_CONFIRMATION } from '@/Strings'
import { ButtonType, ClientDisplayableError } from '@standardnotes/snjs'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
-interface IProps {
+type Props = {
application: WebApplication
appState: AppState
}
-export const OfflineSubscription: FunctionalComponent = observer(({ application }) => {
+const OfflineSubscription: FunctionComponent = ({ application }) => {
const [activationCode, setActivationCode] = useState('')
const [isSuccessfullyActivated, setIsSuccessfullyActivated] = useState(false)
const [isSuccessfullyRemoved, setIsSuccessfullyRemoved] = useState(false)
@@ -31,7 +30,7 @@ export const OfflineSubscription: FunctionalComponent = observer(({ appl
return !application.hasAccount() || application.isThirdPartyHostUsed() || hasUserPreviouslyStoredCode
}
- const handleSubscriptionCodeSubmit = async (event: Event) => {
+ const handleSubscriptionCodeSubmit = async (event: React.FormEvent) => {
event.preventDefault()
const result = await application.features.setOfflineFeaturesCode(activationCode)
@@ -123,4 +122,6 @@ export const OfflineSubscription: FunctionalComponent = observer(({ appl
>
)
-})
+}
+
+export default observer(OfflineSubscription)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx
index 94cef1db1..95a70c5eb 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/SignOutView.tsx
@@ -1,21 +1,21 @@
-import { Button } from '@/Components/Button/Button'
-import { OtherSessionsSignOutContainer } from '@/Components/OtherSessionsSignOut/OtherSessionsSignOut'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
+import Button from '@/Components/Button/Button'
+import OtherSessionsSignOutContainer from '@/Components/OtherSessionsSignOut/OtherSessionsSignOut'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
+import { Subtitle, Title, Text } from '../../PreferencesComponents/Content'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+import ClearSessionDataView from './ClearSessionDataView'
-const SignOutView: FunctionComponent<{
+type Props = {
application: WebApplication
appState: AppState
-}> = observer(({ application, appState }) => {
+}
+
+const SignOutView: FunctionComponent = observer(({ application, appState }) => {
return (
<>
@@ -36,6 +36,7 @@ const SignOutView: FunctionComponent<{
appState.openSessionsModal()} />
+
This workspace
Remove all data related to the current workspace from the application.
@@ -54,33 +55,13 @@ const SignOutView: FunctionComponent<{
)
})
-const ClearSessionDataView: FunctionComponent<{
- appState: AppState
-}> = observer(({ appState }) => {
- return (
-
-
- Clear workspace
- Remove all data related to the current workspace from the application.
-
- {
- appState.accountMenu.setSigningOut(true)
- }}
- />
-
-
- )
-})
+SignOutView.displayName = 'SignOutView'
-export const SignOutWrapper: FunctionComponent<{
- application: WebApplication
- appState: AppState
-}> = observer(({ application, appState }) => {
+const SignOutWrapper: FunctionComponent = ({ application, appState }) => {
if (!application.hasAccount()) {
return
}
return
-})
+}
+
+export default observer(SignOutWrapper)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/NoSubscription.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/NoSubscription.tsx
index 00e47b253..45440773a 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/NoSubscription.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/NoSubscription.tsx
@@ -1,13 +1,14 @@
-import { FunctionalComponent } from 'preact'
-import { LinkButton, Text } from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import { FunctionComponent, useState } from 'react'
+import { LinkButton, Text } from '@/Components/Preferences/PreferencesComponents/Content'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
-import { useState } from 'preact/hooks'
import { loadPurchaseFlowUrl } from '@/Components/PurchaseFlow/PurchaseFlowFunctions'
-export const NoSubscription: FunctionalComponent<{
+type Props = {
application: WebApplication
-}> = ({ application }) => {
+}
+
+const NoSubscription: FunctionComponent = ({ application }) => {
const [isLoadingPurchaseFlow, setIsLoadingPurchaseFlow] = useState(false)
const [purchaseFlowError, setPurchaseFlowError] = useState(undefined)
@@ -39,3 +40,5 @@ export const NoSubscription: FunctionalComponent<{
>
)
}
+
+export default NoSubscription
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/StatusText.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/StatusText.tsx
new file mode 100644
index 000000000..38825fca8
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/StatusText.tsx
@@ -0,0 +1,61 @@
+import { SubscriptionState } from '@/UIModels/AppState/SubscriptionState'
+import { observer } from 'mobx-react-lite'
+import { Text } from '@/Components/Preferences/PreferencesComponents/Content'
+
+type Props = { subscriptionState: SubscriptionState }
+
+const StatusText = ({ subscriptionState }: Props) => {
+ const {
+ userSubscriptionName,
+ userSubscriptionExpirationDate,
+ isUserSubscriptionExpired,
+ isUserSubscriptionCanceled,
+ } = subscriptionState
+ const expirationDateString = userSubscriptionExpirationDate?.toLocaleString()
+
+ if (isUserSubscriptionCanceled) {
+ return (
+
+ Your{' '}
+
+ Standard Notes{userSubscriptionName ? ' ' : ''}
+ {userSubscriptionName}
+ {' '}
+ subscription has been canceled{' '}
+ {isUserSubscriptionExpired ? (
+ and expired on {expirationDateString}
+ ) : (
+ but will remain valid until {expirationDateString}
+ )}
+ . You may resubscribe below if you wish.
+
+ )
+ }
+
+ if (isUserSubscriptionExpired) {
+ return (
+
+ Your{' '}
+
+ Standard Notes{userSubscriptionName ? ' ' : ''}
+ {userSubscriptionName}
+ {' '}
+ subscription expired on {expirationDateString}. You may resubscribe below if
+ you wish.
+
+ )
+ }
+
+ return (
+
+ Your{' '}
+
+ Standard Notes{userSubscriptionName ? ' ' : ''}
+ {userSubscriptionName}
+ {' '}
+ subscription will be renewed on {expirationDateString}.
+
+ )
+}
+
+export default observer(StatusText)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx
index d680c9328..38cb941ca 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/Subscription.tsx
@@ -1,17 +1,19 @@
-import { PreferencesGroup, PreferencesSegment, Title } from '@/Components/Preferences/PreferencesComponents'
+import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
-import { SubscriptionInformation } from './SubscriptionInformation'
-import { NoSubscription } from './NoSubscription'
+import SubscriptionInformation from './SubscriptionInformation'
+import NoSubscription from './NoSubscription'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { AppState } from '@/UIModels/AppState'
+import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
}
-export const Subscription: FunctionComponent = observer(({ application, appState }: Props) => {
+const Subscription: FunctionComponent = ({ application, appState }: Props) => {
const subscriptionState = appState.subscription
const { userSubscription } = subscriptionState
@@ -33,4 +35,6 @@ export const Subscription: FunctionComponent = observer(({ application, a
)
-})
+}
+
+export default observer(Subscription)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionInformation.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionInformation.tsx
index 0d2e24494..7344ab22d 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionInformation.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Subscription/SubscriptionInformation.tsx
@@ -1,70 +1,16 @@
import { observer } from 'mobx-react-lite'
import { SubscriptionState } from '@/UIModels/AppState/SubscriptionState'
-import { Text } from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
+import StatusText from './StatusText'
type Props = {
subscriptionState: SubscriptionState
application: WebApplication
}
-const StatusText = observer(({ subscriptionState }: { subscriptionState: Props['subscriptionState'] }) => {
- const {
- userSubscriptionName,
- userSubscriptionExpirationDate,
- isUserSubscriptionExpired,
- isUserSubscriptionCanceled,
- } = subscriptionState
- const expirationDateString = userSubscriptionExpirationDate?.toLocaleString()
-
- if (isUserSubscriptionCanceled) {
- return (
-
- Your{' '}
-
- Standard Notes{userSubscriptionName ? ' ' : ''}
- {userSubscriptionName}
- {' '}
- subscription has been canceled{' '}
- {isUserSubscriptionExpired ? (
- and expired on {expirationDateString}
- ) : (
- but will remain valid until {expirationDateString}
- )}
- . You may resubscribe below if you wish.
-
- )
- }
-
- if (isUserSubscriptionExpired) {
- return (
-
- Your{' '}
-
- Standard Notes{userSubscriptionName ? ' ' : ''}
- {userSubscriptionName}
- {' '}
- subscription expired on {expirationDateString}. You may resubscribe below if
- you wish.
-
- )
- }
-
- return (
-
- Your{' '}
-
- Standard Notes{userSubscriptionName ? ' ' : ''}
- {userSubscriptionName}
- {' '}
- subscription will be renewed on {expirationDateString}.
-
- )
-})
-
-export const SubscriptionInformation = observer(({ subscriptionState, application }: Props) => {
+const SubscriptionInformation = ({ subscriptionState, application }: Props) => {
const manageSubscription = async () => {
openSubscriptionDashboard(application)
}
@@ -80,4 +26,6 @@ export const SubscriptionInformation = observer(({ subscriptionState, applicatio
/>
>
)
-})
+}
+
+export default observer(SubscriptionInformation)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Account/Sync.tsx b/app/assets/javascripts/Components/Preferences/Panes/Account/Sync.tsx
index ca6c809ee..cb3a1977f 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Account/Sync.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Account/Sync.tsx
@@ -1,21 +1,19 @@
-import { PreferencesGroup, PreferencesSegment, Text, Title } from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
-import { SyncQueueStrategy, dateToLocalizedString } from '@standardnotes/snjs'
+import { Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
+import Button from '@/Components/Button/Button'
+import { SyncQueueStrategy } from '@standardnotes/snjs'
import { STRING_GENERIC_SYNC_ERROR } from '@/Strings'
-import { useState } from '@node_modules/preact/hooks'
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent, useState } from 'react'
+import { formatLastSyncDate } from '@/Utils/FormatLastSyncDate'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const formatLastSyncDate = (lastUpdatedDate: Date) => {
- return dateToLocalizedString(lastUpdatedDate)
-}
-
-export const Sync: FunctionComponent = observer(({ application }: Props) => {
+const Sync: FunctionComponent = ({ application }: Props) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false)
const [lastSyncDate, setLastSyncDate] = useState(formatLastSyncDate(application.sync.getLastSyncDate() as Date))
@@ -55,4 +53,6 @@ export const Sync: FunctionComponent = observer(({ application }: Props)
)
-})
+}
+
+export default observer(Sync)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Appearance.tsx b/app/assets/javascripts/Components/Preferences/Panes/Appearance.tsx
index dfa4cced4..ea60a5dc3 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Appearance.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Appearance.tsx
@@ -1,27 +1,23 @@
-import { Dropdown, DropdownItem } from '@/Components/Dropdown/Dropdown'
+import Dropdown from '@/Components/Dropdown/Dropdown'
+import { DropdownItem } from '@/Components/Dropdown/DropdownItem'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { Switch } from '@/Components/Switch/Switch'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Switch from '@/Components/Switch/Switch'
import { WebApplication } from '@/UIModels/Application'
import { ContentType, FeatureIdentifier, FeatureStatus, PrefKey, GetFeatures, SNTheme } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useEffect, useState } from 'preact/hooks'
-import {
- PreferencesGroup,
- PreferencesPane,
- PreferencesSegment,
- Subtitle,
- Title,
- Text,
-} from '@/Components/Preferences/PreferencesComponents'
+import { FunctionComponent, useEffect, useState } from 'react'
+import { Subtitle, Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import { sortThemes } from '@/Utils/SortThemes'
+import PreferencesPane from '../PreferencesComponents/PreferencesPane'
+import PreferencesGroup from '../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const Appearance: FunctionComponent = observer(({ application }) => {
+const Appearance: FunctionComponent = ({ application }) => {
const premiumModal = usePremiumModal()
const isEntitledToMidnightTheme =
application.features.getFeatureStatus(FeatureIdentifier.MidnightTheme) === FeatureStatus.Entitled
@@ -120,7 +116,7 @@ export const Appearance: FunctionComponent = observer(({ application }) =
-
+
Automatic Light Theme
Theme to be used for system light mode:
@@ -135,7 +131,7 @@ export const Appearance: FunctionComponent
= observer(({ application }) =
/>
-
+
Automatic Dark Theme
Theme to be used for system dark mode:
@@ -155,4 +151,6 @@ export const Appearance: FunctionComponent
= observer(({ application }) =
)
-})
+}
+
+export default observer(Appearance)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/Backups.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/Backups.tsx
index 13e0d3a7c..0671fa0b5 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/Backups.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/Backups.tsx
@@ -1,24 +1,27 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
-import { FunctionComponent } from 'preact'
-import { PreferencesPane } from '@/Components/Preferences/PreferencesComponents'
-import { CloudLink } from './CloudBackups/CloudBackups'
-import { DataBackups } from './DataBackups'
-import { EmailBackups } from './EmailBackups'
-import { FileBackups } from './Files/FileBackups'
+import { FunctionComponent } from 'react'
+import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane'
+import CloudLink from './CloudBackups/CloudBackups'
+import DataBackups from './DataBackups'
+import EmailBackups from './EmailBackups'
+import FileBackupsCrossPlatform from './Files/FileBackupsCrossPlatform'
+import { observer } from 'mobx-react-lite'
-interface Props {
+type Props = {
appState: AppState
application: WebApplication
}
-export const Backups: FunctionComponent = ({ application, appState }) => {
+const Backups: FunctionComponent = ({ application, appState }) => {
return (
-
+
)
}
+
+export default observer(Backups)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx
index aa66e0058..b7d99e38d 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackupProvider.tsx
@@ -1,4 +1,12 @@
-import { useCallback, useEffect, useState } from 'preact/hooks'
+import {
+ useCallback,
+ useEffect,
+ useState,
+ FunctionComponent,
+ KeyboardEventHandler,
+ ChangeEventHandler,
+ MouseEventHandler,
+} from 'react'
import {
ButtonType,
SettingName,
@@ -8,11 +16,10 @@ import {
OneDriveBackupFrequency,
} from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
import { isDev, openInNewTab } from '@/Utils'
-import { Subtitle } from '@/Components/Preferences/PreferencesComponents'
+import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { KeyboardKey } from '@/Services/IOService'
-import { FunctionComponent } from 'preact'
type Props = {
application: WebApplication
@@ -20,17 +27,13 @@ type Props = {
isEntitledToCloudBackups: boolean
}
-export const CloudBackupProvider: FunctionComponent = ({
- application,
- providerName,
- isEntitledToCloudBackups,
-}) => {
+const CloudBackupProvider: FunctionComponent = ({ application, providerName, isEntitledToCloudBackups }) => {
const [authBegan, setAuthBegan] = useState(false)
const [successfullyInstalled, setSuccessfullyInstalled] = useState(false)
const [backupFrequency, setBackupFrequency] = useState(undefined)
const [confirmation, setConfirmation] = useState('')
- const disable = async (event: Event) => {
+ const disable: MouseEventHandler = async (event) => {
event.stopPropagation()
try {
@@ -52,7 +55,7 @@ export const CloudBackupProvider: FunctionComponent = ({
}
}
- const installIntegration = (event: Event) => {
+ const installIntegration: MouseEventHandler = (event) => {
if (!isEntitledToCloudBackups) {
return
}
@@ -117,7 +120,7 @@ export const CloudBackupProvider: FunctionComponent = ({
return urlSearchParams.get(integrationTokenKeyInUrl)
}
- const handleKeyPress = async (event: KeyboardEvent) => {
+ const handleKeyPress: KeyboardEventHandler = async (event) => {
if (event.key === KeyboardKey.Enter) {
try {
const decryptedCode = atob(confirmation)
@@ -145,8 +148,8 @@ export const CloudBackupProvider: FunctionComponent = ({
}
}
- const handleChange = (event: Event) => {
- setConfirmation((event.target as HTMLInputElement).value)
+ const handleChange: ChangeEventHandler = (event) => {
+ setConfirmation(event.target.value)
}
const getIntegrationStatus = useCallback(async () => {
@@ -219,3 +222,5 @@ export const CloudBackupProvider: FunctionComponent = ({
)
}
+
+export default CloudBackupProvider
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackups.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackups.tsx
index baa8a0b2a..f7794647e 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackups.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/CloudBackups/CloudBackups.tsx
@@ -1,14 +1,8 @@
-import { CloudBackupProvider } from './CloudBackupProvider'
-import { useCallback, useEffect, useState } from 'preact/hooks'
+import CloudBackupProvider from './CloudBackupProvider'
+import { useCallback, useEffect, useState, FunctionComponent, Fragment } from 'react'
import { WebApplication } from '@/UIModels/Application'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import {
FeatureStatus,
FeatureIdentifier,
@@ -16,11 +10,12 @@ import {
MuteFailedCloudBackupsEmailsOption,
SettingName,
} from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { Switch } from '@/Components/Switch/Switch'
+import Switch from '@/Components/Switch/Switch'
import { convertStringifiedBooleanToBoolean } from '@/Utils'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Strings'
+import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
const providerData = [{ name: CloudProvider.Dropbox }, { name: CloudProvider.Google }, { name: CloudProvider.OneDrive }]
@@ -28,7 +23,7 @@ type Props = {
application: WebApplication
}
-export const CloudLink: FunctionComponent = ({ application }) => {
+const CloudLink: FunctionComponent = ({ application }) => {
const [isEntitledToCloudBackups, setIsEntitledToCloudBackups] = useState(false)
const [isFailedCloudBackupEmailMuted, setIsFailedCloudBackupEmailMuted] = useState(true)
const [isLoading, setIsLoading] = useState(false)
@@ -121,14 +116,14 @@ export const CloudLink: FunctionComponent = ({ application }) => {
{providerData.map(({ name }) => (
- <>
+
- >
+
))}
@@ -155,3 +150,5 @@ export const CloudLink: FunctionComponent = ({ application }) => {
)
}
+
+export default CloudLink
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx
index 1763af116..1067dafe9 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/DataBackups.tsx
@@ -11,27 +11,22 @@ import {
STRING_ENC_NOT_ENABLED,
} from '@/Strings'
import { BackupFile } from '@standardnotes/snjs'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
+import { ChangeEventHandler, MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
-import { JSXInternal } from 'preact/src/jsx'
-import TargetedEvent = JSXInternal.TargetedEvent
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Title,
- Text,
- Subtitle,
-} from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
+import Button from '@/Components/Button/Button'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
type Props = {
application: WebApplication
appState: AppState
}
-export const DataBackups = observer(({ application, appState }: Props) => {
+const DataBackups = ({ application, appState }: Props) => {
const fileInputRef = useRef(null)
const [isImportDataLoading, setIsImportDataLoading] = useState(false)
const {
@@ -109,8 +104,8 @@ export const DataBackups = observer(({ application, appState }: Props) => {
})
}
- const importFileSelected = async (event: TargetedEvent) => {
- const { files } = event.target as HTMLInputElement
+ const importFileSelected: ChangeEventHandler = async (event) => {
+ const { files } = event.target
if (!files) {
return
@@ -136,7 +131,7 @@ export const DataBackups = observer(({ application, appState }: Props) => {
}
// Whenever "Import Backup" is either clicked or key-pressed, proceed the import
- const handleImportFile = (event: TargetedEvent | KeyboardEvent) => {
+ const handleImportFile: MouseEventHandler = (event) => {
if (event instanceof KeyboardEvent) {
const { code } = event
@@ -158,7 +153,7 @@ export const DataBackups = observer(({ application, appState }: Props) => {
Data Backups
- {!isDesktopApplication() && (
+ {isDesktopApplication() && (
Backups are automatically created on desktop and can be managed via the "Backups" top-level menu.
@@ -183,10 +178,11 @@ export const DataBackups = observer(({ application, appState }: Props) => {
+
Import a previously saved backup file
-
+
{isImportDataLoading &&
}
@@ -195,4 +191,6 @@ export const DataBackups = observer(({ application, appState }: Props) => {
>
)
-})
+}
+
+export default observer(DataBackups)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/EmailBackups.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/EmailBackups.tsx
index f5e55926c..fc9526874 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/EmailBackups.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/EmailBackups.tsx
@@ -1,18 +1,13 @@
import { convertStringifiedBooleanToBoolean, isDesktopApplication } from '@/Utils'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Strings'
-import { useCallback, useEffect, useState } from 'preact/hooks'
+import { useCallback, useEffect, useState } from 'react'
import { WebApplication } from '@/UIModels/Application'
import { observer } from 'mobx-react-lite'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
-import { Dropdown, DropdownItem } from '@/Components/Dropdown/Dropdown'
-import { Switch } from '@/Components/Switch/Switch'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
+import Dropdown from '@/Components/Dropdown/Dropdown'
+import { DropdownItem } from '@/Components/Dropdown/DropdownItem'
+import Switch from '@/Components/Switch/Switch'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import {
FeatureStatus,
FeatureIdentifier,
@@ -20,12 +15,14 @@ import {
MuteFailedBackupsEmailsOption,
SettingName,
} from '@standardnotes/snjs'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const EmailBackups = observer(({ application }: Props) => {
+const EmailBackups = ({ application }: Props) => {
const [isLoading, setIsLoading] = useState(false)
const [emailFrequency, setEmailFrequency] = useState
(EmailBackupFrequency.Disabled)
const [emailFrequencyOptions, setEmailFrequencyOptions] = useState([])
@@ -132,7 +129,7 @@ export const EmailBackups = observer(({ application }: Props) => {
.
-
+
>
)}
@@ -157,7 +154,7 @@ export const EmailBackups = observer(({ application }: Props) => {
/>
)}
-
+
Email preferences
@@ -177,4 +174,6 @@ export const EmailBackups = observer(({ application }: Props) => {
)
-})
+}
+
+export default observer(EmailBackups)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx
index 9dc388cd4..0b9e64fc3 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/BackupsDropZone.tsx
@@ -1,20 +1,20 @@
-import { PreferencesSegment, Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents'
-import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
-import { Button } from '@/Components/Button/Button'
+import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
+import { useCallback, useEffect, useMemo, useState, FunctionComponent } from 'react'
+import Button from '@/Components/Button/Button'
import { FileBackupMetadataFile, FileBackupsConstantsV1, FileItem, FileHandleRead } from '@standardnotes/snjs'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { EncryptionStatusItem } from '../../Security/Encryption'
-import { Icon } from '@/Components/Icon/Icon'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Icon from '@/Components/Icon/Icon'
import { StreamingFileApi } from '@standardnotes/filepicker'
-import { FunctionComponent } from 'preact'
import { isHandlingBackupDrag } from '@/Utils/DragTypeCheck'
import { WebApplication } from '@/UIModels/Application'
+import EncryptionStatusItem from '../../Security/EncryptionStatusItem'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const BackupsDropZone: FunctionComponent
= ({ application }) => {
+const BackupsDropZone: FunctionComponent = ({ application }) => {
const [droppedFile, setDroppedFile] = useState(undefined)
const [decryptedFileItem, setDecryptedFileItem] = useState(undefined)
const [binaryFile, setBinaryFile] = useState(undefined)
@@ -225,3 +225,5 @@ export const BackupsDropZone: FunctionComponent = ({ application }) => {
>
)
}
+
+export default BackupsDropZone
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsCrossPlatform.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsCrossPlatform.tsx
new file mode 100644
index 000000000..2118645c5
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsCrossPlatform.tsx
@@ -0,0 +1,34 @@
+import { Subtitle, Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
+import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
+import { WebApplication } from '@/UIModels/Application'
+import { useMemo } from 'react'
+import BackupsDropZone from './BackupsDropZone'
+import FileBackupsDesktop from './FileBackupsDesktop'
+
+type Props = {
+ application: WebApplication
+}
+
+const FileBackupsCrossPlatform = ({ application }: Props) => {
+ const fileBackupsService = useMemo(() => application.fileBackups, [application])
+
+ return fileBackupsService ? (
+
+ ) : (
+ <>
+
+
+ File Backups
+ Automatically save encrypted backups of files uploaded to any device to this computer.
+ To enable file backups, use the Standard Notes desktop application.
+
+
+
+
+
+ >
+ )
+}
+
+export default FileBackupsCrossPlatform
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackups.tsx b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsDesktop.tsx
similarity index 72%
rename from app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackups.tsx
rename to app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsDesktop.tsx
index e611acace..64c625a81 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackups.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Backups/Files/FileBackupsDesktop.tsx
@@ -1,45 +1,24 @@
import { WebApplication } from '@/UIModels/Application'
import { observer } from 'mobx-react-lite'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Title,
- Text,
- Subtitle,
-} from '@/Components/Preferences/PreferencesComponents'
-import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
-import { Button } from '@/Components/Button/Button'
-import { Switch } from '@/Components/Switch/Switch'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { EncryptionStatusItem } from '../../Security/Encryption'
-import { Icon } from '@/Components/Icon/Icon'
-import { BackupsDropZone } from './BackupsDropZone'
+import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
+import { useCallback, useEffect, useState } from 'react'
+import Button from '@/Components/Button/Button'
+import Switch from '@/Components/Switch/Switch'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Icon from '@/Components/Icon/Icon'
+import BackupsDropZone from './BackupsDropZone'
+import EncryptionStatusItem from '../../Security/EncryptionStatusItem'
+import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
+ backupsService: NonNullable
}
-export const FileBackups = observer(({ application }: Props) => {
+const FileBackupsDesktop = ({ application, backupsService }: Props) => {
const [backupsEnabled, setBackupsEnabled] = useState(false)
const [backupsLocation, setBackupsLocation] = useState('')
- const backupsService = useMemo(() => application.fileBackups, [application])
-
- if (!backupsService) {
- return (
- <>
-
-
- File Backups
- Automatically save encrypted backups of files uploaded to any device to this computer.
- To enable file backups, use the Standard Notes desktop application.
-
-
-
-
-
- >
- )
- }
useEffect(() => {
void backupsService.isFilesBackupsEnabled().then(setBackupsEnabled)
@@ -108,6 +87,7 @@ export const FileBackups = observer(({ application }: Props) => {
icon={[]}
checkmark={false}
/>
+
{
>
)
-})
+}
+
+export default observer(FileBackupsDesktop)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/CloudLink.tsx b/app/assets/javascripts/Components/Preferences/Panes/CloudLink.tsx
index c6e06d35f..6d85195d3 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/CloudLink.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/CloudLink.tsx
@@ -1,15 +1,10 @@
-import { FunctionComponent } from 'preact'
-import {
- Title,
- Subtitle,
- Text,
- LinkButton,
- PreferencesGroup,
- PreferencesPane,
- PreferencesSegment,
-} from '@/Components/Preferences/PreferencesComponents'
+import { FunctionComponent } from 'react'
+import { Title, Subtitle, Text, LinkButton } from '@/Components/Preferences/PreferencesComponents/Content'
+import PreferencesPane from '../PreferencesComponents/PreferencesPane'
+import PreferencesGroup from '../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../PreferencesComponents/PreferencesSegment'
-export const CloudLink: FunctionComponent = () => (
+const CloudLink: FunctionComponent = () => (
@@ -83,3 +78,5 @@ export const CloudLink: FunctionComponent = () => (
)
+
+export default CloudLink
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ConfirmCustomExtension.tsx b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ConfirmCustomExtension.tsx
index ae52c4b72..b6db22ae7 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ConfirmCustomExtension.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ConfirmCustomExtension.tsx
@@ -1,10 +1,11 @@
import { DisplayStringForContentType } from '@standardnotes/snjs'
-import { Button } from '@/Components/Button/Button'
-import { FunctionComponent } from 'preact'
-import { Title, Text, Subtitle, PreferencesSegment } from '@/Components/Preferences/PreferencesComponents'
+import Button from '@/Components/Button/Button'
+import { Fragment, FunctionComponent } from 'react'
+import { Title, Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { AnyExtension } from './AnyExtension'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
-export const ConfirmCustomExtension: FunctionComponent<{
+const ConfirmCustomExtension: FunctionComponent<{
component: AnyExtension
callback: (confirmed: boolean) => void
}> = ({ component, callback }) => {
@@ -44,11 +45,11 @@ export const ConfirmCustomExtension: FunctionComponent<{
return undefined
}
return (
- <>
+
{field.label}
{field.value}
- >
+
)
})}
@@ -64,3 +65,5 @@ export const ConfirmCustomExtension: FunctionComponent<{
)
}
+
+export default ConfirmCustomExtension
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionInfoCell.tsx b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionInfoCell.tsx
index 005bcb676..67679ed02 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionInfoCell.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionInfoCell.tsx
@@ -1,11 +1,12 @@
-import { FunctionComponent } from 'preact'
-import { useState, useRef, useEffect } from 'preact/hooks'
+import { FunctionComponent, useState, useRef, useEffect } from 'react'
-export const ExtensionInfoCell: FunctionComponent<{
+type Props = {
extensionName: string
changeName: (newName: string) => void
isThirdParty: boolean
-}> = ({ extensionName, changeName, isThirdParty }) => {
+}
+
+const ExtensionInfoCell: FunctionComponent = ({ extensionName, changeName, isThirdParty }) => {
const [isRenaming, setIsRenaming] = useState(false)
const [newExtensionName, setNewExtensionName] = useState(extensionName)
@@ -42,7 +43,7 @@ export const ExtensionInfoCell: FunctionComponent<{
)
}
+
+export default ExtensionInfoCell
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItem.tsx b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItem.tsx
index 35cbb38dd..80846a832 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItem.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItem.tsx
@@ -1,45 +1,32 @@
-import { FunctionComponent } from 'preact'
-import { SNComponent } from '@standardnotes/snjs'
-import { PreferencesSegment, SubtitleLight } from '@/Components/Preferences/PreferencesComponents'
-import { Switch } from '@/Components/Switch/Switch'
-import { WebApplication } from '@/UIModels/Application'
-import { useState } from 'preact/hooks'
-import { Button } from '@/Components/Button/Button'
-import { ExtensionInfoCell } from './ExtensionInfoCell'
-import { AnyExtension } from './AnyExtension'
+import { FunctionComponent, useState } from 'react'
+import { ComponentMutator, SNComponent } from '@standardnotes/snjs'
+import { SubtitleLight } from '@/Components/Preferences/PreferencesComponents/Content'
+import Switch from '@/Components/Switch/Switch'
+import Button from '@/Components/Button/Button'
+import ExtensionInfoCell from './ExtensionInfoCell'
+import { ExtensionItemProps } from './ExtensionItemProps'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
const UseHosted: FunctionComponent<{
offlineOnly: boolean
- toggleOfllineOnly: () => void
-}> = ({ offlineOnly, toggleOfllineOnly }) => (
+ toggleOfflineOnly: () => void
+}> = ({ offlineOnly, toggleOfflineOnly }) => (
Use hosted when local is unavailable
-
+
)
-export interface ExtensionItemProps {
- application: WebApplication
- extension: AnyExtension
- first: boolean
- latestVersion: string | undefined
- uninstall: (extension: AnyExtension) => void
- toggleActivate?: (extension: AnyExtension) => void
-}
-
-export const ExtensionItem: FunctionComponent = ({ application, extension, uninstall }) => {
+const ExtensionItem: FunctionComponent = ({ application, extension, uninstall }) => {
const [offlineOnly, setOfflineOnly] = useState(extension instanceof SNComponent ? extension.offlineOnly : false)
const [extensionName, setExtensionName] = useState(extension.displayName)
- const toggleOffllineOnly = () => {
+ const toggleOfflineOnly = () => {
const newOfflineOnly = !offlineOnly
setOfflineOnly(newOfflineOnly)
application.mutator
- .changeAndSaveItem(extension, (m: any) => {
- if (m.content == undefined) {
- m.content = {}
- }
- m.content.offlineOnly = newOfflineOnly
+ .changeAndSaveItem(extension, (mutator) => {
+ mutator.offlineOnly = newOfflineOnly
})
.then((item) => {
const component = item as SNComponent
@@ -53,11 +40,8 @@ export const ExtensionItem: FunctionComponent = ({ applicati
const changeExtensionName = (newName: string) => {
setExtensionName(newName)
application.mutator
- .changeAndSaveItem(extension, (m: any) => {
- if (m.content == undefined) {
- m.content = {}
- }
- m.content.name = newName
+ .changeAndSaveItem(extension, (mutator) => {
+ mutator.name = newName
})
.then((item) => {
const component = item as SNComponent
@@ -76,9 +60,7 @@ export const ExtensionItem: FunctionComponent = ({ applicati
- {isThirParty && localInstallable && (
-
- )}
+ {isThirParty && localInstallable && }
<>
@@ -94,3 +76,5 @@ export const ExtensionItem: FunctionComponent = ({ applicati
)
}
+
+export default ExtensionItem
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItemProps.tsx b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItemProps.tsx
new file mode 100644
index 000000000..aef23ebd2
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Extensions/ExtensionItemProps.tsx
@@ -0,0 +1,11 @@
+import { WebApplication } from '@/UIModels/Application'
+import { AnyExtension } from './AnyExtension'
+
+export interface ExtensionItemProps {
+ application: WebApplication
+ extension: AnyExtension
+ first: boolean
+ latestVersion: string | undefined
+ uninstall: (extension: AnyExtension) => void
+ toggleActivate?: (extension: AnyExtension) => void
+}
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Extensions/Extensions.tsx b/app/assets/javascripts/Components/Preferences/Panes/Extensions/Extensions.tsx
index 0d2e4f862..e9f872ce2 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Extensions/Extensions.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Extensions/Extensions.tsx
@@ -1,24 +1,26 @@
import { ButtonType, ContentType, SNComponent } from '@standardnotes/snjs'
-import { Button } from '@/Components/Button/Button'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
+import Button from '@/Components/Button/Button'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
import { WebApplication } from '@/UIModels/Application'
-import { FunctionComponent } from 'preact'
-import { Title, PreferencesSegment } from '@/Components/Preferences/PreferencesComponents'
-import { useEffect, useRef, useState } from 'preact/hooks'
+import { FunctionComponent, useEffect, useRef, useState } from 'react'
+import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { observer } from 'mobx-react-lite'
import { ExtensionsLatestVersions } from './ExtensionsLatestVersions'
-import { ExtensionItem } from './ExtensionItem'
-import { ConfirmCustomExtension } from './ConfirmCustomExtension'
+import ExtensionItem from './ExtensionItem'
+import ConfirmCustomExtension from './ConfirmCustomExtension'
import { AnyExtension } from './AnyExtension'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
const loadExtensions = (application: WebApplication) =>
application.items.getItems([ContentType.ActionsExtension, ContentType.Component, ContentType.Theme]) as AnyExtension[]
-export const Extensions: FunctionComponent<{
+type Props = {
application: WebApplication
extensionsLatestVersions: ExtensionsLatestVersions
className?: string
-}> = observer(({ application, extensionsLatestVersions, className = '' }) => {
+}
+
+const Extensions: FunctionComponent = ({ application, extensionsLatestVersions, className = '' }) => {
const [customUrl, setCustomUrl] = useState('')
const [confirmableExtension, setConfirmableExtension] = useState(undefined)
const [extensions, setExtensions] = useState(loadExtensions(application))
@@ -134,4 +136,6 @@ export const Extensions: FunctionComponent<{
)
-})
+}
+
+export default observer(Extensions)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/General/Defaults.tsx b/app/assets/javascripts/Components/Preferences/Panes/General/Defaults.tsx
index c68c0290d..0fb52173c 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/General/Defaults.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/General/Defaults.tsx
@@ -1,18 +1,14 @@
-import { Dropdown, DropdownItem } from '@/Components/Dropdown/Dropdown'
+import Dropdown from '@/Components/Dropdown/Dropdown'
+import { DropdownItem } from '@/Components/Dropdown/DropdownItem'
import { FeatureIdentifier, PrefKey, ComponentArea, ComponentMutator, SNComponent } from '@standardnotes/snjs'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
-import { FunctionComponent } from 'preact'
-import { useEffect, useState } from 'preact/hooks'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { Switch } from '@/Components/Switch/Switch'
+import { FunctionComponent, useEffect, useState } from 'react'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Switch from '@/Components/Switch/Switch'
import { PLAIN_EDITOR_NAME } from '@/Constants'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
@@ -47,7 +43,7 @@ const getDefaultEditor = (application: WebApplication) => {
return application.componentManager.componentsForArea(ComponentArea.Editor).filter((e) => e.isDefaultEditor())[0]
}
-export const Defaults: FunctionComponent
= ({ application }) => {
+const Defaults: FunctionComponent = ({ application }) => {
const [editorItems, setEditorItems] = useState([])
const [defaultEditorValue, setDefaultEditorValue] = useState(
() => getDefaultEditor(application)?.package_info?.identifier || 'plain-editor',
@@ -123,7 +119,7 @@ export const Defaults: FunctionComponent = ({ application }) => {
/>
-
+
Spellcheck
@@ -134,7 +130,7 @@ export const Defaults: FunctionComponent
= ({ application }) => {
-
+
Add all parent tags when adding a nested tag to a note
@@ -152,3 +148,5 @@ export const Defaults: FunctionComponent
= ({ application }) => {
)
}
+
+export default Defaults
diff --git a/app/assets/javascripts/Components/Preferences/Panes/General/General.tsx b/app/assets/javascripts/Components/Preferences/Panes/General/General.tsx
index 353dcf226..dec99befc 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/General/General.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/General/General.tsx
@@ -1,27 +1,27 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
-import { FunctionComponent } from 'preact'
-import { PreferencesPane } from '@/Components/Preferences/PreferencesComponents'
+import { FunctionComponent } from 'react'
import { ExtensionsLatestVersions } from '@/Components/Preferences/Panes/Extensions/ExtensionsLatestVersions'
import { observer } from 'mobx-react-lite'
-import { Tools } from './Tools'
-import { Defaults } from './Defaults'
-import { LabsPane } from './Labs'
-import { Advanced } from '@/Components/Preferences/Panes/Account/Advanced'
+import Tools from './Tools'
+import Defaults from './Defaults'
+import LabsPane from './Labs'
+import Advanced from '@/Components/Preferences/Panes/Account/Advanced'
+import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
-interface GeneralProps {
+type Props = {
appState: AppState
application: WebApplication
extensionsLatestVersions: ExtensionsLatestVersions
}
-export const General: FunctionComponent = observer(
- ({ appState, application, extensionsLatestVersions }) => (
-
-
-
-
-
-
- ),
+const General: FunctionComponent = ({ appState, application, extensionsLatestVersions }) => (
+
+
+
+
+
+
)
+
+export default observer(General)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/General/Labs.tsx b/app/assets/javascripts/Components/Preferences/Panes/General/Labs.tsx
index 6650642d4..df48fdacf 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/General/Labs.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/General/Labs.tsx
@@ -1,17 +1,12 @@
-import { Switch } from '@/Components/Switch/Switch'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
+import Switch from '@/Components/Switch/Switch'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { FeatureIdentifier, FeatureStatus, FindNativeFeature } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useState } from 'preact/hooks'
+import { Fragment, FunctionComponent, useCallback, useEffect, useState } from 'react'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type ExperimentalFeatureItem = {
identifier: FeatureIdentifier
@@ -25,7 +20,7 @@ type Props = {
application: WebApplication
}
-export const LabsPane: FunctionComponent = ({ application }) => {
+const LabsPane: FunctionComponent = ({ application }) => {
const [experimentalFeatures, setExperimentalFeatures] = useState([])
const reloadExperimentalFeatures = useCallback(() => {
@@ -67,7 +62,7 @@ export const LabsPane: FunctionComponent = ({ application }) => {
const showHorizontalSeparator = experimentalFeatures.length > 1 && index !== experimentalFeatures.length - 1
return (
- <>
+
{name}
@@ -76,7 +71,7 @@ export const LabsPane: FunctionComponent
= ({ application }) => {
{showHorizontalSeparator &&
}
- >
+
)
})}
{experimentalFeatures.length === 0 && (
@@ -91,3 +86,5 @@ export const LabsPane: FunctionComponent
= ({ application }) => {
)
}
+
+export default LabsPane
diff --git a/app/assets/javascripts/Components/Preferences/Panes/General/Tools.tsx b/app/assets/javascripts/Components/Preferences/Panes/General/Tools.tsx
index 098799a3d..39b8a95e3 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/General/Tools.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/General/Tools.tsx
@@ -1,23 +1,18 @@
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { Switch } from '@/Components/Switch/Switch'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Switch from '@/Components/Switch/Switch'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { PrefKey } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionalComponent } from 'preact'
-import { useState } from 'preact/hooks'
+import { FunctionComponent, useState } from 'react'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const Tools: FunctionalComponent = observer(({ application }: Props) => {
+const Tools: FunctionComponent = ({ application }: Props) => {
const [monospaceFont, setMonospaceFont] = useState(() =>
application.getPreference(PrefKey.EditorMonospaceEnabled, true),
)
@@ -47,7 +42,7 @@ export const Tools: FunctionalComponent = observer(({ application }: Prop
-
+
Margin Resizers
@@ -59,4 +54,6 @@ export const Tools: FunctionalComponent
= observer(({ application }: Prop
)
-})
+}
+
+export default observer(Tools)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/HelpFeedback.tsx b/app/assets/javascripts/Components/Preferences/Panes/HelpFeedback.tsx
index e08b94462..deb7d7e12 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/HelpFeedback.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/HelpFeedback.tsx
@@ -1,15 +1,11 @@
-import { FunctionComponent } from 'preact'
-import {
- Title,
- Subtitle,
- Text,
- LinkButton,
- PreferencesGroup,
- PreferencesPane,
- PreferencesSegment,
-} from '@/Components/Preferences/PreferencesComponents'
+import { FunctionComponent } from 'react'
+import { Title, Subtitle, Text, LinkButton } from '@/Components/Preferences/PreferencesComponents/Content'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import PreferencesPane from '../PreferencesComponents/PreferencesPane'
+import PreferencesGroup from '../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../PreferencesComponents/PreferencesSegment'
-export const HelpAndFeedback: FunctionComponent = () => (
+const HelpAndFeedback: FunctionComponent = () => (
@@ -26,6 +22,7 @@ export const HelpAndFeedback: FunctionComponent = () => (
+
Can I collaborate with others on a note?
@@ -34,6 +31,7 @@ export const HelpAndFeedback: FunctionComponent = () => (
conflicts, which may result in the duplication of notes.
+
Can I use Standard Notes totally offline?
@@ -44,6 +42,7 @@ export const HelpAndFeedback: FunctionComponent = () => (
+
Can’t find your question here?
@@ -83,3 +82,5 @@ export const HelpAndFeedback: FunctionComponent = () => (
)
+
+export default HelpAndFeedback
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Listed/Listed.tsx b/app/assets/javascripts/Components/Preferences/Panes/Listed/Listed.tsx
index 68fb663a5..c4c9f4385 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Listed/Listed.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Listed/Listed.tsx
@@ -1,23 +1,20 @@
-import {
- PreferencesGroup,
- PreferencesPane,
- PreferencesSegment,
- Title,
- Subtitle,
- Text,
-} from '@/Components/Preferences/PreferencesComponents'
+import { Title, Subtitle, Text } from '@/Components/Preferences/PreferencesComponents/Content'
import { observer } from 'mobx-react-lite'
import { WebApplication } from '@/UIModels/Application'
import { ButtonType, ListedAccount } from '@standardnotes/snjs'
-import { useCallback, useEffect, useState } from 'preact/hooks'
-import { ListedAccountItem } from './BlogItem'
-import { Button } from '@/Components/Button/Button'
+import { useCallback, useEffect, useState } from 'react'
+import ListedAccountItem from './ListedAccountItem'
+import Button from '@/Components/Button/Button'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const Listed = observer(({ application }: Props) => {
+const Listed = ({ application }: Props) => {
const [accounts, setAccounts] = useState([])
const [requestingAccount, setRequestingAccount] = useState()
@@ -92,19 +89,24 @@ export const Listed = observer(({ application }: Props) => {
{application.getUser() && (
-
- Get Started
- Create a free Listed author account to get started.
-
-
+ <>
+
+
+ Get Started
+ Create a free Listed author account to get started.
+
+
+ >
)}
)
-})
+}
+
+export default observer(Listed)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Listed/BlogItem.tsx b/app/assets/javascripts/Components/Preferences/Panes/Listed/ListedAccountItem.tsx
similarity index 80%
rename from app/assets/javascripts/Components/Preferences/Panes/Listed/BlogItem.tsx
rename to app/assets/javascripts/Components/Preferences/Panes/Listed/ListedAccountItem.tsx
index a5fba599b..ff8364a0e 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Listed/BlogItem.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Listed/ListedAccountItem.tsx
@@ -1,9 +1,8 @@
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { LinkButton, Subtitle } from '@/Components/Preferences/PreferencesComponents'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import { LinkButton, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { ListedAccount, ListedAccountInfo } from '@standardnotes/snjs'
-import { FunctionalComponent } from 'preact'
-import { useEffect, useState } from 'preact/hooks'
+import { FunctionComponent, useEffect, useState } from 'react'
type Props = {
account: ListedAccount
@@ -11,7 +10,7 @@ type Props = {
application: WebApplication
}
-export const ListedAccountItem: FunctionalComponent = ({ account, showSeparator, application }) => {
+const ListedAccountItem: FunctionComponent = ({ account, showSeparator, application }) => {
const [isLoading, setIsLoading] = useState(false)
const [accountInfo, setAccountInfo] = useState()
@@ -42,3 +41,5 @@ export const ListedAccountItem: FunctionalComponent = ({ account, showSep
>
)
}
+
+export default ListedAccountItem
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/Encryption.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/Encryption.tsx
index e95851ed5..944c0dbcc 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/Encryption.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/Encryption.tsx
@@ -1,54 +1,15 @@
-import { Icon } from '@/Components/Icon/Icon'
import { STRING_E2E_ENABLED, STRING_ENC_NOT_ENABLED, STRING_LOCAL_ENC_ENABLED } from '@/Strings'
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { ComponentChild, FunctionComponent } from 'preact'
-import { PreferencesGroup, PreferencesSegment, Text, Title } from '@/Components/Preferences/PreferencesComponents'
+import { FunctionComponent } from 'react'
+import { Title, Text } from '../../PreferencesComponents/Content'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+import EncryptionEnabled from './EncryptionEnabled'
-const formatCount = (count: number, itemType: string) => `${count} / ${count} ${itemType}`
+type Props = { appState: AppState }
-export const EncryptionStatusItem: FunctionComponent<{
- icon: ComponentChild
- status: string
- checkmark?: boolean
-}> = ({ icon, status, checkmark = true }) => (
-
- {icon}
-
-
{status}
-
- {checkmark &&
}
-
-)
-
-const EncryptionEnabled: FunctionComponent<{ appState: AppState }> = observer(({ appState }) => {
- const count = appState.accountMenu.structuredNotesAndTagsCount
- const notes = formatCount(count.notes, 'notes')
- const tags = formatCount(count.tags, 'tags')
- const archived = formatCount(count.archived, 'archived notes')
- const deleted = formatCount(count.deleted, 'trashed notes')
-
- const noteIcon =
- const tagIcon =
- const archiveIcon =
- const trashIcon =
- return (
- <>
-
-
- >
- )
-})
-
-export const Encryption: FunctionComponent<{ appState: AppState }> = observer(({ appState }) => {
+const Encryption: FunctionComponent = ({ appState }) => {
const app = appState.application
const hasUser = app.hasAccount()
const hasPasscode = app.hasPasscode()
@@ -70,4 +31,6 @@ export const Encryption: FunctionComponent<{ appState: AppState }> = observer(({
)
-})
+}
+
+export default observer(Encryption)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx
new file mode 100644
index 000000000..add683ae8
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionEnabled.tsx
@@ -0,0 +1,39 @@
+import Icon from '@/Components/Icon/Icon'
+import { AppState } from '@/UIModels/AppState'
+import { observer } from 'mobx-react-lite'
+import { FunctionComponent } from 'react'
+import EncryptionStatusItem from './EncryptionStatusItem'
+import { formatCount } from './formatCount'
+
+type Props = {
+ appState: AppState
+}
+
+const EncryptionEnabled: FunctionComponent = ({ appState }) => {
+ const count = appState.accountMenu.structuredNotesAndTagsCount
+ const notes = formatCount(count.notes, 'notes')
+ const tags = formatCount(count.tags, 'tags')
+ const archived = formatCount(count.archived, 'archived notes')
+ const deleted = formatCount(count.deleted, 'trashed notes')
+
+ const noteIcon =
+ const tagIcon =
+ const archiveIcon =
+ const trashIcon =
+ return (
+ <>
+
+
+ >
+ )
+}
+
+export default observer(EncryptionEnabled)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionStatusItem.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionStatusItem.tsx
new file mode 100644
index 000000000..bdb298e3e
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/EncryptionStatusItem.tsx
@@ -0,0 +1,20 @@
+import Icon from '@/Components/Icon/Icon'
+import { FunctionComponent, ReactNode } from 'react'
+
+type Props = {
+ icon: ReactNode
+ status: string
+ checkmark?: boolean
+}
+
+const EncryptionStatusItem: FunctionComponent = ({ icon, status, checkmark = true }) => (
+
+ {icon}
+
+
{status}
+
+ {checkmark &&
}
+
+)
+
+export default EncryptionStatusItem
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx
index 930accb77..d0d7c83ec 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/ErroredItems.tsx
@@ -1,26 +1,21 @@
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Text,
- Title,
- Subtitle,
-} from '@/Components/Preferences/PreferencesComponents'
+import { Fragment, FunctionComponent, useState } from 'react'
+import { Text, Title, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import {
ButtonType,
ClientDisplayableError,
DisplayStringForContentType,
EncryptedItemInterface,
} from '@standardnotes/snjs'
-import { Button } from '@/Components/Button/Button'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { useState } from 'preact/hooks'
+import Button from '@/Components/Button/Button'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
type Props = { appState: AppState }
-export const ErroredItems: FunctionComponent = observer(({ appState }: Props) => {
+const ErroredItems: FunctionComponent = ({ appState }: Props) => {
const app = appState.application
const [erroredItems, setErroredItems] = useState(app.items.invalidItems)
@@ -96,7 +91,7 @@ export const ErroredItems: FunctionComponent = observer(({ appState }: Pr
{erroredItems.map((item, index) => {
return (
- <>
+
{`${getContentTypeDisplay(item)} created on ${item.createdAtString}`}
@@ -134,10 +129,12 @@ export const ErroredItems: FunctionComponent
= observer(({ appState }: Pr
{index < erroredItems.length - 1 && }
- >
+
)
})}
)
-})
+}
+
+export default observer(ErroredItems)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx
index 6aea88040..69ba76c63 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/PasscodeLock.tsx
@@ -10,23 +10,22 @@ import {
} from '@/Strings'
import { WebApplication } from '@/UIModels/Application'
import { preventRefreshing } from '@/Utils'
-import { JSXInternal } from 'preact/src/jsx'
-import TargetedEvent = JSXInternal.TargetedEvent
-import TargetedMouseEvent = JSXInternal.TargetedMouseEvent
import { alertDialog } from '@/Services/AlertService'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
+import { ChangeEventHandler, FormEvent, useCallback, useEffect, useRef, useState } from 'react'
import { ApplicationEvent } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { AppState } from '@/UIModels/AppState'
-import { PreferencesSegment, Title, Text, PreferencesGroup } from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import { Title, Text } from '@/Components/Preferences/PreferencesComponents/Content'
+import Button from '@/Components/Button/Button'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
appState: AppState
}
-export const PasscodeLock = observer(({ application, appState }: Props) => {
+const PasscodeLock = ({ application, appState }: Props) => {
const keyStorageInfo = StringUtils.keyStorageInfo(application)
const passcodeAutoLockOptions = application.getAutolockService().getAutoLockIntervalOptions()
@@ -34,8 +33,8 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
const passcodeInputRef = useRef(null)
- const [passcode, setPasscode] = useState(undefined)
- const [passcodeConfirmation, setPasscodeConfirmation] = useState(undefined)
+ const [passcode, setPasscode] = useState()
+ const [passcodeConfirmation, setPasscodeConfirmation] = useState()
const [selectedAutoLockInterval, setSelectedAutoLockInterval] = useState(null)
const [isPasscodeFocused, setIsPasscodeFocused] = useState(false)
const [showPasscodeForm, setShowPasscodeForm] = useState(false)
@@ -93,17 +92,17 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
})
}
- const handlePasscodeChange = (event: TargetedEvent) => {
- const { value } = event.target as HTMLInputElement
+ const handlePasscodeChange: ChangeEventHandler = (event) => {
+ const { value } = event.target
setPasscode(value)
}
- const handleConfirmPasscodeChange = (event: TargetedEvent) => {
- const { value } = event.target as HTMLInputElement
+ const handleConfirmPasscodeChange: ChangeEventHandler = (event) => {
+ const { value } = event.target
setPasscodeConfirmation(value)
}
- const submitPasscodeForm = async (event: TargetedEvent | TargetedMouseEvent) => {
+ const submitPasscodeForm = async (event: MouseEvent | FormEvent) => {
event.preventDefault()
if (!passcode || passcode.length === 0) {
@@ -167,6 +166,12 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
}
}, [application])
+ const cancelPasscodeForm = () => {
+ setShowPasscodeForm(false)
+ setPasscode(undefined)
+ setPasscodeConfirmation(undefined)
+ }
+
return (
<>
@@ -197,20 +202,20 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
className="sk-input contrast"
type="password"
ref={passcodeInputRef}
- value={passcode}
+ value={passcode ? passcode : ''}
onChange={handlePasscodeChange}
placeholder="Passcode"
/>
- setShowPasscodeForm(false)} label="Cancel" />
+
)}
@@ -237,6 +242,7 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
{passcodeAutoLockOptions.map((option) => {
return (
selectAutoLockInterval(option.value)}
>
@@ -251,4 +257,6 @@ export const PasscodeLock = observer(({ application, appState }: Props) => {
)}
>
)
-})
+}
+
+export default observer(PasscodeLock)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/Privacy.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/Privacy.tsx
index fdb44b16b..7d4d270f9 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/Privacy.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/Privacy.tsx
@@ -1,31 +1,26 @@
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
-import { Switch } from '@/Components/Switch/Switch'
-import {
- PreferencesGroup,
- PreferencesSegment,
- Subtitle,
- Text,
- Title,
-} from '@/Components/Preferences/PreferencesComponents'
+import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
+import Switch from '@/Components/Switch/Switch'
+import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/UIModels/Application'
import { MuteSignInEmailsOption, LogSessionUserAgentOption, SettingName } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionalComponent } from 'preact'
-import { useCallback, useEffect, useState } from 'preact/hooks'
+import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Strings'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
type Props = {
application: WebApplication
}
-export const Privacy: FunctionalComponent = observer(({ application }: Props) => {
+const Privacy: FunctionComponent = ({ application }: Props) => {
const [signInEmailsMutedValue, setSignInEmailsMutedValue] = useState(
MuteSignInEmailsOption.NotMuted,
)
const [sessionUaLoggingValue, setSessionUaLoggingValue] = useState(
LogSessionUserAgentOption.Enabled,
)
- const [isLoading, setIsLoading] = useState(false)
+ const [isLoading, setIsLoading] = useState(true)
const updateSetting = async (settingName: SettingName, payload: string): Promise => {
try {
@@ -110,7 +105,7 @@ export const Privacy: FunctionalComponent = observer(({ application }: Pr
{isLoading ? (
-
+
) : (
= observer(({ application }: Pr
/>
)}
-
+
Session user agent logging
@@ -129,7 +124,7 @@ export const Privacy: FunctionalComponent
= observer(({ application }: Pr
{isLoading ? (
-
+
) : (
= observer(({ application }: Pr
)
-})
+}
+
+export default observer(Privacy)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/Protections.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/Protections.tsx
index 9dfa530b7..2668e7ecb 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/Protections.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/Protections.tsx
@@ -1,16 +1,17 @@
import { WebApplication } from '@/UIModels/Application'
-import { FunctionalComponent } from 'preact'
-import { useCallback, useState, useEffect } from 'preact/hooks'
+import { FunctionComponent, useCallback, useState, useEffect } from 'react'
import { ApplicationEvent } from '@standardnotes/snjs'
import { isSameDay } from '@/Utils'
-import { PreferencesGroup, PreferencesSegment, Title, Text } from '@/Components/Preferences/PreferencesComponents'
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
+import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
+import { Title, Text } from '../../PreferencesComponents/Content'
type Props = {
application: WebApplication
}
-export const Protections: FunctionalComponent = ({ application }) => {
+const Protections: FunctionComponent = ({ application }) => {
const enableProtections = () => {
application.clearProtectionSession().catch(console.error)
}
@@ -88,3 +89,5 @@ export const Protections: FunctionalComponent = ({ application }) => {
)
}
+
+export default Protections
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/Security.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/Security.tsx
index 0d1dbf53d..9c256c1f8 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/Security/Security.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/Security.tsx
@@ -1,25 +1,21 @@
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
-import { FunctionComponent } from 'preact'
-import { PreferencesPane } from '@/Components/Preferences/PreferencesComponents'
-import { TwoFactorAuthWrapper } from '../TwoFactorAuth/TwoFactorAuthWrapper'
+import { FunctionComponent } from 'react'
+import TwoFactorAuthWrapper from '../TwoFactorAuth/TwoFactorAuthWrapper'
import { MfaProps } from '../TwoFactorAuth/MfaProps'
-import { Encryption } from './Encryption'
-import { PasscodeLock } from './PasscodeLock'
-import { Privacy } from './Privacy'
-import { Protections } from './Protections'
-import { ErroredItems } from './ErroredItems'
+import Encryption from './Encryption'
+import PasscodeLock from './PasscodeLock'
+import Privacy from './Privacy'
+import Protections from './Protections'
+import ErroredItems from './ErroredItems'
+import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane'
interface SecurityProps extends MfaProps {
appState: AppState
application: WebApplication
}
-export const securityPrefsHasBubble = (application: WebApplication): boolean => {
- return application.items.invalidItems.length > 0
-}
-
-export const Security: FunctionComponent = (props) => (
+const Security: FunctionComponent = (props) => (
{props.application.items.invalidItems.length > 0 && }
@@ -29,3 +25,5 @@ export const Security: FunctionComponent = (props) => (
{props.application.getUser() && }
)
+
+export default Security
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/formatCount.ts b/app/assets/javascripts/Components/Preferences/Panes/Security/formatCount.ts
new file mode 100644
index 000000000..e6b9bf58f
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/formatCount.ts
@@ -0,0 +1 @@
+export const formatCount = (count: number, itemType: string) => `${count} / ${count} ${itemType}`
diff --git a/app/assets/javascripts/Components/Preferences/Panes/Security/securityPrefsHasBubble.tsx b/app/assets/javascripts/Components/Preferences/Panes/Security/securityPrefsHasBubble.tsx
new file mode 100644
index 000000000..d6dda7577
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/Security/securityPrefsHasBubble.tsx
@@ -0,0 +1,5 @@
+import { WebApplication } from '@/UIModels/Application'
+
+export const securityPrefsHasBubble = (application: WebApplication): boolean => {
+ return application.items.invalidItems.length > 0
+}
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/AuthAppInfoPopup.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/AuthAppInfoPopup.tsx
index 3af29b955..be443de56 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/AuthAppInfoPopup.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/AuthAppInfoPopup.tsx
@@ -1,15 +1,16 @@
-import { Icon } from '@/Components/Icon/Icon'
+import Icon from '@/Components/Icon/Icon'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
-import { FunctionComponent } from 'preact'
-import { useState, useRef, useEffect } from 'preact/hooks'
+import { FunctionComponent, useState, useRef, useEffect, MouseEventHandler } from 'react'
import { IconType } from '@standardnotes/snjs'
-const DisclosureIconButton: FunctionComponent<{
+type Props = {
className?: string
icon: IconType
- onMouseEnter?: any
- onMouseLeave?: any
-}> = ({ className = '', icon, onMouseEnter, onMouseLeave }) => (
+ onMouseEnter?: MouseEventHandler
+ onMouseLeave?: MouseEventHandler
+}
+
+const DisclosureIconButton: FunctionComponent = ({ className = '', icon, onMouseEnter, onMouseLeave }) => (
{
+const AuthAppInfoTooltip: FunctionComponent = () => {
const [isClicked, setClicked] = useState(false)
const [isHover, setHover] = useState(false)
const ref = useRef(null)
@@ -61,3 +62,5 @@ py-1.5 px-2 absolute w-103 -top-10 -left-51`}
)
}
+
+export default AuthAppInfoTooltip
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Bullet.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Bullet.tsx
index 10772aa22..82ee0eed8 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Bullet.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Bullet.tsx
@@ -1,5 +1,11 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
-export const Bullet: FunctionComponent<{ className?: string }> = ({ className = '' }) => (
+type Props = {
+ className?: string
+}
+
+const Bullet: FunctionComponent = ({ className = '' }) => (
)
+
+export default Bullet
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/CopyButton.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/CopyButton.tsx
index f2317356d..64cae4360 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/CopyButton.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/CopyButton.tsx
@@ -1,10 +1,11 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent, useState } from 'react'
+import IconButton from '@/Components/Button/IconButton'
-import { IconButton } from '@/Components/Button/IconButton'
+type Props = {
+ copyValue: string
+}
-import { useState } from 'preact/hooks'
-
-export const CopyButton: FunctionComponent<{ copyValue: string }> = ({ copyValue: secretKey }) => {
+const CopyButton: FunctionComponent = ({ copyValue: secretKey }) => {
const [isCopied, setCopied] = useState(false)
return (
= ({ copyValue
/>
)
}
+
+export default CopyButton
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/SaveSecretKey.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/SaveSecretKey.tsx
index 931b9254b..9f79a9fed 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/SaveSecretKey.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/SaveSecretKey.tsx
@@ -1,22 +1,22 @@
-import { Button } from '@/Components/Button/Button'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
-import { IconButton } from '@/Components/Button/IconButton'
+import Button from '@/Components/Button/Button'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
+import IconButton from '@/Components/Button/IconButton'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { CopyButton } from './CopyButton'
-import { Bullet } from './Bullet'
+import { FunctionComponent } from 'react'
+import CopyButton from './CopyButton'
+import Bullet from './Bullet'
import { downloadSecretKey } from './download-secret-key'
import { TwoFactorActivation } from './TwoFactorActivation'
-import {
- ModalDialog,
- ModalDialogButtons,
- ModalDialogDescription,
- ModalDialogLabel,
-} from '@/Components/Shared/ModalDialog'
+import ModalDialog from '@/Components/Shared/ModalDialog'
+import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons'
+import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
+import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
-export const SaveSecretKey: FunctionComponent<{
+type Props = {
activation: TwoFactorActivation
-}> = observer(({ activation: act }) => {
+}
+
+const SaveSecretKey: FunctionComponent = ({ activation: act }) => {
const download = (
)
-})
+}
+
+export default observer(SaveSecretKey)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/ScanQRCode.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/ScanQRCode.tsx
index ed4d3596a..e97b0f8f0 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/ScanQRCode.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/ScanQRCode.tsx
@@ -1,22 +1,22 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { observer } from 'mobx-react-lite'
import QRCode from 'qrcode.react'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
-import { Button } from '@/Components/Button/Button'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
+import Button from '@/Components/Button/Button'
import { TwoFactorActivation } from './TwoFactorActivation'
-import { AuthAppInfoTooltip } from './AuthAppInfoPopup'
-import {
- ModalDialog,
- ModalDialogButtons,
- ModalDialogDescription,
- ModalDialogLabel,
-} from '@/Components/Shared/ModalDialog'
-import { CopyButton } from './CopyButton'
-import { Bullet } from './Bullet'
+import AuthAppInfoTooltip from './AuthAppInfoPopup'
+import ModalDialog from '@/Components/Shared/ModalDialog'
+import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons'
+import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
+import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
+import CopyButton from './CopyButton'
+import Bullet from './Bullet'
-export const ScanQRCode: FunctionComponent<{
+type Props = {
activation: TwoFactorActivation
-}> = observer(({ activation: act }) => {
+}
+
+const ScanQRCode: FunctionComponent = ({ activation: act }) => {
return (
Step 1 of 3 - Scan QR code
@@ -58,4 +58,6 @@ export const ScanQRCode: FunctionComponent<{
)
-})
+}
+
+export default observer(ScanQRCode)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorActivationView.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorActivationView.tsx
index 2ac0aa94b..ee492d386 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorActivationView.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorActivationView.tsx
@@ -1,14 +1,16 @@
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { TwoFactorActivation } from './TwoFactorActivation'
-import { SaveSecretKey } from './SaveSecretKey'
-import { ScanQRCode } from './ScanQRCode'
-import { Verification } from './Verification'
-import { TwoFactorSuccess } from './TwoFactorSuccess'
+import SaveSecretKey from './SaveSecretKey'
+import ScanQRCode from './ScanQRCode'
+import Verification from './Verification'
+import TwoFactorSuccess from './TwoFactorSuccess'
-export const TwoFactorActivationView: FunctionComponent<{
+type Props = {
activation: TwoFactorActivation
-}> = observer(({ activation: act }) => {
+}
+
+const TwoFactorActivationView: FunctionComponent = ({ activation: act }) => {
switch (act.activationStep) {
case 'scan-qr-code':
return
@@ -19,4 +21,6 @@ export const TwoFactorActivationView: FunctionComponent<{
case 'success':
return
}
-})
+}
+
+export default observer(TwoFactorActivationView)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView.tsx
deleted file mode 100644
index a657f478a..000000000
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import { FunctionComponent } from 'preact'
-import { Title, Text, PreferencesGroup, PreferencesSegment } from '@/Components/Preferences/PreferencesComponents'
-import { Switch } from '@/Components/Switch/Switch'
-import { observer } from 'mobx-react-lite'
-import { is2FAActivation, is2FADisabled, TwoFactorAuth } from './TwoFactorAuth'
-import { TwoFactorActivationView } from './TwoFactorActivationView'
-
-const TwoFactorTitle: FunctionComponent<{ auth: TwoFactorAuth }> = observer(({ auth }) => {
- if (!auth.isLoggedIn()) {
- return Two-factor authentication not available
- }
- if (!auth.isMfaFeatureAvailable()) {
- return Two-factor authentication not available
- }
- return Two-factor authentication
-})
-
-const TwoFactorDescription: FunctionComponent<{ auth: TwoFactorAuth }> = observer(({ auth }) => {
- if (!auth.isLoggedIn()) {
- return Sign in or register for an account to configure 2FA.
- }
- if (!auth.isMfaFeatureAvailable()) {
- return (
-
- A paid subscription plan is required to enable 2FA.{' '}
-
- Learn more
-
- .
-
- )
- }
- return An extra layer of security when logging in to your account.
-})
-
-const TwoFactorSwitch: FunctionComponent<{ auth: TwoFactorAuth }> = observer(({ auth }) => {
- if (!(auth.isLoggedIn() && auth.isMfaFeatureAvailable())) {
- return null
- }
-
- if (auth.status === 'fetching') {
- return
- }
-
- return
-})
-
-export const TwoFactorAuthView: FunctionComponent<{
- auth: TwoFactorAuth
-}> = observer(({ auth }) => {
- return (
- <>
-
-
-
-
-
- {auth.errorMessage != null && (
-
- {auth.errorMessage}
-
- )}
-
- {auth.status !== 'fetching' && is2FAActivation(auth.status) && (
-
- )}
- >
- )
-})
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx
new file mode 100644
index 000000000..f5e90a55b
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx
@@ -0,0 +1,45 @@
+import { FunctionComponent } from 'react'
+import { Text } from '@/Components/Preferences/PreferencesComponents/Content'
+import { observer } from 'mobx-react-lite'
+import { is2FAActivation, TwoFactorAuth } from '../TwoFactorAuth'
+import TwoFactorActivationView from '../TwoFactorActivationView'
+import TwoFactorTitle from './TwoFactorTitle'
+import TwoFactorDescription from './TwoFactorDescription'
+import TwoFactorSwitch from './TwoFactorSwitch'
+import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
+import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
+
+type Props = {
+ auth: TwoFactorAuth
+}
+
+const TwoFactorAuthView: FunctionComponent = ({ auth }) => {
+ return (
+ <>
+
+
+
+
+
+ {auth.errorMessage != null && (
+
+ {auth.errorMessage}
+
+ )}
+
+ {auth.status !== 'fetching' && is2FAActivation(auth.status) && (
+
+ )}
+ >
+ )
+}
+
+export default observer(TwoFactorAuthView)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorDescription.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorDescription.tsx
new file mode 100644
index 000000000..838952018
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorDescription.tsx
@@ -0,0 +1,28 @@
+import { FunctionComponent } from 'react'
+import { Text } from '@/Components/Preferences/PreferencesComponents/Content'
+import { observer } from 'mobx-react-lite'
+import { TwoFactorAuth } from '../TwoFactorAuth'
+
+type Props = {
+ auth: TwoFactorAuth
+}
+
+const TwoFactorDescription: FunctionComponent = ({ auth }) => {
+ if (!auth.isLoggedIn()) {
+ return Sign in or register for an account to configure 2FA.
+ }
+ if (!auth.isMfaFeatureAvailable()) {
+ return (
+
+ A paid subscription plan is required to enable 2FA.{' '}
+
+ Learn more
+
+ .
+
+ )
+ }
+ return An extra layer of security when logging in to your account.
+}
+
+export default observer(TwoFactorDescription)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx
new file mode 100644
index 000000000..f02c814e6
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx
@@ -0,0 +1,22 @@
+import { FunctionComponent } from 'react'
+import Switch from '@/Components/Switch/Switch'
+import { observer } from 'mobx-react-lite'
+import { is2FADisabled, TwoFactorAuth } from '../TwoFactorAuth'
+
+type Props = {
+ auth: TwoFactorAuth
+}
+
+const TwoFactorSwitch: FunctionComponent = ({ auth }) => {
+ if (!(auth.isLoggedIn() && auth.isMfaFeatureAvailable())) {
+ return null
+ }
+
+ if (auth.status === 'fetching') {
+ return
+ }
+
+ return
+}
+
+export default observer(TwoFactorSwitch)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorTitle.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorTitle.tsx
new file mode 100644
index 000000000..b48e3787b
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthView/TwoFactorTitle.tsx
@@ -0,0 +1,20 @@
+import { FunctionComponent } from 'react'
+import { Title } from '@/Components/Preferences/PreferencesComponents/Content'
+import { observer } from 'mobx-react-lite'
+import { TwoFactorAuth } from '../TwoFactorAuth'
+
+type Props = {
+ auth: TwoFactorAuth
+}
+
+const TwoFactorTitle: FunctionComponent = ({ auth }) => {
+ if (!auth.isLoggedIn()) {
+ return Two-factor authentication not available
+ }
+ if (!auth.isMfaFeatureAvailable()) {
+ return Two-factor authentication not available
+ }
+ return Two-factor authentication
+}
+
+export default observer(TwoFactorTitle)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthWrapper.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthWrapper.tsx
index 5d051d2e6..850fade1c 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthWrapper.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorAuthWrapper.tsx
@@ -1,11 +1,12 @@
-import { FunctionComponent } from 'preact'
-import { useState } from 'preact/hooks'
+import { FunctionComponent, useState } from 'react'
import { MfaProps } from './MfaProps'
import { TwoFactorAuth } from './TwoFactorAuth'
-import { TwoFactorAuthView } from './TwoFactorAuthView'
+import TwoFactorAuthView from './TwoFactorAuthView/TwoFactorAuthView'
-export const TwoFactorAuthWrapper: FunctionComponent = (props) => {
+const TwoFactorAuthWrapper: FunctionComponent = (props) => {
const [auth] = useState(() => new TwoFactorAuth(props.mfaProvider, props.userProvider))
auth.fetchStatus()
return
}
+
+export default TwoFactorAuthWrapper
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorSuccess.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorSuccess.tsx
index 1b3270bec..e696b8d30 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorSuccess.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/TwoFactorSuccess.tsx
@@ -1,17 +1,18 @@
-import { Button } from '@/Components/Button/Button'
-import ModalDialog, {
- ModalDialogButtons,
- ModalDialogDescription,
- ModalDialogLabel,
-} from '@/Components/Shared/ModalDialog'
-import { Subtitle } from '@/Components/Preferences/PreferencesComponents'
+import Button from '@/Components/Button/Button'
+import ModalDialog from '@/Components/Shared/ModalDialog'
+import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons'
+import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
+import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
+import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { TwoFactorActivation } from './TwoFactorActivation'
-export const TwoFactorSuccess: FunctionComponent<{
+type Props = {
activation: TwoFactorActivation
-}> = observer(({ activation: act }) => (
+}
+
+const TwoFactorSuccess: FunctionComponent = ({ activation: act }) => (
Successfully Enabled
@@ -23,4 +24,6 @@ export const TwoFactorSuccess: FunctionComponent<{
-))
+)
+
+export default observer(TwoFactorSuccess)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Verification.tsx b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Verification.tsx
index 7bd7409d6..27a7fa4f2 100644
--- a/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Verification.tsx
+++ b/app/assets/javascripts/Components/Preferences/Panes/TwoFactorAuth/Verification.tsx
@@ -1,19 +1,19 @@
-import { Button } from '@/Components/Button/Button'
-import { DecoratedInput } from '@/Components/Input/DecoratedInput'
+import Button from '@/Components/Button/Button'
+import DecoratedInput from '@/Components/Input/DecoratedInput'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { Bullet } from './Bullet'
+import { FunctionComponent } from 'react'
+import Bullet from './Bullet'
import { TwoFactorActivation } from './TwoFactorActivation'
-import {
- ModalDialog,
- ModalDialogButtons,
- ModalDialogDescription,
- ModalDialogLabel,
-} from '@/Components/Shared/ModalDialog'
+import ModalDialog from '@/Components/Shared/ModalDialog'
+import ModalDialogButtons from '@/Components/Shared/ModalDialogButtons'
+import ModalDialogDescription from '@/Components/Shared/ModalDialogDescription'
+import ModalDialogLabel from '@/Components/Shared/ModalDialogLabel'
-export const Verification: FunctionComponent<{
+type Props = {
activation: TwoFactorActivation
-}> = observer(({ activation: act }) => {
+}
+
+const Verification: FunctionComponent = ({ activation: act }) => {
const secretKeyClass = act.verificationStatus === 'invalid-secret' ? 'border-danger' : ''
const authTokenClass = act.verificationStatus === 'invalid-auth-code' ? 'border-danger' : ''
return (
@@ -53,4 +53,6 @@ export const Verification: FunctionComponent<{
)
-})
+}
+
+export default observer(Verification)
diff --git a/app/assets/javascripts/Components/Preferences/Panes/index.ts b/app/assets/javascripts/Components/Preferences/Panes/index.ts
deleted file mode 100644
index d2fdab581..000000000
--- a/app/assets/javascripts/Components/Preferences/Panes/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './HelpFeedback'
-export * from './Security/Security'
-export * from './Account/AccountPreferences'
-export * from './Listed/Listed'
-export * from './General/General'
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesCanvas.tsx b/app/assets/javascripts/Components/Preferences/PreferencesCanvas.tsx
new file mode 100644
index 000000000..81d7f3b4c
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/PreferencesCanvas.tsx
@@ -0,0 +1,15 @@
+import { FunctionComponent } from 'react'
+import { observer } from 'mobx-react-lite'
+import { PreferencesMenu } from './PreferencesMenu'
+import PreferencesMenuView from './PreferencesMenuView'
+import PaneSelector from './PaneSelector'
+import { PreferencesProps } from './PreferencesProps'
+
+const PreferencesCanvas: FunctionComponent = (props) => (
+
+)
+
+export default observer(PreferencesCanvas)
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/Content.tsx b/app/assets/javascripts/Components/Preferences/PreferencesComponents/Content.tsx
index 39894a1da..f0c4494a3 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/Content.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesComponents/Content.tsx
@@ -1,4 +1,4 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
export const Title: FunctionComponent = ({ children }) => (
<>
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/MenuItem.tsx b/app/assets/javascripts/Components/Preferences/PreferencesComponents/MenuItem.tsx
index 4ba1a277c..bc4c741fa 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/MenuItem.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesComponents/MenuItem.tsx
@@ -1,5 +1,5 @@
-import { Icon } from '@/Components/Icon/Icon'
-import { FunctionComponent } from 'preact'
+import Icon from '@/Components/Icon/Icon'
+import { FunctionComponent } from 'react'
import { IconType } from '@standardnotes/snjs'
interface Props {
@@ -10,7 +10,7 @@ interface Props {
onClick: () => void
}
-export const MenuItem: FunctionComponent = ({ iconType, label, selected, onClick, hasBubble }) => (
+const PreferencesMenuItem: FunctionComponent = ({ iconType, label, selected, onClick, hasBubble }) => (
{
@@ -24,3 +24,5 @@ export const MenuItem: FunctionComponent
= ({ iconType, label, selected,
{hasBubble && ⚠️}
)
+
+export default PreferencesMenuItem
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesGroup.tsx b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesGroup.tsx
index deae99ce3..054183e62 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesGroup.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesGroup.tsx
@@ -1,21 +1,7 @@
-import { FunctionComponent } from 'preact'
-import { HorizontalSeparator } from '@/Components/Shared/HorizontalSeparator'
+import { FunctionComponent } from 'react'
-const HorizontalLine: FunctionComponent<{ index: number; length: number }> = ({ index, length }) => {
- return index < length - 1 ? : null
-}
-
-export const PreferencesGroup: FunctionComponent = ({ children }) => (
-
- {Array.isArray(children)
- ? children
- .filter((child) => child != undefined && child !== '' && child !== false)
- .map((child, i, arr) => (
- <>
- {child}
-
- >
- ))
- : children}
-
+const PreferencesGroup: FunctionComponent = ({ children }) => (
+ {children}
)
+
+export default PreferencesGroup
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesPane.tsx b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesPane.tsx
index 614a5ed5a..a32529e05 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesPane.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesPane.tsx
@@ -1,6 +1,6 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
-export const PreferencesPane: FunctionComponent = ({ children }) => (
+const PreferencesPane: FunctionComponent = ({ children }) => (
@@ -10,3 +10,5 @@ export const PreferencesPane: FunctionComponent = ({ children }) => (
)
+
+export default PreferencesPane
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesSegment.tsx b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesSegment.tsx
index 8fa1e4ffd..050ab5a0b 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesSegment.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesComponents/PreferencesSegment.tsx
@@ -1,8 +1,10 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
type Props = {
classes?: string
}
-export const PreferencesSegment: FunctionComponent
= ({ children, classes = '' }) => (
+const PreferencesSegment: FunctionComponent = ({ children, classes = '' }) => (
{children}
)
+
+export default PreferencesSegment
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesComponents/index.ts b/app/assets/javascripts/Components/Preferences/PreferencesComponents/index.ts
deleted file mode 100644
index c41ad54ae..000000000
--- a/app/assets/javascripts/Components/Preferences/PreferencesComponents/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './Content'
-export * from './MenuItem'
-export * from './PreferencesPane'
-export * from './PreferencesGroup'
-export * from './PreferencesSegment'
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesMenu.ts b/app/assets/javascripts/Components/Preferences/PreferencesMenu.ts
index 414841651..d7454c5db 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesMenu.ts
+++ b/app/assets/javascripts/Components/Preferences/PreferencesMenu.ts
@@ -2,7 +2,7 @@ import { action, makeAutoObservable, observable } from 'mobx'
import { IconType } from '@standardnotes/snjs'
import { WebApplication } from '@/UIModels/Application'
import { ExtensionsLatestVersions } from './Panes/Extensions/ExtensionsLatestVersions'
-import { securityPrefsHasBubble } from './Panes'
+import { securityPrefsHasBubble } from './Panes/Security/securityPrefsHasBubble'
const PREFERENCE_IDS = [
'general',
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesMenuView.tsx b/app/assets/javascripts/Components/Preferences/PreferencesMenuView.tsx
index 0a37f1f93..41227e604 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesMenuView.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesMenuView.tsx
@@ -1,14 +1,16 @@
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { MenuItem } from './PreferencesComponents'
+import { FunctionComponent } from 'react'
+import PreferencesMenuItem from './PreferencesComponents/MenuItem'
import { PreferencesMenu } from './PreferencesMenu'
-export const PreferencesMenuView: FunctionComponent<{
+type Props = {
menu: PreferencesMenu
-}> = observer(({ menu }) => (
+}
+
+const PreferencesMenuView: FunctionComponent = ({ menu }) => (
{menu.menuItems.map((pref) => (
-
))}
-))
+)
+
+export default observer(PreferencesMenuView)
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesProps.tsx b/app/assets/javascripts/Components/Preferences/PreferencesProps.tsx
new file mode 100644
index 000000000..dc84b3e24
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/PreferencesProps.tsx
@@ -0,0 +1,9 @@
+import { WebApplication } from '@/UIModels/Application'
+import { MfaProps } from './Panes/TwoFactorAuth/MfaProps'
+import { AppState } from '@/UIModels/AppState'
+
+export interface PreferencesProps extends MfaProps {
+ application: WebApplication
+ appState: AppState
+ closePreferences: () => void
+}
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesView.tsx b/app/assets/javascripts/Components/Preferences/PreferencesView.tsx
index 992d67988..f3be2eaac 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesView.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesView.tsx
@@ -1,80 +1,13 @@
-import { RoundIconButton } from '@/Components/Button/RoundIconButton'
-import { TitleBar } from '@/Components/TitleBar/TitleBar'
-import { Title } from '@/Components/TitleBar/Title'
-import { FunctionComponent } from 'preact'
+import RoundIconButton from '@/Components/Button/RoundIconButton'
+import TitleBar from '@/Components/TitleBar/TitleBar'
+import Title from '@/Components/TitleBar/Title'
+import { FunctionComponent, useEffect, useMemo } from 'react'
import { observer } from 'mobx-react-lite'
-import { AccountPreferences, HelpAndFeedback, Listed, General, Security } from './Panes'
import { PreferencesMenu } from './PreferencesMenu'
-import { PreferencesMenuView } from './PreferencesMenuView'
-import { WebApplication } from '@/UIModels/Application'
-import { MfaProps } from './Panes/TwoFactorAuth/MfaProps'
-import { AppState } from '@/UIModels/AppState'
-import { useEffect, useMemo } from 'preact/hooks'
-import { Backups } from '@/Components/Preferences/Panes/Backups/Backups'
-import { Appearance } from './Panes/Appearance'
+import PreferencesCanvas from './PreferencesCanvas'
+import { PreferencesProps } from './PreferencesProps'
-interface PreferencesProps extends MfaProps {
- application: WebApplication
- appState: AppState
- closePreferences: () => void
-}
-
-const PaneSelector: FunctionComponent = observer(
- ({ menu, appState, application, mfaProvider, userProvider }) => {
- switch (menu.selectedPaneId) {
- case 'general':
- return (
-
- )
- case 'account':
- return
- case 'appearance':
- return
- case 'security':
- return (
-
- )
- case 'backups':
- return
- case 'listed':
- return
- case 'shortcuts':
- return null
- case 'accessibility':
- return null
- case 'get-free-month':
- return null
- case 'help-feedback':
- return
- default:
- return (
-
- )
- }
- },
-)
-
-const PreferencesCanvas: FunctionComponent = observer((props) => (
-
-))
-
-export const PreferencesView: FunctionComponent = observer((props) => {
+const PreferencesView: FunctionComponent = (props) => {
const menu = useMemo(
() => new PreferencesMenu(props.application, props.appState.enableUnfinishedFeatures),
[props.appState.enableUnfinishedFeatures, props.application],
@@ -97,7 +30,6 @@ export const PreferencesView: FunctionComponent = observer((pr
return (
- {/* div is added so flex justify-between can center the title */}
Your preferences for Standard Notes
= observer((pr
)
-})
+}
+
+export default observer(PreferencesView)
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesViewWrapper.tsx b/app/assets/javascripts/Components/Preferences/PreferencesViewWrapper.tsx
index ea79c2526..f42c2c7b9 100644
--- a/app/assets/javascripts/Components/Preferences/PreferencesViewWrapper.tsx
+++ b/app/assets/javascripts/Components/Preferences/PreferencesViewWrapper.tsx
@@ -1,28 +1,22 @@
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { observer } from 'mobx-react-lite'
-import { WebApplication } from '@/UIModels/Application'
-import { PreferencesView } from './PreferencesView'
-import { AppState } from '@/UIModels/AppState'
+import PreferencesView from './PreferencesView'
+import { PreferencesViewWrapperProps } from './PreferencesViewWrapperProps'
-export interface PreferencesViewWrapperProps {
- appState: AppState
- application: WebApplication
+const PreferencesViewWrapper: FunctionComponent = ({ appState, application }) => {
+ if (!appState.preferences?.isOpen) {
+ return null
+ }
+
+ return (
+ appState.preferences.closePreferences()}
+ application={application}
+ appState={appState}
+ mfaProvider={application}
+ userProvider={application}
+ />
+ )
}
-export const PreferencesViewWrapper: FunctionComponent = observer(
- ({ appState, application }) => {
- if (!appState.preferences?.isOpen) {
- return null
- }
-
- return (
- appState.preferences.closePreferences()}
- application={application}
- appState={appState}
- mfaProvider={application}
- userProvider={application}
- />
- )
- },
-)
+export default observer(PreferencesViewWrapper)
diff --git a/app/assets/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx b/app/assets/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx
new file mode 100644
index 000000000..95ad152f2
--- /dev/null
+++ b/app/assets/javascripts/Components/Preferences/PreferencesViewWrapperProps.tsx
@@ -0,0 +1,7 @@
+import { WebApplication } from '@/UIModels/Application'
+import { AppState } from '@/UIModels/AppState'
+
+export interface PreferencesViewWrapperProps {
+ appState: AppState
+ application: WebApplication
+}
diff --git a/app/assets/javascripts/Components/PremiumFeaturesModal/PremiumFeaturesModal.tsx b/app/assets/javascripts/Components/PremiumFeaturesModal/PremiumFeaturesModal.tsx
index 82a84aa27..dd934247e 100644
--- a/app/assets/javascripts/Components/PremiumFeaturesModal/PremiumFeaturesModal.tsx
+++ b/app/assets/javascripts/Components/PremiumFeaturesModal/PremiumFeaturesModal.tsx
@@ -1,8 +1,7 @@
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
-import { FunctionalComponent } from 'preact'
-import { Icon } from '@/Components/Icon/Icon'
+import { FunctionComponent, useCallback, useRef } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { PremiumIllustration } from '@standardnotes/icons'
-import { useCallback, useRef } from 'preact/hooks'
import { WebApplication } from '@/UIModels/Application'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
@@ -14,7 +13,7 @@ type Props = {
showModal: boolean
}
-export const PremiumFeaturesModal: FunctionalComponent = ({
+const PremiumFeaturesModal: FunctionComponent = ({
application,
featureName,
hasSubscription,
@@ -68,3 +67,5 @@ export const PremiumFeaturesModal: FunctionalComponent = ({
) : null
}
+
+export default PremiumFeaturesModal
diff --git a/app/assets/javascripts/Components/ProtectedNoteOverlay/ProtectedNoteOverlay.tsx b/app/assets/javascripts/Components/ProtectedNoteOverlay/ProtectedNoteOverlay.tsx
index fbb0d56bc..52399f8c1 100644
--- a/app/assets/javascripts/Components/ProtectedNoteOverlay/ProtectedNoteOverlay.tsx
+++ b/app/assets/javascripts/Components/ProtectedNoteOverlay/ProtectedNoteOverlay.tsx
@@ -6,7 +6,7 @@ type Props = {
hasProtectionSources: boolean
}
-export function ProtectedNoteOverlay({ appState, onViewNote, hasProtectionSources }: Props) {
+const ProtectedNoteOverlay = ({ appState, onViewNote, hasProtectionSources }: Props) => {
const instructionText = hasProtectionSources
? 'Authenticate to view this note.'
: 'Add a passcode or create an account to require authentication to view this note.'
@@ -33,3 +33,5 @@ export function ProtectedNoteOverlay({ appState, onViewNote, hasProtectionSource
)
}
+
+export default ProtectedNoteOverlay
diff --git a/app/assets/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx b/app/assets/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx
index 904675153..ea78c4321 100644
--- a/app/assets/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx
+++ b/app/assets/javascripts/Components/PurchaseFlow/Panes/CreateAccount.tsx
@@ -1,11 +1,10 @@
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { PurchaseFlowPane } from '@/UIModels/AppState/PurchaseFlowPane'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useEffect, useRef, useState } from 'preact/hooks'
-import { FloatingLabelInput } from '@/Components/Input/FloatingLabelInput'
+import { ChangeEventHandler, FunctionComponent, useEffect, useRef, useState } from 'react'
+import FloatingLabelInput from '@/Components/Input/FloatingLabelInput'
import { isEmailValid } from '@/Utils'
import { BlueDotIcon, CircleIcon, DiamondIcon, CreateAccountIllustration } from '@standardnotes/icons'
import { loadPurchaseFlowUrl } from '../PurchaseFlowFunctions'
@@ -15,7 +14,7 @@ type Props = {
application: WebApplication
}
-export const CreateAccount: FunctionComponent
= observer(({ appState, application }) => {
+const CreateAccount: FunctionComponent = ({ appState, application }) => {
const { setCurrentPane } = appState.purchaseFlow
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
@@ -34,24 +33,18 @@ export const CreateAccount: FunctionComponent = observer(({ appState, app
}
}, [])
- const handleEmailChange = (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setEmail(e.target.value)
- setIsEmailInvalid(false)
- }
+ const handleEmailChange: ChangeEventHandler = (e) => {
+ setEmail(e.target.value)
+ setIsEmailInvalid(false)
}
- const handlePasswordChange = (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setPassword(e.target.value)
- }
+ const handlePasswordChange: ChangeEventHandler = (e) => {
+ setPassword(e.target.value)
}
- const handleConfirmPasswordChange = (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setConfirmPassword(e.target.value)
- setIsPasswordNotMatching(false)
- }
+ const handleConfirmPasswordChange: ChangeEventHandler = (e) => {
+ setConfirmPassword(e.target.value)
+ setIsPasswordNotMatching(false)
}
const handleSignInInstead = () => {
@@ -196,4 +189,6 @@ export const CreateAccount: FunctionComponent = observer(({ appState, app
)
-})
+}
+
+export default observer(CreateAccount)
diff --git a/app/assets/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx b/app/assets/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx
index 2cf8f7e93..c4552f7d5 100644
--- a/app/assets/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx
+++ b/app/assets/javascripts/Components/PurchaseFlow/Panes/SignIn.tsx
@@ -1,11 +1,10 @@
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { PurchaseFlowPane } from '@/UIModels/AppState/PurchaseFlowPane'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useEffect, useRef, useState } from 'preact/hooks'
-import { FloatingLabelInput } from '@/Components/Input/FloatingLabelInput'
+import { ChangeEventHandler, FunctionComponent, useEffect, useRef, useState } from 'react'
+import FloatingLabelInput from '@/Components/Input/FloatingLabelInput'
import { isEmailValid } from '@/Utils'
import { BlueDotIcon, CircleIcon, DiamondIcon } from '@standardnotes/icons'
import { loadPurchaseFlowUrl } from '../PurchaseFlowFunctions'
@@ -15,7 +14,7 @@ type Props = {
application: WebApplication
}
-export const SignIn: FunctionComponent = observer(({ appState, application }) => {
+const SignIn: FunctionComponent = ({ appState, application }) => {
const { setCurrentPane } = appState.purchaseFlow
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
@@ -33,19 +32,15 @@ export const SignIn: FunctionComponent = observer(({ appState, applicatio
}
}, [])
- const handleEmailChange = (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setEmail(e.target.value)
- setIsEmailInvalid(false)
- }
+ const handleEmailChange: ChangeEventHandler = (e) => {
+ setEmail(e.target.value)
+ setIsEmailInvalid(false)
}
- const handlePasswordChange = (e: Event) => {
- if (e.target instanceof HTMLInputElement) {
- setPassword(e.target.value)
- setIsPasswordInvalid(false)
- setOtherErrorMessage('')
- }
+ const handlePasswordChange: ChangeEventHandler = (e) => {
+ setPassword(e.target.value)
+ setIsPasswordInvalid(false)
+ setOtherErrorMessage('')
}
const handleCreateAccountInstead = () => {
@@ -160,4 +155,6 @@ export const SignIn: FunctionComponent = observer(({ appState, applicatio
)
-})
+}
+
+export default observer(SignIn)
diff --git a/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx
index 13d42adcc..989e08907 100644
--- a/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx
+++ b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowView.tsx
@@ -2,9 +2,9 @@ import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { PurchaseFlowPane } from '@/UIModels/AppState/PurchaseFlowPane'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { CreateAccount } from './Panes/CreateAccount'
-import { SignIn } from './Panes/SignIn'
+import { FunctionComponent } from 'react'
+import CreateAccount from './Panes/CreateAccount'
+import SignIn from './Panes/SignIn'
import { SNLogoFull } from '@standardnotes/icons'
type PaneSelectorProps = {
@@ -25,7 +25,7 @@ const PurchaseFlowPaneSelector: FunctionComponent
= ({ curren
}
}
-export const PurchaseFlowView: FunctionComponent = observer(({ appState, application }) => {
+const PurchaseFlowView: FunctionComponent = ({ appState, application }) => {
const { currentPane } = appState.purchaseFlow
return (
@@ -56,4 +56,6 @@ export const PurchaseFlowView: FunctionComponent = observ
)
-})
+}
+
+export default observer(PurchaseFlowView)
diff --git a/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapper.tsx b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapper.tsx
index 3c4b943cd..ad529b456 100644
--- a/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapper.tsx
+++ b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapper.tsx
@@ -1,20 +1,14 @@
-import { WebApplication } from '@/UIModels/Application'
-import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { PurchaseFlowView } from './PurchaseFlowView'
+import { FunctionComponent } from 'react'
+import PurchaseFlowView from './PurchaseFlowView'
+import { PurchaseFlowWrapperProps } from './PurchaseFlowWrapperProps'
-export type PurchaseFlowWrapperProps = {
- appState: AppState
- application: WebApplication
+const PurchaseFlowWrapper: FunctionComponent = ({ appState, application }) => {
+ if (!appState.purchaseFlow.isOpen) {
+ return null
+ }
+
+ return
}
-export const PurchaseFlowWrapper: FunctionComponent = observer(
- ({ appState, application }) => {
- if (!appState.purchaseFlow.isOpen) {
- return null
- }
-
- return
- },
-)
+export default observer(PurchaseFlowWrapper)
diff --git a/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx
new file mode 100644
index 000000000..6d3dc4f6e
--- /dev/null
+++ b/app/assets/javascripts/Components/PurchaseFlow/PurchaseFlowWrapperProps.tsx
@@ -0,0 +1,7 @@
+import { WebApplication } from '@/UIModels/Application'
+import { AppState } from '@/UIModels/AppState'
+
+export type PurchaseFlowWrapperProps = {
+ appState: AppState
+ application: WebApplication
+}
diff --git a/app/assets/javascripts/Components/QuickSettingsMenu/EventHandlers.ts b/app/assets/javascripts/Components/QuickSettingsMenu/EventHandlers.ts
index 4cbe3b719..983a3ff20 100644
--- a/app/assets/javascripts/Components/QuickSettingsMenu/EventHandlers.ts
+++ b/app/assets/javascripts/Components/QuickSettingsMenu/EventHandlers.ts
@@ -1,10 +1,8 @@
-import { RefObject } from 'preact'
-import { StateUpdater } from 'preact/hooks'
-import { JSXInternal } from 'preact/src/jsx'
+import { Dispatch, RefObject, SetStateAction } from 'react'
export const quickSettingsKeyDownHandler = (
closeQuickSettingsMenu: () => void,
- event: JSXInternal.TargetedKeyboardEvent,
+ event: React.KeyboardEvent,
quickSettingsMenuRef: RefObject,
themesMenuOpen: boolean,
) => {
@@ -39,7 +37,7 @@ export const quickSettingsKeyDownHandler = (
export const themesMenuKeyDownHandler = (
event: React.KeyboardEvent,
themesMenuRef: RefObject,
- setThemesMenuOpen: StateUpdater,
+ setThemesMenuOpen: Dispatch>,
themesButtonRef: RefObject,
) => {
if (themesMenuRef?.current) {
diff --git a/app/assets/javascripts/Components/QuickSettingsMenu/FocusModeSwitch.tsx b/app/assets/javascripts/Components/QuickSettingsMenu/FocusModeSwitch.tsx
index c800c52a1..e099bbc96 100644
--- a/app/assets/javascripts/Components/QuickSettingsMenu/FocusModeSwitch.tsx
+++ b/app/assets/javascripts/Components/QuickSettingsMenu/FocusModeSwitch.tsx
@@ -1,11 +1,9 @@
import { WebApplication } from '@/UIModels/Application'
import { FeatureStatus, FeatureIdentifier } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useCallback } from 'preact/hooks'
-import { JSXInternal } from 'preact/src/jsx'
-import { Icon } from '@/Components/Icon/Icon'
+import { FunctionComponent, MouseEventHandler, useCallback } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
-import { Switch } from '@/Components/Switch/Switch'
+import Switch from '@/Components/Switch/Switch'
type Props = {
application: WebApplication
@@ -14,12 +12,12 @@ type Props = {
isEnabled: boolean
}
-export const FocusModeSwitch: FunctionComponent = ({ application, onToggle, onClose, isEnabled }) => {
+const FocusModeSwitch: FunctionComponent = ({ application, onToggle, onClose, isEnabled }) => {
const premiumModal = usePremiumModal()
const isEntitled = application.features.getFeatureStatus(FeatureIdentifier.FocusMode) === FeatureStatus.Entitled
- const toggle = useCallback(
- (e: JSXInternal.TargetedMouseEvent) => {
+ const toggle: MouseEventHandler = useCallback(
+ (e) => {
e.preventDefault()
if (isEntitled) {
@@ -50,3 +48,5 @@ export const FocusModeSwitch: FunctionComponent = ({ application, onToggl
>
)
}
+
+export default FocusModeSwitch
diff --git a/app/assets/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx b/app/assets/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx
index 3bbbc29c1..e8bca454c 100644
--- a/app/assets/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx
+++ b/app/assets/javascripts/Components/QuickSettingsMenu/QuickSettingsMenu.tsx
@@ -3,15 +3,13 @@ import { AppState } from '@/UIModels/AppState'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { ComponentArea, ContentType, FeatureIdentifier, GetFeatures, SNComponent } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
-import { JSXInternal } from 'preact/src/jsx'
-import { Icon } from '@/Components/Icon/Icon'
-import { Switch } from '@/Components/Switch/Switch'
+import { FunctionComponent, KeyboardEventHandler, useCallback, useEffect, useRef, useState } from 'react'
+import Icon from '@/Components/Icon/Icon'
+import Switch from '@/Components/Switch/Switch'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { quickSettingsKeyDownHandler, themesMenuKeyDownHandler } from './EventHandlers'
-import { FocusModeSwitch } from './FocusModeSwitch'
-import { ThemesMenuButton } from './ThemesMenuButton'
+import FocusModeSwitch from './FocusModeSwitch'
+import ThemesMenuButton from './ThemesMenuButton'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
import { ThemeItem } from './ThemeItem'
import { sortThemes } from '@/Utils/SortThemes'
@@ -40,7 +38,7 @@ const toggleFocusMode = (enabled: boolean) => {
}
}
-export const QuickSettingsMenu: FunctionComponent = observer(({ application, appState, onClickOutside }) => {
+const QuickSettingsMenu: FunctionComponent = ({ application, appState, onClickOutside }) => {
const { closeQuickSettingsMenu, shouldAnimateCloseMenu, focusModeEnabled, setFocusModeEnabled } =
appState.quickSettingsMenu
const [themes, setThemes] = useState([])
@@ -188,7 +186,7 @@ export const QuickSettingsMenu: FunctionComponent = observer(({ appli
[themesMenuOpen, toggleThemesMenu],
)
- const handleQuickSettingsKeyDown: JSXInternal.KeyboardEventHandler = useCallback(
+ const handleQuickSettingsKeyDown: KeyboardEventHandler = useCallback(
(event) => {
quickSettingsKeyDownHandler(closeQuickSettingsMenu, event, quickSettingsMenuRef, themesMenuOpen)
},
@@ -264,6 +262,7 @@ export const QuickSettingsMenu: FunctionComponent = observer(({ appli
onClick={() => {
toggleComponent(component)
}}
+ key={component.uuid}
>
@@ -290,4 +289,6 @@ export const QuickSettingsMenu: FunctionComponent = observer(({ appli
)
-})
+}
+
+export default observer(QuickSettingsMenu)
diff --git a/app/assets/javascripts/Components/QuickSettingsMenu/ThemesMenuButton.tsx b/app/assets/javascripts/Components/QuickSettingsMenu/ThemesMenuButton.tsx
index ce3bef119..18fd7cf0a 100644
--- a/app/assets/javascripts/Components/QuickSettingsMenu/ThemesMenuButton.tsx
+++ b/app/assets/javascripts/Components/QuickSettingsMenu/ThemesMenuButton.tsx
@@ -1,11 +1,9 @@
import { WebApplication } from '@/UIModels/Application'
import { FeatureStatus } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useCallback, useMemo } from 'preact/hooks'
-import { JSXInternal } from 'preact/src/jsx'
-import { Icon } from '@/Components/Icon/Icon'
+import { FunctionComponent, MouseEventHandler, useCallback, useMemo } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
-import { Switch } from '@/Components/Switch/Switch'
+import Switch from '@/Components/Switch/Switch'
import { ThemeItem } from './ThemeItem'
type Props = {
@@ -14,7 +12,7 @@ type Props = {
onBlur: (event: { relatedTarget: EventTarget | null }) => void
}
-export const ThemesMenuButton: FunctionComponent = ({ application, item, onBlur }) => {
+const ThemesMenuButton: FunctionComponent = ({ application, item, onBlur }) => {
const premiumModal = usePremiumModal()
const isThirdPartyTheme = useMemo(
@@ -27,7 +25,7 @@ export const ThemesMenuButton: FunctionComponent = ({ application, item,
)
const canActivateTheme = useMemo(() => isEntitledToTheme || isThirdPartyTheme, [isEntitledToTheme, isThirdPartyTheme])
- const toggleTheme: JSXInternal.MouseEventHandler = useCallback(
+ const toggleTheme: MouseEventHandler = useCallback(
(e) => {
e.preventDefault()
@@ -79,3 +77,5 @@ export const ThemesMenuButton: FunctionComponent = ({ application, item,
)
}
+
+export default ThemesMenuButton
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListContainer.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListContainer.tsx
index 871d7765c..57e8bd5d6 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListContainer.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListContainer.tsx
@@ -1,11 +1,10 @@
import { WebApplication } from '@/UIModels/Application'
import { Action, ActionVerb, HistoryEntry, NoteHistoryEntry, RevisionListEntry, SNNote } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { StateUpdater, useCallback, useState, useEffect } from 'preact/hooks'
-import { LegacyHistoryList } from './LegacyHistoryList'
-import { RemoteHistoryList } from './RemoteHistoryList'
-import { SessionHistoryList } from './SessionHistoryList'
+import { FunctionComponent, useCallback, useState, useEffect, SetStateAction, Dispatch } from 'react'
+import LegacyHistoryList from './LegacyHistoryList'
+import RemoteHistoryList from './RemoteHistoryList'
+import SessionHistoryList from './SessionHistoryList'
import { LegacyHistoryEntry, RemoteRevisionListGroup, sortRevisionListIntoGroups } from './utils'
export enum RevisionListTabType {
@@ -19,169 +18,169 @@ type Props = {
isFetchingRemoteHistory: boolean
note: SNNote
remoteHistory: RemoteRevisionListGroup[] | undefined
- setIsFetchingSelectedRevision: StateUpdater
- setSelectedRemoteEntry: StateUpdater
- setSelectedRevision: StateUpdater
- setShowContentLockedScreen: StateUpdater
+ setIsFetchingSelectedRevision: Dispatch>
+ setSelectedRemoteEntry: Dispatch>
+ setSelectedRevision: Dispatch>
+ setShowContentLockedScreen: Dispatch>
}
-export const HistoryListContainer: FunctionComponent = observer(
- ({
- application,
- isFetchingRemoteHistory,
- note,
- remoteHistory,
- setIsFetchingSelectedRevision,
- setSelectedRemoteEntry,
- setSelectedRevision,
- setShowContentLockedScreen,
- }) => {
- const sessionHistory = sortRevisionListIntoGroups(
- application.historyManager.sessionHistoryForItem(note) as NoteHistoryEntry[],
- )
- const [legacyHistory, setLegacyHistory] = useState()
+const HistoryListContainer: FunctionComponent = ({
+ application,
+ isFetchingRemoteHistory,
+ note,
+ remoteHistory,
+ setIsFetchingSelectedRevision,
+ setSelectedRemoteEntry,
+ setSelectedRevision,
+ setShowContentLockedScreen,
+}) => {
+ const sessionHistory = sortRevisionListIntoGroups(
+ application.historyManager.sessionHistoryForItem(note) as NoteHistoryEntry[],
+ )
+ const [legacyHistory, setLegacyHistory] = useState()
- const [selectedTab, setSelectedTab] = useState(RevisionListTabType.Remote)
+ const [selectedTab, setSelectedTab] = useState(RevisionListTabType.Remote)
- useEffect(() => {
- const fetchLegacyHistory = async () => {
- const actionExtensions = application.actionsManager.getExtensions()
- actionExtensions.forEach(async (ext) => {
- const actionExtension = await application.actionsManager.loadExtensionInContextOfItem(ext, note)
+ useEffect(() => {
+ const fetchLegacyHistory = async () => {
+ const actionExtensions = application.actionsManager.getExtensions()
+ actionExtensions.forEach(async (ext) => {
+ const actionExtension = await application.actionsManager.loadExtensionInContextOfItem(ext, note)
- if (!actionExtension) {
- return
- }
+ if (!actionExtension) {
+ return
+ }
- const isLegacyNoteHistoryExt = actionExtension?.actions.some((action) => action.verb === ActionVerb.Nested)
+ const isLegacyNoteHistoryExt = actionExtension?.actions.some((action) => action.verb === ActionVerb.Nested)
- if (!isLegacyNoteHistoryExt) {
- return
- }
+ if (!isLegacyNoteHistoryExt) {
+ return
+ }
- const legacyHistoryEntries = actionExtension.actions.filter((action) => action.subactions?.[0])
+ const legacyHistoryEntries = actionExtension.actions.filter((action) => action.subactions?.[0])
- setLegacyHistory(legacyHistoryEntries)
- })
- }
-
- fetchLegacyHistory().catch(console.error)
- }, [application, note])
-
- const TabButton: FunctionComponent<{
- type: RevisionListTabType
- }> = ({ type }) => {
- const isSelected = selectedTab === type
-
- return (
- {
- setSelectedTab(type)
- setSelectedRemoteEntry(undefined)
- }}
- >
- {type}
-
- )
+ setLegacyHistory(legacyHistoryEntries)
+ })
}
- const fetchAndSetLegacyRevision = useCallback(
- async (revisionListEntry: Action) => {
- setSelectedRemoteEntry(undefined)
+ fetchLegacyHistory().catch(console.error)
+ }, [application, note])
+
+ const TabButton: FunctionComponent<{
+ type: RevisionListTabType
+ }> = ({ type }) => {
+ const isSelected = selectedTab === type
+
+ return (
+ {
+ setSelectedTab(type)
+ setSelectedRemoteEntry(undefined)
+ }}
+ >
+ {type}
+
+ )
+ }
+
+ const fetchAndSetLegacyRevision = useCallback(
+ async (revisionListEntry: Action) => {
+ setSelectedRemoteEntry(undefined)
+ setSelectedRevision(undefined)
+ setIsFetchingSelectedRevision(true)
+
+ try {
+ if (!revisionListEntry.subactions?.[0]) {
+ throw new Error('Could not find revision action url')
+ }
+
+ const response = await application.actionsManager.runAction(revisionListEntry.subactions[0], note)
+
+ if (!response) {
+ throw new Error('Could not fetch revision')
+ }
+
+ setSelectedRevision(response.item as unknown as HistoryEntry)
+ } catch (error) {
+ console.error(error)
setSelectedRevision(undefined)
+ } finally {
+ setIsFetchingSelectedRevision(false)
+ }
+ },
+ [application.actionsManager, note, setIsFetchingSelectedRevision, setSelectedRemoteEntry, setSelectedRevision],
+ )
+
+ const fetchAndSetRemoteRevision = useCallback(
+ async (revisionListEntry: RevisionListEntry) => {
+ setShowContentLockedScreen(false)
+
+ if (application.features.hasMinimumRole(revisionListEntry.required_role)) {
setIsFetchingSelectedRevision(true)
+ setSelectedRevision(undefined)
+ setSelectedRemoteEntry(undefined)
try {
- if (!revisionListEntry.subactions?.[0]) {
- throw new Error('Could not find revision action url')
- }
-
- const response = await application.actionsManager.runAction(revisionListEntry.subactions[0], note)
-
- if (!response) {
- throw new Error('Could not fetch revision')
- }
-
- setSelectedRevision(response.item as unknown as HistoryEntry)
- } catch (error) {
- console.error(error)
- setSelectedRevision(undefined)
+ const remoteRevision = await application.historyManager.fetchRemoteRevision(note, revisionListEntry)
+ setSelectedRevision(remoteRevision)
+ setSelectedRemoteEntry(revisionListEntry)
+ } catch (err) {
+ console.error(err)
} finally {
setIsFetchingSelectedRevision(false)
}
- },
- [application.actionsManager, note, setIsFetchingSelectedRevision, setSelectedRemoteEntry, setSelectedRevision],
- )
+ } else {
+ setShowContentLockedScreen(true)
+ setSelectedRevision(undefined)
+ }
+ },
+ [
+ application,
+ note,
+ setIsFetchingSelectedRevision,
+ setSelectedRemoteEntry,
+ setSelectedRevision,
+ setShowContentLockedScreen,
+ ],
+ )
- const fetchAndSetRemoteRevision = useCallback(
- async (revisionListEntry: RevisionListEntry) => {
- setShowContentLockedScreen(false)
-
- if (application.features.hasMinimumRole(revisionListEntry.required_role)) {
- setIsFetchingSelectedRevision(true)
- setSelectedRevision(undefined)
- setSelectedRemoteEntry(undefined)
-
- try {
- const remoteRevision = await application.historyManager.fetchRemoteRevision(note, revisionListEntry)
- setSelectedRevision(remoteRevision)
- setSelectedRemoteEntry(revisionListEntry)
- } catch (err) {
- console.error(err)
- } finally {
- setIsFetchingSelectedRevision(false)
- }
- } else {
- setShowContentLockedScreen(true)
- setSelectedRevision(undefined)
- }
- },
- [
- application,
- note,
- setIsFetchingSelectedRevision,
- setSelectedRemoteEntry,
- setSelectedRevision,
- setShowContentLockedScreen,
- ],
- )
-
- return (
-
-
-
-
- {legacyHistory && legacyHistory.length > 0 && }
-
-
- {selectedTab === RevisionListTabType.Session && (
-
- )}
- {selectedTab === RevisionListTabType.Remote && (
-
- )}
- {selectedTab === RevisionListTabType.Legacy && (
-
- )}
-
+ return (
+
+
+
+
+ {legacyHistory && legacyHistory.length > 0 && }
- )
- },
-)
+
+ {selectedTab === RevisionListTabType.Session && (
+
+ )}
+ {selectedTab === RevisionListTabType.Remote && (
+
+ )}
+ {selectedTab === RevisionListTabType.Legacy && (
+
+ )}
+
+
+ )
+}
+
+export default observer(HistoryListContainer)
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListItem.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListItem.tsx
index 4ee116cbe..6b9821366 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListItem.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/HistoryListItem.tsx
@@ -1,12 +1,12 @@
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
type HistoryListItemProps = {
isSelected: boolean
onClick: () => void
}
-export const HistoryListItem: FunctionComponent
= ({ children, isSelected, onClick }) => {
+const HistoryListItem: FunctionComponent = ({ children, isSelected, onClick }) => {
return (
= ({ child
)
}
+
+export default HistoryListItem
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/LegacyHistoryList.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/LegacyHistoryList.tsx
index 2b9c468e5..57d09ab8c 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/LegacyHistoryList.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/LegacyHistoryList.tsx
@@ -1,18 +1,17 @@
import { Action, HistoryEntry, RevisionListEntry } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { StateUpdater, useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
+import { Dispatch, FunctionComponent, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useListKeyboardNavigation } from '@/Hooks/useListKeyboardNavigation'
-import { HistoryListItem } from './HistoryListItem'
+import HistoryListItem from './HistoryListItem'
import { LegacyHistoryEntry } from './utils'
type Props = {
legacyHistory: Action[] | undefined
- setSelectedRevision: StateUpdater
- setSelectedRemoteEntry: StateUpdater
+ setSelectedRevision: Dispatch>
+ setSelectedRemoteEntry: Dispatch>
fetchAndSetLegacyRevision: (revisionListEntry: Action) => Promise
}
-export const LegacyHistoryList: FunctionComponent = ({
+const LegacyHistoryList: FunctionComponent = ({
legacyHistory,
setSelectedRevision,
setSelectedRemoteEntry,
@@ -72,3 +71,5 @@ export const LegacyHistoryList: FunctionComponent = ({
)
}
+
+export default LegacyHistoryList
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/RemoteHistoryList.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/RemoteHistoryList.tsx
index c940e4793..2c392e1ea 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/RemoteHistoryList.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/RemoteHistoryList.tsx
@@ -1,11 +1,10 @@
import { WebApplication } from '@/UIModels/Application'
import { RevisionListEntry } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { Fragment, FunctionComponent } from 'preact'
-import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
-import { Icon } from '@/Components/Icon/Icon'
+import { Fragment, FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import Icon from '@/Components/Icon/Icon'
import { useListKeyboardNavigation } from '@/Hooks/useListKeyboardNavigation'
-import { HistoryListItem } from './HistoryListItem'
+import HistoryListItem from './HistoryListItem'
import { previewHistoryEntryTitle, RemoteRevisionListGroup } from './utils'
type RemoteHistoryListProps = {
@@ -15,76 +14,78 @@ type RemoteHistoryListProps = {
fetchAndSetRemoteRevision: (revisionListEntry: RevisionListEntry) => Promise
}
-export const RemoteHistoryList: FunctionComponent = observer(
- ({ application, remoteHistory, isFetchingRemoteHistory, fetchAndSetRemoteRevision }) => {
- const remoteHistoryListRef = useRef(null)
+const RemoteHistoryList: FunctionComponent = ({
+ application,
+ remoteHistory,
+ isFetchingRemoteHistory,
+ fetchAndSetRemoteRevision,
+}) => {
+ const remoteHistoryListRef = useRef(null)
- useListKeyboardNavigation(remoteHistoryListRef)
+ useListKeyboardNavigation(remoteHistoryListRef)
- const remoteHistoryLength = useMemo(
- () => remoteHistory?.map((group) => group.entries).flat().length,
- [remoteHistory],
- )
+ const remoteHistoryLength = useMemo(() => remoteHistory?.map((group) => group.entries).flat().length, [remoteHistory])
- const [selectedEntryUuid, setSelectedEntryUuid] = useState('')
+ const [selectedEntryUuid, setSelectedEntryUuid] = useState('')
- const firstEntry = useMemo(() => {
- return remoteHistory?.find((group) => group.entries?.length)?.entries?.[0]
- }, [remoteHistory])
+ const firstEntry = useMemo(() => {
+ return remoteHistory?.find((group) => group.entries?.length)?.entries?.[0]
+ }, [remoteHistory])
- const selectFirstEntry = useCallback(() => {
- if (firstEntry) {
- setSelectedEntryUuid(firstEntry.uuid)
- fetchAndSetRemoteRevision(firstEntry).catch(console.error)
- }
- }, [fetchAndSetRemoteRevision, firstEntry])
+ const selectFirstEntry = useCallback(() => {
+ if (firstEntry) {
+ setSelectedEntryUuid(firstEntry.uuid)
+ fetchAndSetRemoteRevision(firstEntry).catch(console.error)
+ }
+ }, [fetchAndSetRemoteRevision, firstEntry])
- useEffect(() => {
- if (firstEntry && !selectedEntryUuid.length) {
- selectFirstEntry()
- }
- }, [fetchAndSetRemoteRevision, firstEntry, remoteHistory, selectFirstEntry, selectedEntryUuid.length])
+ useEffect(() => {
+ if (firstEntry && !selectedEntryUuid.length) {
+ selectFirstEntry()
+ }
+ }, [fetchAndSetRemoteRevision, firstEntry, remoteHistory, selectFirstEntry, selectedEntryUuid.length])
- return (
-
- {isFetchingRemoteHistory &&
}
- {remoteHistory?.map((group) => {
- if (group.entries && group.entries.length) {
- return (
-
-
- {group.title}
-
- {group.entries.map((entry) => (
- {
- setSelectedEntryUuid(entry.uuid)
- fetchAndSetRemoteRevision(entry).catch(console.error)
- }}
- >
-
-
{previewHistoryEntryTitle(entry)}
- {!application.features.hasMinimumRole(entry.required_role) &&
}
-
-
- ))}
-
- )
- } else {
- return null
- }
- })}
- {!remoteHistoryLength && !isFetchingRemoteHistory && (
-
No remote history found
- )}
-
- )
- },
-)
+ return (
+
+ {isFetchingRemoteHistory &&
}
+ {remoteHistory?.map((group) => {
+ if (group.entries && group.entries.length) {
+ return (
+
+
+ {group.title}
+
+ {group.entries.map((entry) => (
+ {
+ setSelectedEntryUuid(entry.uuid)
+ fetchAndSetRemoteRevision(entry).catch(console.error)
+ }}
+ >
+
+
{previewHistoryEntryTitle(entry)}
+ {!application.features.hasMinimumRole(entry.required_role) &&
}
+
+
+ ))}
+
+ )
+ } else {
+ return null
+ }
+ })}
+ {!remoteHistoryLength && !isFetchingRemoteHistory && (
+
No remote history found
+ )}
+
+ )
+}
+
+export default observer(RemoteHistoryList)
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx
index f22885185..52edcbf95 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/RevisionContentLocked.tsx
@@ -1,8 +1,8 @@
import { AppState } from '@/UIModels/AppState'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
+import { FunctionComponent } from 'react'
import { HistoryLockedIllustration } from '@standardnotes/icons'
-import { Button } from '@/Components/Button/Button'
+import Button from '@/Components/Button/Button'
const getPlanHistoryDuration = (planName: string | undefined) => {
switch (planName) {
@@ -19,16 +19,18 @@ const getPremiumContentCopy = (planName: string | undefined) => {
return `Version history is limited to ${getPlanHistoryDuration(planName)} in the ${planName} plan`
}
-export const RevisionContentLocked: FunctionComponent<{
+type Props = {
appState: AppState
-}> = observer(({ appState }) => {
+}
+
+const RevisionContentLocked: FunctionComponent = ({ appState }) => {
const { userSubscriptionName, isUserSubscriptionExpired, isUserSubscriptionCanceled } = appState.subscription
return (
-
Can't access this version
+
Can't access this version
{getPremiumContentCopy(
!isUserSubscriptionCanceled && !isUserSubscriptionExpired && userSubscriptionName
@@ -49,4 +51,6 @@ export const RevisionContentLocked: FunctionComponent<{
)
-})
+}
+
+export default observer(RevisionContentLocked)
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/RevisionHistoryModalWrapper.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/RevisionHistoryModalWrapper.tsx
index 5b483b67c..24d54382a 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/RevisionHistoryModalWrapper.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/RevisionHistoryModalWrapper.tsx
@@ -13,12 +13,11 @@ import {
SNNote,
} from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
-import { Button } from '@/Components/Button/Button'
-import { HistoryListContainer } from './HistoryListContainer'
-import { RevisionContentLocked } from './RevisionContentLocked'
-import { SelectedRevisionContent } from './SelectedRevisionContent'
+import { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import Button from '@/Components/Button/Button'
+import HistoryListContainer from './HistoryListContainer'
+import RevisionContentLocked from './RevisionContentLocked'
+import SelectedRevisionContent from './SelectedRevisionContent'
import { LegacyHistoryEntry, RemoteRevisionListGroup, sortRevisionListIntoGroups } from './utils'
type RevisionHistoryModalProps = {
@@ -209,6 +208,7 @@ export const RevisionHistoryModal: FunctionComponent
aria-label="Note revision history"
>
/>
{selectedRevision && (
-
+
{selectedRemoteEntry && (
{isDeletingRevision ? (
@@ -291,12 +291,14 @@ export const RevisionHistoryModal: FunctionComponent
},
)
-export const RevisionHistoryModalWrapper: FunctionComponent = observer(
- ({ application, appState }) => {
- if (!appState.notes.showRevisionHistoryModal) {
- return null
- }
+RevisionHistoryModal.displayName = 'RevisionHistoryModal'
- return
- },
-)
+const RevisionHistoryModalWrapper: FunctionComponent = ({ application, appState }) => {
+ if (!appState.notes.showRevisionHistoryModal) {
+ return null
+ }
+
+ return
+}
+
+export default observer(RevisionHistoryModalWrapper)
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/SelectedRevisionContent.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/SelectedRevisionContent.tsx
index 9b87e6eb3..4257ba0e3 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/SelectedRevisionContent.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/SelectedRevisionContent.tsx
@@ -2,9 +2,8 @@ import { WebApplication } from '@/UIModels/Application'
import { AppState } from '@/UIModels/AppState'
import { HistoryEntry, SNComponent, SNNote } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
-import { FunctionComponent } from 'preact'
-import { useEffect, useMemo } from 'preact/hooks'
-import { ComponentView } from '@/Components/ComponentView/ComponentView'
+import { FunctionComponent, useEffect, useMemo } from 'react'
+import ComponentView from '@/Components/ComponentView/ComponentView'
import { LegacyHistoryEntry } from './utils'
const ABSOLUTE_CENTER_CLASSNAME = 'absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'
@@ -17,58 +16,64 @@ type SelectedRevisionContentProps = {
templateNoteForRevision: SNNote
}
-export const SelectedRevisionContent: FunctionComponent = observer(
- ({ application, appState, selectedRevision, editorForCurrentNote, templateNoteForRevision }) => {
- const componentViewer = useMemo(() => {
- if (!editorForCurrentNote) {
- return undefined
+const SelectedRevisionContent: FunctionComponent = ({
+ application,
+ appState,
+ selectedRevision,
+ editorForCurrentNote,
+ templateNoteForRevision,
+}) => {
+ const componentViewer = useMemo(() => {
+ if (!editorForCurrentNote) {
+ return undefined
+ }
+
+ const componentViewer = application.componentManager.createComponentViewer(editorForCurrentNote)
+ componentViewer.setReadonly(true)
+ componentViewer.lockReadonly = true
+ componentViewer.overrideContextItem = templateNoteForRevision
+ return componentViewer
+ }, [application, editorForCurrentNote, templateNoteForRevision])
+
+ useEffect(() => {
+ return () => {
+ if (componentViewer) {
+ application.componentManager.destroyComponentViewer(componentViewer)
}
+ }
+ }, [application, componentViewer])
- const componentViewer = application.componentManager.createComponentViewer(editorForCurrentNote)
- componentViewer.setReadonly(true)
- componentViewer.lockReadonly = true
- componentViewer.overrideContextItem = templateNoteForRevision
- return componentViewer
- }, [application, editorForCurrentNote, templateNoteForRevision])
-
- useEffect(() => {
- return () => {
- if (componentViewer) {
- application.componentManager.destroyComponentViewer(componentViewer)
- }
- }
- }, [application, componentViewer])
-
- return (
-
-
-
{selectedRevision.payload.content.title}
-
- {!componentViewer && (
-
- {selectedRevision.payload.content.text.length ? (
-
- ) : (
-
Empty note.
- )}
-
- )}
- {componentViewer && (
-
-
-
- )}
+ return (
+
+
+
{selectedRevision.payload.content.title}
- )
- },
-)
+ {!componentViewer && (
+
+ {selectedRevision.payload.content.text.length ? (
+
+ ) : (
+
Empty note.
+ )}
+
+ )}
+ {componentViewer && (
+
+
+
+ )}
+
+ )
+}
+
+export default observer(SelectedRevisionContent)
diff --git a/app/assets/javascripts/Components/RevisionHistoryModal/SessionHistoryList.tsx b/app/assets/javascripts/Components/RevisionHistoryModal/SessionHistoryList.tsx
index 205730c69..68fedccd5 100644
--- a/app/assets/javascripts/Components/RevisionHistoryModal/SessionHistoryList.tsx
+++ b/app/assets/javascripts/Components/RevisionHistoryModal/SessionHistoryList.tsx
@@ -1,17 +1,26 @@
import { HistoryEntry, NoteHistoryEntry, RevisionListEntry } from '@standardnotes/snjs'
-import { Fragment, FunctionComponent } from 'preact'
-import { StateUpdater, useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
+import {
+ Dispatch,
+ Fragment,
+ FunctionComponent,
+ SetStateAction,
+ useCallback,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+} from 'react'
import { useListKeyboardNavigation } from '@/Hooks/useListKeyboardNavigation'
-import { HistoryListItem } from './HistoryListItem'
+import HistoryListItem from './HistoryListItem'
import { LegacyHistoryEntry, ListGroup } from './utils'
type Props = {
sessionHistory: ListGroup
[]
- setSelectedRevision: StateUpdater
- setSelectedRemoteEntry: StateUpdater
+ setSelectedRevision: Dispatch>
+ setSelectedRemoteEntry: Dispatch>
}
-export const SessionHistoryList: FunctionComponent = ({
+const SessionHistoryList: FunctionComponent = ({
sessionHistory,
setSelectedRevision,
setSelectedRemoteEntry,
@@ -83,3 +92,5 @@ export const SessionHistoryList: FunctionComponent = ({
)
}
+
+export default SessionHistoryList
diff --git a/app/assets/javascripts/Components/SearchOptions/SearchOptions.tsx b/app/assets/javascripts/Components/SearchOptions/SearchOptions.tsx
index 3fbd8a6ce..6bc2bb04d 100644
--- a/app/assets/javascripts/Components/SearchOptions/SearchOptions.tsx
+++ b/app/assets/javascripts/Components/SearchOptions/SearchOptions.tsx
@@ -2,14 +2,14 @@ import { AppState } from '@/UIModels/AppState'
import { WebApplication } from '@/UIModels/Application'
import { observer } from 'mobx-react-lite'
import Bubble from '@/Components/Bubble/Bubble'
-import { useCallback } from 'preact/hooks'
+import { useCallback } from 'react'
type Props = {
appState: AppState
application: WebApplication
}
-export const SearchOptions = observer(({ appState }: Props) => {
+const SearchOptions = ({ appState }: Props) => {
const { searchOptions } = appState
const { includeProtectedContents, includeArchived, includeTrashed } = searchOptions
@@ -31,4 +31,6 @@ export const SearchOptions = observer(({ appState }: Props) => {
)
-})
+}
+
+export default observer(SearchOptions)
diff --git a/app/assets/javascripts/Components/SessionsModal/SessionsModal.tsx b/app/assets/javascripts/Components/SessionsModal/SessionsModal.tsx
index df6ff0f17..833cf791d 100644
--- a/app/assets/javascripts/Components/SessionsModal/SessionsModal.tsx
+++ b/app/assets/javascripts/Components/SessionsModal/SessionsModal.tsx
@@ -1,7 +1,6 @@
import { AppState } from '@/UIModels/AppState'
import { SNApplication, SessionStrings, UuidString, isNullOrUndefined, RemoteSession } from '@standardnotes/snjs'
-import { FunctionComponent } from 'preact'
-import { useState, useEffect, useRef, useMemo } from 'preact/hooks'
+import { FunctionComponent, useState, useEffect, useRef, useMemo } from 'react'
import { Dialog } from '@reach/dialog'
import { Alert } from '@reach/alert'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
@@ -103,23 +102,23 @@ const SessionsModalContent: FunctionComponent<{
<>