Skip to content

Commit

Permalink
refactor(renterd): native direct file downloads
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Jan 19, 2025
1 parent b95af8d commit 7301f76
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 254 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-pumas-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

The transfers bar no longer includes a download list.
5 changes: 5 additions & 0 deletions .changeset/four-apes-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Files are now downloaded directly in the browser with cookie based auth.
11 changes: 8 additions & 3 deletions apps/renterd-e2e/src/specs/files.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ test('can upload, rename, and delete files', async ({ page }) => {
await deleteBucket(page, bucketName)
})

test('can upload and download a file', async ({ page }) => {
test('can upload and download a file', async ({ page, context }) => {
const bucketName = 'files-test'
const fileName = 'sample.txt'
const filePath = `${bucketName}/${fileName}`
Expand All @@ -127,11 +127,16 @@ test('can upload and download a file', async ({ page }) => {
await fileInList(page, filePath)

// Download.
const pagePromise = context.waitForEvent('page')
await openFileContextMenu(page, filePath)
await page.getByRole('menuitem', { name: 'Download file' }).click()
await expect(
page.getByRole('button', { name: 'Active downloads' })
page.getByRole('menuitem', { name: 'Download file' })
).toBeVisible()
await page.getByRole('menuitem', { name: 'Download file' }).click()
const newPage = await pagePromise
expect(newPage.url()).toContain(
'/api/worker/object/sample.txt?bucket=files-test'
)
})

test('can rename and delete a directory with contents', async ({ page }) => {
Expand Down
9 changes: 5 additions & 4 deletions apps/renterd/components/Files/FileContextMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CopyMetadataMenuItem } from './CopyMetadataMenuItem'
import { getFilename } from '../../../lib/paths'
import { useDialog } from '../../../contexts/dialog'
import { useFilesManager } from '../../../contexts/filesManager'
import { useDownloads } from '../../../contexts/filesManager/downloads'

type Props = {
path: string
Expand All @@ -30,8 +31,8 @@ type Props = {
}

export function FileContextMenu({ trigger, path, contentProps }: Props) {
const { downloadFiles, getFileUrl, navigateToModeSpecificFiltering } =
useFilesManager()
const { navigateToModeSpecificFiltering } = useFilesManager()
const { getAuthenticatedFileUrl, getFileUrl, downloadFiles } = useDownloads()
const deleteFile = useFileDelete()
const { openDialog } = useDialog()

Expand Down Expand Up @@ -114,7 +115,7 @@ export function FileContextMenu({ trigger, path, contentProps }: Props) {
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => {
copyToClipboard(getFileUrl(path, false), 'file URL')
copyToClipboard(getFileUrl(path), 'file URL')
}}
>
<DropdownMenuLeftSlot>
Expand All @@ -125,7 +126,7 @@ export function FileContextMenu({ trigger, path, contentProps }: Props) {
<DropdownMenuItem
onSelect={() => {
copyToClipboardCustom({
text: getFileUrl(path, true),
text: getAuthenticatedFileUrl(path),
title: 'Copied authenticated file URL to clipboard',
body: (
<>
Expand Down
87 changes: 13 additions & 74 deletions apps/renterd/components/TransfersBar.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,31 @@
import {
Button,
Panel,
ScrollArea,
Text,
AppDockedControl,
} from '@siafoundation/design-system'
import { Download16, Subtract24, Upload16 } from '@siafoundation/react-icons'
import { useState } from 'react'
import { Button, AppDockedControl } from '@siafoundation/design-system'
import { Upload16 } from '@siafoundation/react-icons'
import { useFilesManager } from '../contexts/filesManager'
import { useAppSettings } from '@siafoundation/react-core'
import { TransfersBarItem } from './TransfersBarItem'
import { useUploads } from '../contexts/uploads'

export function TransfersBar() {
const { isUnlockedAndAuthedRoute } = useAppSettings()
const { downloadsList, downloadCancel, isViewingUploads, navigateToUploads } =
useFilesManager()
const { isViewingUploads, navigateToUploads } = useFilesManager()
const { datasetPageTotal: uploadsPageTotal } = useUploads()
const [maximized, setMaximized] = useState<boolean>(true)

const isActiveUploads = !!uploadsPageTotal
const downloadCount = downloadsList.length
const isActiveDownloads = !!downloadCount

if (!isUnlockedAndAuthedRoute) {
return <AppDockedControl />
}

if (!isActiveUploads && !isActiveDownloads) {
if (!isActiveUploads) {
return <AppDockedControl />
}

const controls = (
<div className="flex gap-2 justify-center">
{isActiveUploads && !isViewingUploads ? (
if (isViewingUploads) {
return <AppDockedControl />
}

return (
<AppDockedControl>
<div className="flex gap-2 justify-center">
<Button
tip="Uploads list"
onClick={navigateToUploads}
Expand All @@ -42,60 +34,7 @@ export function TransfersBar() {
<Upload16 className="opacity-50 scale-75 relative top-px" />
Active uploads
</Button>
) : null}
{isActiveDownloads ? (
<Button
tip="Downloads list"
onClick={() => setMaximized((max) => !max)}
className="flex gap-1"
>
<Download16 className="opacity-50 scale-75" />
Active downloads
</Button>
) : null}
</div>
</div>
</AppDockedControl>
)

if (isActiveDownloads && maximized) {
return (
<AppDockedControl>
<div className="flex flex-col items-center justify-center gap-2">
<Panel className="w-[400px] flex flex-col max-h-[600px]">
<ScrollArea>
{isActiveDownloads ? (
<>
<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">
Active downloads ({downloadCount})
</Text>
<Button variant="ghost" onClick={() => setMaximized(false)}>
<Subtract24 />
</Button>
</div>
{downloadsList.map((download) => (
<TransfersBarItem
key={download.id}
path={download.path}
loaded={download.loaded || 0}
size={download.size}
status={
download.loaded === download.size
? 'processing'
: 'downloading'
}
abort={() => downloadCancel(download)}
abortTip="Cancel download"
/>
))}
</>
) : null}
</ScrollArea>
</Panel>
{controls}
</div>
</AppDockedControl>
)
}

return <AppDockedControl>{controls}</AppDockedControl>
}
Loading

0 comments on commit 7301f76

Please sign in to comment.