Skip to content

Commit

Permalink
Added better archive functionalty (backend side atm)
Browse files Browse the repository at this point in the history
Code refactoring
  • Loading branch information
marcopiovanello committed Dec 18, 2024
1 parent d9cb018 commit 9d3861a
Show file tree
Hide file tree
Showing 29 changed files with 1,398 additions and 414 deletions.
18 changes: 16 additions & 2 deletions frontend/src/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ThemeProvider } from '@emotion/react'
import ArchiveIcon from '@mui/icons-material/Archive'
import CloudDownloadIcon from '@mui/icons-material/CloudDownload'
import ChevronLeft from '@mui/icons-material/ChevronLeft'
import Dashboard from '@mui/icons-material/Dashboard'
import LiveTvIcon from '@mui/icons-material/LiveTv'
Expand Down Expand Up @@ -42,7 +43,7 @@ export default function Layout() {
palette: {
mode: settings.theme,
primary: {
main: getAccentValue(settings.accent)
main: getAccentValue(settings.accent, settings.theme)
},
background: {
default: settings.theme === 'light' ? grey[50] : '#121212'
Expand Down Expand Up @@ -113,7 +114,7 @@ export default function Layout() {
<ListItemText primary={i18n.t('homeButtonLabel')} />
</ListItemButton>
</Link>
<Link to={'/archive'} style={
{/* <Link to={'/archive'} style={
{
textDecoration: 'none',
color: mode === 'dark' ? '#ffffff' : '#000000DE'
Expand All @@ -125,6 +126,19 @@ export default function Layout() {
</ListItemIcon>
<ListItemText primary={i18n.t('archiveButtonLabel')} />
</ListItemButton>
</Link> */}
<Link to={'/filebrowser'} style={
{
textDecoration: 'none',
color: mode === 'dark' ? '#ffffff' : '#000000DE'
}
}>
<ListItemButton>
<ListItemIcon>
<CloudDownloadIcon />
</ListItemIcon>
<ListItemText primary={i18n.t('archiveButtonLabel')} />
</ListItemButton>
</Link>
<Link to={'/monitor'} style={
{
Expand Down
98 changes: 98 additions & 0 deletions frontend/src/components/ArchiveCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import DeleteIcon from '@mui/icons-material/Delete'
import DeleteForeverIcon from '@mui/icons-material/DeleteForever'
import OpenInBrowserIcon from '@mui/icons-material/OpenInBrowser'
import SaveAltIcon from '@mui/icons-material/SaveAlt'
import {
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
IconButton,
Skeleton,
Tooltip,
Typography
} from '@mui/material'
import { useAtomValue } from 'jotai'
import { serverURL } from '../atoms/settings'
import { ArchiveEntry } from '../types'
import { base64URLEncode, ellipsis } from '../utils'

type Props = {
entry: ArchiveEntry
onDelete: (id: string) => void
onHardDelete: (id: string) => void
}

const ArchiveCard: React.FC<Props> = ({ entry, onDelete, onHardDelete }) => {
const serverAddr = useAtomValue(serverURL)

const viewFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/filebrowser/v/${encoded}?token=${localStorage.getItem('token')}`)
}

const downloadFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/filebrowser/d/${encoded}?token=${localStorage.getItem('token')}`)
}

return (
<Card>
<CardActionArea onClick={() => navigator.clipboard.writeText(entry.source)}>
{entry.thumbnail !== '' ?
<CardMedia
component="img"
height={180}
image={entry.thumbnail}
/> :
<Skeleton variant="rectangular" height={180} />
}
<CardContent>
{entry.title !== '' ?
<Typography gutterBottom variant="h6" component="div">
{ellipsis(entry.title, 60)}
</Typography> :
<Skeleton />
}
{/* <code>
{JSON.stringify(JSON.parse(entry.metadata), null, 2)}
</code> */}
<p>{new Date(entry.created_at).toLocaleString()}</p>
</CardContent>
</CardActionArea>
<CardActions>
<Tooltip title="Open in browser">
<IconButton
onClick={() => viewFile(entry.path)}
>
<OpenInBrowserIcon />
</IconButton>
</Tooltip>
<Tooltip title="Download this file">
<IconButton
onClick={() => downloadFile(entry.path)}
>
<SaveAltIcon />
</IconButton>
</Tooltip>
<Tooltip title="Delete from archive">
<IconButton
onClick={() => onDelete(entry.id)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
<Tooltip title="Delete from disk">
<IconButton
onClick={() => onHardDelete(entry.id)}
>
<DeleteForeverIcon />
</IconButton>
</Tooltip>
</CardActions>
</Card>
)
}

export default ArchiveCard
83 changes: 42 additions & 41 deletions frontend/src/components/DownloadCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import EightK from '@mui/icons-material/EightK'
import FourK from '@mui/icons-material/FourK'
import Hd from '@mui/icons-material/Hd'
import Sd from '@mui/icons-material/Sd'
import {
Button,
Card,
Expand All @@ -10,32 +6,30 @@ import {
CardContent,
CardMedia,
Chip,
IconButton,
LinearProgress,
Skeleton,
Stack,
Tooltip,
Typography
} from '@mui/material'
import { useAtomValue } from 'jotai'
import { useCallback } from 'react'
import { serverURL } from '../atoms/settings'
import { RPCResult } from '../types'
import { base64URLEncode, ellipsis, formatSize, formatSpeedMiB, mapProcessStatus } from '../utils'
import { useAtomValue } from 'jotai'
import ResolutionBadge from './ResolutionBadge'
import ClearIcon from '@mui/icons-material/Clear'
import StopCircleIcon from '@mui/icons-material/StopCircle'
import OpenInBrowserIcon from '@mui/icons-material/OpenInBrowser'
import SaveAltIcon from '@mui/icons-material/SaveAlt'

type Props = {
download: RPCResult
onStop: () => void
onCopy: () => void
}

const Resolution: React.FC<{ resolution?: string }> = ({ resolution }) => {
if (!resolution) return null
if (resolution.includes('4320')) return <EightK color="primary" />
if (resolution.includes('2160')) return <FourK color="primary" />
if (resolution.includes('1080')) return <Hd color="primary" />
if (resolution.includes('720')) return <Sd color="primary" />
return null
}

const DownloadCard: React.FC<Props> = ({ download, onStop, onCopy }) => {
const serverAddr = useAtomValue(serverURL)

Expand All @@ -53,12 +47,12 @@ const DownloadCard: React.FC<Props> = ({ download, onStop, onCopy }) => {

const viewFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/archive/v/${encoded}?token=${localStorage.getItem('token')}`)
window.open(`${serverAddr}/filebrowser/v/${encoded}?token=${localStorage.getItem('token')}`)
}

const downloadFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/archive/d/${encoded}?token=${localStorage.getItem('token')}`)
window.open(`${serverAddr}/filebrowser/d/${encoded}?token=${localStorage.getItem('token')}`)
}

return (
Expand Down Expand Up @@ -110,37 +104,44 @@ const DownloadCard: React.FC<Props> = ({ download, onStop, onCopy }) => {
<Typography>
{formatSize(download.info.filesize_approx ?? 0)}
</Typography>
<Resolution resolution={download.info.resolution} />
<ResolutionBadge resolution={download.info.resolution} />
</Stack>
</CardContent>
</CardActionArea>
<CardActions>
<Button
variant="contained"
size="small"
color="primary"
onClick={onStop}
>
{isCompleted() ? "Clear" : "Stop"}
</Button>
{isCompleted() &&
<>
<Button
variant="contained"
size="small"
color="primary"
onClick={() => downloadFile(download.output.savedFilePath)}
{isCompleted() ?
<Tooltip title="Clear from the view">
<IconButton
onClick={onStop}
>
Download
</Button>
<Button
variant="contained"
size="small"
color="primary"
onClick={() => viewFile(download.output.savedFilePath)}
<ClearIcon />
</IconButton>
</Tooltip>
:
<Tooltip title="Stop this download">
<IconButton
onClick={onStop}
>
View
</Button>
<StopCircleIcon />
</IconButton>
</Tooltip>
}
{isCompleted() &&
<>
<Tooltip title="Download this file">
<IconButton
onClick={() => downloadFile(download.output.savedFilePath)}
>
<SaveAltIcon />
</IconButton>
</Tooltip>
<Tooltip title="Open in a new tab">
<IconButton
onClick={() => viewFile(download.output.savedFilePath)}
>
<OpenInBrowserIcon />
</IconButton>
</Tooltip>
</>
}
</CardActions>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/DownloadDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ const DownloadDialog: FC<Props> = ({ open, onClose, onDownloadStart }) => {
disabled={url === ''}
onClick={() => settings.formatSelection
? startTransition(() => sendUrlFormatSelection())
: sendUrl()
: startTransition(async () => await sendUrl())
}
>
{
Expand Down
43 changes: 26 additions & 17 deletions frontend/src/components/DownloadsGridView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Grid } from '@mui/material'
import { Grid2 } from '@mui/material'
import { useAtomValue } from 'jotai'
import { useTransition } from 'react'
import { activeDownloadsState } from '../atoms/downloads'
import { useToast } from '../hooks/toast'
import { useI18n } from '../hooks/useI18n'
import { useRPC } from '../hooks/useRPC'
import { ProcessStatus, RPCResult } from '../types'
import DownloadCard from './DownloadCard'
import LoadingBackdrop from './LoadingBackdrop'

const DownloadsGridView: React.FC = () => {
const downloads = useAtomValue(activeDownloadsState)
Expand All @@ -14,24 +16,31 @@ const DownloadsGridView: React.FC = () => {
const { client } = useRPC()
const { pushMessage } = useToast()

const stop = (r: RPCResult) => r.progress.process_status === ProcessStatus.COMPLETED
? client.clear(r.id)
: client.kill(r.id)
const [isPending, startTransition] = useTransition()

const stop = async (r: RPCResult) => r.progress.process_status === ProcessStatus.COMPLETED
? await client.clear(r.id)
: await client.kill(r.id)

return (
<Grid container spacing={{ xs: 2, md: 2 }} columns={{ xs: 4, sm: 8, md: 12, xl: 12 }} pt={2}>
{
downloads.map(download => (
<Grid item xs={4} sm={8} md={6} xl={4} key={download.id}>
<DownloadCard
download={download}
onStop={() => stop(download)}
onCopy={() => pushMessage(i18n.t('clipboardAction'), 'info')}
/>
</Grid>
))
}
</Grid>
<>
<LoadingBackdrop isLoading={isPending} />
<Grid2 container spacing={{ xs: 2, md: 2 }} columns={{ xs: 4, sm: 8, md: 12, xl: 12 }} pt={2}>
{
downloads.map(download => (
<Grid2 size={{ xs: 4, sm: 8, md: 6, xl: 4 }} key={download.id}>
<DownloadCard
download={download}
onStop={() => startTransition(async () => {
await stop(download)
})}
onCopy={() => pushMessage(i18n.t('clipboardAction'), 'info')}
/>
</Grid2>
))
}
</Grid2>
</>
)
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/DownloadsTableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ const DownloadsTableView: React.FC = () => {

const viewFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/archive/v/${encoded}?token=${localStorage.getItem('token')}`)
window.open(`${serverAddr}/filebrowser/v/${encoded}?token=${localStorage.getItem('token')}`)
}

const downloadFile = (path: string) => {
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/archive/d/${encoded}?token=${localStorage.getItem('token')}`)
window.open(`${serverAddr}/filebrowser/d/${encoded}?token=${localStorage.getItem('token')}`)
}

const stop = (r: RPCResult) => r.progress.process_status === ProcessStatus.COMPLETED
Expand Down
Loading

0 comments on commit 9d3861a

Please sign in to comment.