file browser overhaul

This commit is contained in:
2023-05-26 17:31:00 +02:00
parent 58b05e1403
commit 5d97873748
3 changed files with 59 additions and 23 deletions

View File

@@ -33,6 +33,7 @@ import { BehaviorSubject, Subject, combineLatestWith, map, share } from 'rxjs'
import { useObservable } from './hooks/observable' import { useObservable } from './hooks/observable'
import { RootState } from './stores/store' import { RootState } from './stores/store'
import { DeleteRequest, DirectoryEntry } from './types' import { DeleteRequest, DirectoryEntry } from './types'
import { roundMiB } from './utils'
export default function Downloaded() { export default function Downloaded() {
const settings = useSelector((state: RootState) => state.settings) const settings = useSelector((state: RootState) => state.settings)
@@ -52,7 +53,9 @@ export default function Downloaded() {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ subdir: '' }) body: JSON.stringify({
subdir: '',
})
}) })
.then(res => res.json()) .then(res => res.json())
.then(data => files$.next(data)) .then(data => files$.next(data))
@@ -150,7 +153,7 @@ export default function Downloaded() {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
}}> }}>
<Typography pb={0} variant="h5" color="primary"> <Typography py={1} variant="h5" color="primary">
{'Archive'} {'Archive'}
</Typography> </Typography>
<List sx={{ width: '100%', bgcolor: 'background.paper' }}> <List sx={{ width: '100%', bgcolor: 'background.paper' }}>
@@ -159,11 +162,20 @@ export default function Downloaded() {
<ListItem <ListItem
key={idx} key={idx}
secondaryAction={ secondaryAction={
!file.isDirectory && <Checkbox <div>
{!file.isDirectory && <Typography
variant="caption"
component="span"
>
{roundMiB(file.size)}
</Typography>
}
{!file.isDirectory && <Checkbox
edge="end" edge="end"
checked={file.selected} checked={file.selected}
onChange={() => addSelected(file.name)} onChange={() => addSelected(file.name)}
/> />}
</div>
} }
disablePadding disablePadding
> >
@@ -180,7 +192,10 @@ export default function Downloaded() {
: <InsertDriveFileIcon /> : <InsertDriveFileIcon />
} }
</ListItemIcon> </ListItemIcon>
<ListItemText primary={file.name} /> <ListItemText
primary={file.name}
secondary={file.name != '..' && new Date(file.modTime).toLocaleString()}
/>
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
))} ))}

View File

@@ -65,16 +65,14 @@ export type DLFormat = {
export type DirectoryEntry = { export type DirectoryEntry = {
name: string name: string
path: string path: string
size: number
shaSum: string shaSum: string
isVideo: boolean, modTime: string
isVideo: boolean
isDirectory: boolean isDirectory: boolean
} }
export type DeleteRequest = Omit< export type DeleteRequest = Pick<DirectoryEntry, 'path' | 'shaSum'>
DirectoryEntry, 'name' | 'isDirectory' | 'isVideo'
>
export type PlayRequest = Omit< export type PlayRequest = Pick<DirectoryEntry, 'path'>
DirectoryEntry, 'shaSum' | 'name' | 'isDirectory' | 'isVideo'
>

View File

@@ -6,7 +6,9 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/marcopeocchi/yt-dlp-web-ui/server/config" "github.com/marcopeocchi/yt-dlp-web-ui/server/config"
@@ -16,7 +18,9 @@ import (
type DirectoryEntry struct { type DirectoryEntry struct {
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path"` Path string `json:"path"`
Size int64 `json:"size"`
SHASum string `json:"shaSum"` SHASum string `json:"shaSum"`
ModTime time.Time `json:"modTime"`
IsVideo bool `json:"isVideo"` IsVideo bool `json:"isVideo"`
IsDirectory bool `json:"isDirectory"` IsDirectory bool `json:"isDirectory"`
} }
@@ -36,12 +40,19 @@ func walkDir(root string) (*[]DirectoryEntry, error) {
path := filepath.Join(root, d.Name()) path := filepath.Join(root, d.Name())
info, err := d.Info()
if err != nil {
return nil, err
}
files = append(files, DirectoryEntry{ files = append(files, DirectoryEntry{
Path: path, Path: path,
Name: d.Name(), Name: d.Name(),
Size: info.Size(),
SHASum: utils.ShaSumString(path), SHASum: utils.ShaSumString(path),
IsVideo: utils.IsVideo(d), IsVideo: utils.IsVideo(d),
IsDirectory: d.IsDir(), IsDirectory: d.IsDir(),
ModTime: info.ModTime(),
}) })
} }
@@ -50,6 +61,7 @@ func walkDir(root string) (*[]DirectoryEntry, error) {
type ListRequest struct { type ListRequest struct {
SubDir string `json:"subdir"` SubDir string `json:"subdir"`
OrderBy string `json:"orderBy"`
} }
func ListDownloaded(ctx *fiber.Ctx) error { func ListDownloaded(ctx *fiber.Ctx) error {
@@ -66,6 +78,12 @@ func ListDownloaded(ctx *fiber.Ctx) error {
return err return err
} }
if req.OrderBy == "modtime" {
sort.SliceStable(*files, func(i, j int) bool {
return (*files)[i].ModTime.After((*files)[j].ModTime)
})
}
ctx.Status(http.StatusOK) ctx.Status(http.StatusOK)
return ctx.JSON(files) return ctx.JSON(files)
} }
@@ -105,13 +123,18 @@ func SendFile(ctx *fiber.Ctx) error {
if err != nil { if err != nil {
return err return err
} }
decodedStr := string(decoded)
root := config.Instance().GetConfig().DownloadPath root := config.Instance().GetConfig().DownloadPath
// TODO: further path / file validations // TODO: further path / file validations
if strings.Contains(filepath.Dir(string(decoded)), root) { if strings.Contains(filepath.Dir(decodedStr), root) {
// ctx.Response().Header.Set(
// "Content-Disposition",
// "inline; filename="+filepath.Base(decodedStr),
// )
ctx.SendStatus(fiber.StatusOK) ctx.SendStatus(fiber.StatusOK)
return ctx.SendFile(string(decoded)) return ctx.SendFile(decodedStr)
} }
return ctx.SendStatus(fiber.StatusUnauthorized) return ctx.SendStatus(fiber.StatusUnauthorized)