Skip to content

Commit

Permalink
feat: renterd multipart remote uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Feb 23, 2024
1 parent 32a99b7 commit bc4ce0a
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-toes-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Transfers now list remote uploads originating from other devices.
5 changes: 5 additions & 0 deletions .changeset/short-ducks-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Remote file uploads can now be aborted from the transfer list.
75 changes: 65 additions & 10 deletions apps/renterd/components/TransfersBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
ProgressBar,
ScrollArea,
Text,
Tooltip,
} from '@siafoundation/design-system'
import {
Close16,
CloudUpload16,
Download16,
Subtract24,
Upload16,
Expand All @@ -23,17 +25,19 @@ function getProgress(transfer: { loaded?: number; size?: number }) {

export function TransfersBar() {
const { isUnlockedAndAuthedRoute } = useAppSettings()
const { uploadsList, downloadsList, downloadCancel } = useFilesManager()
const { uploadsList, remoteUploadsList, downloadsList, downloadCancel } =
useFilesManager()
const [maximized, setMaximized] = useState<boolean>(true)

const uploadCount = uploadsList.length
const remoteUploadCount = remoteUploadsList.length
const downloadCount = downloadsList.length

if (!isUnlockedAndAuthedRoute) {
return null
}

if (uploadCount === 0 && downloadCount === 0) {
if (uploadCount === 0 && downloadCount === 0 && remoteUploadCount === 0) {
return null
}

Expand Down Expand Up @@ -91,6 +95,45 @@ export function TransfersBar() {
})}
</>
) : null}
{remoteUploadCount > 0 ? (
<>
<div className="flex justify-between items-center px-3 py-2 border-b border-gray-200 dark:border-graydark-300">
<Text size="16" weight="semibold">
Remote uploads ({remoteUploadCount})
</Text>
<Button variant="ghost" onClick={() => setMaximized(false)}>
<Subtract24 />
</Button>
</div>
{remoteUploadsList.map((upload) => {
return (
<div
key={upload.id}
className="flex flex-col gap-0.5 border-t first:border-t-0 border-gray-200 dark:border-graydark-300 px-3 py-2"
>
<div className="flex gap-1">
<Text ellipsis size="14" className="flex-1">
{upload.path}
</Text>
<Button
tip="Cancel file upload"
variant="ghost"
size="none"
onClick={() => upload.uploadAbort?.()}
>
<Close16 />
</Button>
</div>
<div className="flex justify-between">
<Text size="12" color="verySubtle">
Uploading from a different session
</Text>
</div>
</div>
)
})}
</>
) : null}
{downloadCount > 0 ? (
<>
<div className="flex justify-between items-center px-3 py-2 border-b border-gray-200 dark:border-graydark-300">
Expand Down Expand Up @@ -152,16 +195,28 @@ export function TransfersBar() {
<Button onClick={() => setMaximized(true)} className="flex gap-3">
<LoadingDots />
{uploadCount ? (
<Text className="flex gap-1">
{uploadCount}
<Upload16 className="opacity-50 scale-75 relative top-px" />
</Text>
<Tooltip content="Uploads">
<Text className="flex gap-1">
{uploadCount}
<Upload16 className="opacity-50 scale-75 relative top-px" />
</Text>
</Tooltip>
) : null}
{remoteUploadCount ? (
<Tooltip content="Remote uploads: uploads originating from a different session">
<Text className="flex gap-1">
{remoteUploadCount}
<CloudUpload16 className="opacity-50 scale-75 relative top-px" />
</Text>
</Tooltip>
) : null}
{downloadCount ? (
<Text className="flex gap-1">
{downloadCount && downloadCount}
<Download16 className="opacity-50 scale-75" />
</Text>
<Tooltip content="Downloads">
<Text className="flex gap-1">
{downloadCount && downloadCount}
<Download16 className="opacity-50 scale-75" />
</Text>
</Tooltip>
) : null}
</Button>
</div>
Expand Down
8 changes: 7 additions & 1 deletion apps/renterd/contexts/filesManager/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useDownloads } from './downloads'
import { useBuckets } from '@siafoundation/react-renterd'
import { routes } from '../../config/routes'
import useLocalStorageState from 'use-local-storage-state'
import { useRemoteUploads } from './remoteUploads'

function useFilesManagerMain() {
const {
Expand Down Expand Up @@ -87,9 +88,13 @@ function useFilesManagerMain() {
[router, activeDirectory]
)

const { uploadFiles, uploadsList } = useUploads({
const { uploadFiles, uploadsMap, uploadsList } = useUploads({
activeDirectoryPath,
})
const { remoteUploadsList } = useRemoteUploads({
activeBucket,
uploadsMap,
})
const { downloadFiles, downloadsList, getFileUrl, downloadCancel } =
useDownloads()

Expand Down Expand Up @@ -174,6 +179,7 @@ function useFilesManagerMain() {
navigateToModeSpecificFiltering,
uploadFiles,
uploadsList,
remoteUploadsList,
downloadFiles,
downloadsList,
downloadCancel,
Expand Down
66 changes: 66 additions & 0 deletions apps/renterd/contexts/filesManager/remoteUploads.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
Bucket,
useMultipartUploadAbort,
useMultipartUploadListUploads,
} from '@siafoundation/react-renterd'
import { useMemo } from 'react'
import { ObjectUploadData, ObjectUploadRemoteData, UploadsMap } from './types'
import { getFilename, join } from '../../lib/paths'

type Props = {
activeBucket?: Bucket
uploadsMap: UploadsMap
}

export function useRemoteUploads({ activeBucket, uploadsMap }: Props) {
const apiBusUploadAbort = useMultipartUploadAbort()
const remoteUploads = useMultipartUploadListUploads({
disabled: !activeBucket,
payload: {
bucket: activeBucket?.name,
},
})

const remoteUploadsMap = useMemo(() => {
return (
remoteUploads.data?.uploads?.reduce((acc, upload) => {
const id = upload.uploadID
const name = getFilename(upload.path)
const fullPath = join(activeBucket?.name, upload.path)
return {
...acc,
[id]: {
id,
path: fullPath,
bucket: activeBucket,
name,
size: 1,
loaded: 1,
isUploading: true,
remote: true,
type: 'file',
uploadAbort: () =>
apiBusUploadAbort.post({
payload: {
bucket: activeBucket?.name,
path: upload.path,
uploadID: upload.uploadID,
},
}),
} as ObjectUploadRemoteData,
}
}, {}) || {}
)
}, [activeBucket, remoteUploads.data, apiBusUploadAbort])

const remoteUploadsList = useMemo(() => {
// remoteUploadsMap without anything in uploadsMap
return Object.values(remoteUploadsMap).filter(
(remoteUpload: ObjectUploadData) => !uploadsMap[remoteUpload.id]
) as ObjectUploadData[]
}, [remoteUploadsMap, uploadsMap])

return {
remoteUploadsList,
}
}

0 comments on commit bc4ce0a

Please sign in to comment.