Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Application store to the global/static one #447

Merged
merged 10 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ export class Client {
}
}

export const client = new Client()

// Internal

async function makeRequest<T>(
Expand Down
22 changes: 14 additions & 8 deletions client/components/Application/Browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { ErrorBoundary } from 'react-error-boundary'
import EmptyCard from '../Parts/Cards/Empty'
import SpinnerCard from '../Parts/Cards/Spinner'
import FileTree from '../Parts/Trees/File'
import { useStore } from './store'
import * as store from '@client/store'

export default function Browser() {
const files = useStore((state) => state.files)
const loading = useStore((state) => state.loading)
const files = store.useStore((state) => state.files)
const loading = store.useStore((state) => state.loading)

return loading ? (
<LoadingBrowser />
) : files.length ? (
Expand All @@ -18,10 +19,10 @@ export default function Browser() {
}

function DefaultBrowser() {
const path = useStore((state) => state.path)
const files = useStore((state) => state.files)
const fileEvent = useStore((state) => state.fileEvent)
const selectFile = useStore((state) => state.selectFile)
const path = store.useStore((state) => state.path)
const files = store.useStore((state) => state.files)
const fileEvent = store.useStore((state) => state.fileEvent)

return (
<ErrorBoundary
fallback={
Expand All @@ -34,7 +35,12 @@ function DefaultBrowser() {
</Box>
}
>
<FileTree files={files} event={fileEvent} selected={path} onSelect={selectFile} />
<FileTree
files={files}
event={fileEvent}
selected={path}
onSelect={store.selectFile}
/>
</ErrorBoundary>
)
}
Expand Down
19 changes: 9 additions & 10 deletions client/components/Application/Buttons/Add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import IconButton from '../../Parts/Buttons/Icon'
import CreateNewFolderIcon from '@mui/icons-material/CreateNewFolder'
import DriveFolderUploadRounded from '@mui/icons-material/DriveFolderUploadRounded'
import UploadFileRounded from '@mui/icons-material/UploadFileRounded'
import { useStore } from '../store'
import * as store from '@client/store'

export default function AddButton() {
const fileEvent = useStore((state) => state.fileEvent)
const fileEvent = store.useStore((state) => state.fileEvent)

return (
<DropdownButton
label="Add"
Expand All @@ -27,8 +28,8 @@ export default function AddButton() {
}

function AddLocalFileButton() {
const addFiles = useStore((state) => state.addFiles)
const inputFileRef = React.useRef<HTMLInputElement>(null)

return (
<React.Fragment>
<Button
Expand All @@ -44,7 +45,7 @@ function AddLocalFileButton() {
multiple
ref={inputFileRef}
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => {
if (ev.target.files) addFiles(ev.target.files)
if (ev.target.files) store.addFiles(ev.target.files)
}}
/>
</Button>
Expand All @@ -53,21 +54,20 @@ function AddLocalFileButton() {
}

function AddRemoteFileButton() {
const updateState = useStore((state) => state.updateState)
return (
<IconButton
variant="text"
label="Remote File"
Icon={AddLinkIcon}
onClick={() => updateState({ dialog: 'addRemoteFile' })}
onClick={() => store.openDialog('addRemoteFile')}
/>
)
}

function AddLocalFolderButton() {
const isWebkitDirectorySupported = 'webkitdirectory' in document.createElement('input')
if (!isWebkitDirectorySupported) return null
const addFiles = useStore((state) => state.addFiles)

return (
<React.Fragment>
<Button
Expand All @@ -80,7 +80,7 @@ function AddLocalFolderButton() {
type="file"
hidden
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => {
if (ev.target.files) addFiles(ev.target.files)
if (ev.target.files) store.addFiles(ev.target.files)
}}
// @ts-expect-error
webkitdirectory=""
Expand All @@ -91,13 +91,12 @@ function AddLocalFolderButton() {
}

function AddEmptyFolderButton() {
const updateState = useStore((state) => state.updateState)
return (
<IconButton
variant="text"
label="Create Folder"
Icon={CreateNewFolderIcon}
onClick={() => updateState({ dialog: 'addEmptyFolder' })}
onClick={() => store.openDialog('addEmptyFolder')}
/>
)
}
13 changes: 7 additions & 6 deletions client/components/Application/Buttons/Delete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import Box from '@mui/material/Box'
import DeleteIcon from '@mui/icons-material/Delete'
import IconButton from '../../Parts/Buttons/Icon'
import LightTooltip from '../../Parts/Tooltips/Light'
import { selectors, useStore } from '../store'
import * as store from '@client/store'
import { useKeyPress } from 'ahooks'

export default function DeleteButton() {
const path = useStore((state) => state.path)
const isFolder = useStore(selectors.isFolder)
const updateState = useStore((state) => state.updateState)
const path = store.useStore((state) => state.path)
const isFolder = store.useStore(store.getIsFolder)

const type = isFolder ? 'Folder' : 'File'
useKeyPress(['ctrl.i'], (event) => {
event.preventDefault()
if (path) updateState({ dialog: `delete${type}` })
if (path) store.openDialog(`delete${type}`)
})

return (
<LightTooltip title="Delete file [Ctrl+I]">
<Box>
Expand All @@ -23,7 +24,7 @@ export default function DeleteButton() {
disabled={!path}
variant="text"
color="warning"
onClick={() => updateState({ dialog: `delete${type}` })}
onClick={() => store.openDialog(`delete${type}`)}
/>
</Box>
</LightTooltip>
Expand Down
28 changes: 14 additions & 14 deletions client/components/Application/Buttons/Manage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import RuleIcon from '@mui/icons-material/Rule'
import ManageIcon from '@mui/icons-material/FileCopy'
import IconButton from '../../Parts/Buttons/Icon'
import DropdownButton from '../../Parts/Buttons/Dropdown'
import { useStore, selectors } from '../store'
import * as store from '@client/store'

export default function ManageButton() {
const path = useStore((state) => state.path)
const notIndexedFiles = useStore(selectors.notIndexedFiles)
const path = store.useStore((state) => state.path)
const notIndexedFiles = store.useStore(store.getNotIndexedFiles)

return (
<DropdownButton
disabled={!path && !notIndexedFiles.length}
Expand All @@ -24,47 +25,46 @@ export default function ManageButton() {
}

function CopyButton() {
const path = useStore((state) => state.path)
const updateState = useStore((state) => state.updateState)
const isFolder = useStore(selectors.isFolder)
const path = store.useStore((state) => state.path)
const isFolder = store.useStore(store.getIsFolder)
const type = isFolder ? 'Folder' : 'File'

return (
<IconButton
disabled={!path}
variant="text"
Icon={CopyIcon}
label={`Copy ${type}`}
onClick={() => updateState({ dialog: `copy${type}` })}
onClick={() => store.openDialog(`copy${type}`)}
/>
)
}

function MoveButton() {
const path = useStore((state) => state.path)
const updateState = useStore((state) => state.updateState)
const isFolder = useStore(selectors.isFolder)
const path = store.useStore((state) => state.path)
const isFolder = store.useStore(store.getIsFolder)
const type = isFolder ? 'Folder' : 'File'

return (
<IconButton
disabled={!path}
variant="text"
Icon={MoveIcon}
label={`Move ${type}`}
onClick={() => updateState({ dialog: `move${type}` })}
onClick={() => store.openDialog(`move${type}`)}
/>
)
}

function IndexFilesButton() {
const updateState = useStore((state) => state.updateState)
const notIndexedFiles = useStore(selectors.notIndexedFiles)
const notIndexedFiles = store.useStore(store.getNotIndexedFiles)
return (
<IconButton
disabled={!notIndexedFiles.length}
variant="text"
label="Index Files"
Icon={RuleIcon}
onClick={() => updateState({ dialog: 'indexFiles' })}
onClick={() => store.openDialog('indexFiles')}
/>
)
}
24 changes: 14 additions & 10 deletions client/components/Application/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import Text from '../Controllers/Text'
import View from '../Controllers/View'
import EmptyCard from '../Parts/Cards/Empty'
import SpinnerCard from '../Parts/Cards/Spinner'
import { useStore } from './store'
import * as store from '@client/store'
import { client } from '@client/client'

export default function Content() {
const record = useStore((state) => state.record)
const indexing = useStore((state) => state.indexing)
const path = useStore((state) => state.path)
const record = store.useStore((state) => state.record)
const indexing = store.useStore((state) => state.indexing)
const path = store.useStore((state) => state.path)

return indexing ? (
<LoadingContent />
) : record && path ? (
Expand All @@ -26,13 +28,15 @@ export default function Content() {
}

function FileContent() {
const client = useStore((state) => state.client)
const record = useStore((state) => state.record)
const onFileCreate = useStore((state) => state.onFileCreate)
const onFilePatch = useStore((state) => state.onFilePatch)
const record = store.useStore((state) => state.record)
if (!record) return null

const Controller = CONTROLLERS[record.type] || File
const handleUpdate = React.useMemo(() => () => onFilePatch(record.path), [record.path])
const handleUpdate = React.useMemo(
() => () => store.onFilePatch(record.path),
[record.path]
)

return (
<ErrorBoundary
fallback={
Expand All @@ -49,7 +53,7 @@ function FileContent() {
path={record.path}
client={client}
onSave={handleUpdate}
onSaveAs={(path) => onFileCreate([path])}
onSaveAs={(path) => store.onFileCreate([path])}
/>
</ErrorBoundary>
)
Expand Down
4 changes: 2 additions & 2 deletions client/components/Application/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import DeleteFolderDialog from './Dialogs/DeleteFolder'
import IndexFilesDialog from './Dialogs/IndexFiles'
import MoveFileDialog from './Dialogs/MoveFile'
import MoveFolderDialog from './Dialogs/MoveFolder'
import { useStore } from './store'
import * as store from '@client/store'

export default function Dialog() {
const dialog = useStore((state) => state.dialog)
const dialog = store.useStore((state) => state.dialog)
if (!dialog) return null
// @ts-ignore
const Dialog = DIALOGS[dialog]
Expand Down
13 changes: 6 additions & 7 deletions client/components/Application/Dialogs/AddEmptyFolder.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import InputDialog from '../../Parts/Dialogs/Input'
import { useStore, selectors } from '../store'
import * as store from '@client/store'

export default function AddEmptyFolderDialog() {
const folderPath = useStore(selectors.folderPath)
const createFolder = useStore((state) => state.createFolder)
const updateState = useStore((state) => state.updateState)
const folderPath = store.useStore(store.getFolderPath)

return (
<InputDialog
open={true}
value={folderPath}
title="Create Folder"
label="Create"
placholder="Name of the new folder"
onCancel={() => updateState({ dialog: undefined })}
onCancel={store.closeDialog}
onConfirm={async (path) => {
await createFolder(path)
updateState({ dialog: undefined })
await store.createFolder(path)
store.closeDialog()
}}
/>
)
Expand Down
10 changes: 4 additions & 6 deletions client/components/Application/Dialogs/AddRemoteFile.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as React from 'react'
import UploadIcon from '@mui/icons-material/Upload'
import InputDialog from '../../Parts/Dialogs/Input'
import { useStore } from '../store'
import * as store from '@client/store'
import * as helpers from '../../../helpers'

export default function AddRemoteFileDialog() {
const fetchFile = useStore((state) => state.fetchFile)
const updateState = useStore((state) => state.updateState)
const [textFieldError, setTextFieldError] = React.useState(false)
const [errorHelperText, setErrorHelperText] = React.useState('')

Expand All @@ -20,12 +18,12 @@ export default function AddRemoteFileDialog() {
errorHelperText={errorHelperText}
description="You are fetching a file. Enter source:"
placholder="Enter or paste a URL"
onCancel={() => updateState({ dialog: undefined })}
onCancel={store.closeDialog}
onConfirm={async (url) => {
if (url !== '' && helpers.isUrlValid(url)) {
setTextFieldError(false)
await fetchFile(url)
updateState({ dialog: undefined })
await store.fetchFile(url)
store.closeDialog()
} else {
setTextFieldError(true)
if (url === '') {
Expand Down
14 changes: 7 additions & 7 deletions client/components/Application/Dialogs/AdjustFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import DisplaySettingsIcon from '@mui/icons-material/DisplaySettings'
import ConfirmDialog from '../../Parts/Dialogs/Confirm'
import SelectField from '../../Parts/Fields/Select'
import InputField from '../../Parts/Fields/Input'
import { useStore } from '../store'
import * as store from '@client/store'
import * as settings from '../../../settings'

export default function AdjustFileDialog() {
const record = useStore((state) => state.record)
const adjustFile = useStore((state) => state.adjustFile)
const updateState = useStore((state) => state.updateState)
const record = store.useStore((state) => state.record)
const [name, setName] = React.useState(record?.name || '')
const [type, setType] = React.useState(record?.type || '')
if (!record) return null

const newName = record.name !== name ? name : undefined
const newType = record.type !== type ? type : undefined

return (
<ConfirmDialog
disabled={!newName && !newType}
Expand All @@ -24,10 +24,10 @@ export default function AdjustFileDialog() {
label="Adjust"
Icon={DisplaySettingsIcon}
description="You can change file name and type. Currently they are:"
onCancel={() => updateState({ dialog: undefined })}
onCancel={store.closeDialog}
onConfirm={async () => {
updateState({ dialog: undefined })
await adjustFile(newName, newType)
await store.adjustFile(newName, newType)
store.closeDialog()
}}
>
<Box sx={{ marginTop: -1 }}>
Expand Down
Loading
Loading