refactor: replace 'preact' with 'react' (#1048)

This commit is contained in:
Aman Harwara
2022-05-30 12:42:52 +05:30
committed by GitHub
parent e74b4953ea
commit 8c368dd96b
231 changed files with 4794 additions and 4302 deletions

View File

@@ -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<Props> = ({ application, appState }) => {
const Backups: FunctionComponent<Props> = ({ application, appState }) => {
return (
<PreferencesPane>
<DataBackups application={application} appState={appState} />
<FileBackups application={application} />
<FileBackupsCrossPlatform application={application} />
<EmailBackups application={application} />
<CloudLink application={application} />
</PreferencesPane>
)
}
export default observer(Backups)

View File

@@ -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<Props> = ({
application,
providerName,
isEntitledToCloudBackups,
}) => {
const CloudBackupProvider: FunctionComponent<Props> = ({ application, providerName, isEntitledToCloudBackups }) => {
const [authBegan, setAuthBegan] = useState(false)
const [successfullyInstalled, setSuccessfullyInstalled] = useState(false)
const [backupFrequency, setBackupFrequency] = useState<string | undefined>(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<Props> = ({
}
}
const installIntegration = (event: Event) => {
const installIntegration: MouseEventHandler = (event) => {
if (!isEntitledToCloudBackups) {
return
}
@@ -117,7 +120,7 @@ export const CloudBackupProvider: FunctionComponent<Props> = ({
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<Props> = ({
}
}
const handleChange = (event: Event) => {
setConfirmation((event.target as HTMLInputElement).value)
const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {
setConfirmation(event.target.value)
}
const getIntegrationStatus = useCallback(async () => {
@@ -219,3 +222,5 @@ export const CloudBackupProvider: FunctionComponent<Props> = ({
</div>
)
}
export default CloudBackupProvider

View File

@@ -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<Props> = ({ application }) => {
const CloudLink: FunctionComponent<Props> = ({ application }) => {
const [isEntitledToCloudBackups, setIsEntitledToCloudBackups] = useState(false)
const [isFailedCloudBackupEmailMuted, setIsFailedCloudBackupEmailMuted] = useState(true)
const [isLoading, setIsLoading] = useState(false)
@@ -121,14 +116,14 @@ export const CloudLink: FunctionComponent<Props> = ({ application }) => {
<HorizontalSeparator classes={`mt-3 mb-3 ${additionalClass}`} />
<div>
{providerData.map(({ name }) => (
<>
<Fragment key={name}>
<CloudBackupProvider
application={application}
providerName={name}
isEntitledToCloudBackups={isEntitledToCloudBackups}
/>
<HorizontalSeparator classes={`mt-3 mb-3 ${additionalClass}`} />
</>
</Fragment>
))}
</div>
</div>
@@ -155,3 +150,5 @@ export const CloudLink: FunctionComponent<Props> = ({ application }) => {
</PreferencesGroup>
)
}
export default CloudLink

View File

@@ -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<HTMLInputElement>(null)
const [isImportDataLoading, setIsImportDataLoading] = useState(false)
const {
@@ -109,8 +104,8 @@ export const DataBackups = observer(({ application, appState }: Props) => {
})
}
const importFileSelected = async (event: TargetedEvent<HTMLInputElement, Event>) => {
const { files } = event.target as HTMLInputElement
const importFileSelected: ChangeEventHandler<HTMLInputElement> = 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<HTMLSpanElement, Event> | KeyboardEvent) => {
const handleImportFile: MouseEventHandler = (event) => {
if (event instanceof KeyboardEvent) {
const { code } = event
@@ -158,7 +153,7 @@ export const DataBackups = observer(({ application, appState }: Props) => {
<PreferencesSegment>
<Title>Data Backups</Title>
{!isDesktopApplication() && (
{isDesktopApplication() && (
<Text className="mb-3">
Backups are automatically created on desktop and can be managed via the "Backups" top-level menu.
</Text>
@@ -183,10 +178,11 @@ export const DataBackups = observer(({ application, appState }: Props) => {
<Button variant="normal" onClick={downloadDataArchive} label="Download backup" className="mt-2" />
</PreferencesSegment>
<HorizontalSeparator classes="my-4" />
<PreferencesSegment>
<Subtitle>Import a previously saved backup file</Subtitle>
<div class="flex flex-row items-center mt-3">
<div className="flex flex-row items-center mt-3">
<Button variant="normal" label="Import backup" onClick={handleImportFile} />
<input type="file" ref={fileInputRef} onChange={importFileSelected} className="hidden" />
{isImportDataLoading && <div className="sk-spinner normal info ml-4" />}
@@ -195,4 +191,6 @@ export const DataBackups = observer(({ application, appState }: Props) => {
</PreferencesGroup>
</>
)
})
}
export default observer(DataBackups)

View File

@@ -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>(EmailBackupFrequency.Disabled)
const [emailFrequencyOptions, setEmailFrequencyOptions] = useState<DropdownItem[]>([])
@@ -132,7 +129,7 @@ export const EmailBackups = observer(({ application }: Props) => {
</a>
.
</Text>
<HorizontalSeparator classes="mt-3 mb-3" />
<HorizontalSeparator classes="my-4" />
</>
)}
<div className={isEntitledToEmailBackups ? '' : 'faded cursor-default pointer-events-none'}>
@@ -157,7 +154,7 @@ export const EmailBackups = observer(({ application }: Props) => {
/>
)}
</div>
<HorizontalSeparator classes="mt-5 mb-4" />
<HorizontalSeparator classes="my-4" />
<Subtitle>Email preferences</Subtitle>
<div className="flex items-center justify-between">
<div className="flex flex-col">
@@ -177,4 +174,6 @@ export const EmailBackups = observer(({ application }: Props) => {
</PreferencesSegment>
</PreferencesGroup>
)
})
}
export default observer(EmailBackups)

View File

@@ -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<Props> = ({ application }) => {
const BackupsDropZone: FunctionComponent<Props> = ({ application }) => {
const [droppedFile, setDroppedFile] = useState<FileBackupMetadataFile | undefined>(undefined)
const [decryptedFileItem, setDecryptedFileItem] = useState<FileItem | undefined>(undefined)
const [binaryFile, setBinaryFile] = useState<FileHandleRead | undefined>(undefined)
@@ -225,3 +225,5 @@ export const BackupsDropZone: FunctionComponent<Props> = ({ application }) => {
</>
)
}
export default BackupsDropZone

View File

@@ -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 ? (
<FileBackupsDesktop application={application} backupsService={fileBackupsService} />
) : (
<>
<PreferencesGroup>
<PreferencesSegment>
<Title>File Backups</Title>
<Subtitle>Automatically save encrypted backups of files uploaded to any device to this computer.</Subtitle>
<Text className="mt-3">To enable file backups, use the Standard Notes desktop application.</Text>
</PreferencesSegment>
<PreferencesSegment>
<BackupsDropZone application={application} />
</PreferencesSegment>
</PreferencesGroup>
</>
)
}
export default FileBackupsCrossPlatform

View File

@@ -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<WebApplication['fileBackups']>
}
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 (
<>
<PreferencesGroup>
<PreferencesSegment>
<Title>File Backups</Title>
<Subtitle>Automatically save encrypted backups of files uploaded to any device to this computer.</Subtitle>
<Text className="mt-3">To enable file backups, use the Standard Notes desktop application.</Text>
</PreferencesSegment>
<PreferencesSegment>
<BackupsDropZone application={application} />
</PreferencesSegment>
</PreferencesGroup>
</>
)
}
useEffect(() => {
void backupsService.isFilesBackupsEnabled().then(setBackupsEnabled)
@@ -108,6 +87,7 @@ export const FileBackups = observer(({ application }: Props) => {
icon={[<Icon type="attachment-file" className="min-w-5 min-h-5" />]}
checkmark={false}
/>
<div className="flex flex-row mt-5">
<Button
variant="normal"
@@ -133,4 +113,6 @@ export const FileBackups = observer(({ application }: Props) => {
</PreferencesGroup>
</>
)
})
}
export default observer(FileBackupsDesktop)