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

Sidebar in browser #2

Merged
merged 36 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8ea1b7e
Fixed multi download not appearing correctly
MangoCubes Nov 22, 2022
f161936
Added caching for FileBrowser
MangoCubes Nov 22, 2022
870884f
Added separate sidebar for filebrowser
MangoCubes Nov 22, 2022
72457ef
Stateful cache
MangoCubes Nov 22, 2022
741977e
Cache is used as primary item storage instead
MangoCubes Nov 22, 2022
826a20f
Starting work on filebrowser tree
MangoCubes Nov 23, 2022
324edfe
Empty cache container is added for each child directories
MangoCubes Nov 23, 2022
179b11c
Items on sidebar loads if it is not already
MangoCubes Nov 23, 2022
ed2062c
Added optional controller to make sidebar tree independent from main …
MangoCubes Nov 23, 2022
adb529e
Cache will be used unless explicitly refreshed
MangoCubes Nov 23, 2022
1fa8f2a
Fixed cache being invalidated upon going to parent folder
MangoCubes Nov 23, 2022
934bb20
Moved code into the scope where it matters
MangoCubes Nov 23, 2022
65a90f8
Merged two boolean states into one enum
MangoCubes Nov 25, 2022
aee848f
Failsafe when items is empty
MangoCubes Nov 25, 2022
ed84c71
Concurrency handling
MangoCubes Nov 25, 2022
e7762ca
Moved types for reuse
MangoCubes Nov 25, 2022
d87a47d
Removed potential invalid states
MangoCubes Nov 25, 2022
d761aaf
Applied similar method to vault browser
MangoCubes Nov 25, 2022
d947396
Nonexistent record is correctly assumed as not started
MangoCubes Nov 25, 2022
f42640f
Starting work on vault sidebar
MangoCubes Nov 25, 2022
137a4c8
Added sidebar back into vault browser
MangoCubes Nov 25, 2022
271c72d
Loading dir id happens after loading screen is shown
MangoCubes Nov 26, 2022
d4782c5
Buttons are disabled properly during loading screen
MangoCubes Nov 26, 2022
0a29e1b
Applying similar approach on FileBrowser for simpler code
MangoCubes Nov 26, 2022
5d1abe5
Fixed contents going out of sidebar's intended size
MangoCubes Nov 26, 2022
55390f1
Experimental way of handling async id fetching
MangoCubes Nov 26, 2022
2ba62b7
Fixed wrong id being passed
MangoCubes Nov 26, 2022
1af5810
Decrypted name is displayed instead of placeholder
MangoCubes Nov 26, 2022
4133119
Added placeholder if there are no subdirs
MangoCubes Nov 27, 2022
a364c44
Fixed missing unique key
MangoCubes Nov 27, 2022
9537277
Fixed text going over sidebar
MangoCubes Nov 27, 2022
8325561
Reusing component for both sidebars
MangoCubes Nov 27, 2022
4806381
Browser control separated from querying
MangoCubes Nov 27, 2022
0f84220
Minor bug fixes
MangoCubes Nov 27, 2022
184966f
Previous items will not be discarded during query
MangoCubes Nov 27, 2022
ec45fb9
Functional reload button
MangoCubes Nov 27, 2022
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
Prev Previous commit
Next Next commit
Added separate sidebar for filebrowser
  • Loading branch information
MangoCubes committed Nov 22, 2022
commit 870884f70696bb79fe8e8f850f0bb15939a23e14
9 changes: 4 additions & 5 deletions src/web/MainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ export function MainScreen(){

if(client){
return (
<Box sx={{display: 'flex', width: '100vw', height: '100vh'}}>
<Sidebar logout={() => setClient(null)} vault={vault} lock={() => setVault(null)} downloads={downloads} openDownloads={() => setOpen(true)}/>
<>
{
vault === null
? <FileBrowser client={client} setVault={setVault} download={startDownload}/>
: <VaultBrowser client={client} vault={vault} download={startDownload}/>
? <FileBrowser client={client} logout={() => setClient(null)} setVault={setVault} download={startDownload} downloads={downloads} openDownloads={() => setOpen(true)}/>
: <VaultBrowser client={client} vault={vault} download={startDownload} downloads={downloads} openDownloads={() => setOpen(true)}/>
}
<DownloadProgress open={open} client={client} onClose={() => setOpen(false)} downloads={downloads} clear={clearDownloads}/>
</Box>
</>
)
} else {
return <Login setClient={setClient}/>
Expand Down
66 changes: 39 additions & 27 deletions src/web/fileBrowser/FileBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { ArrowBack, Folder, Article, Refresh, Lock, LockOpen, Key, Download, Delete, MoreVert } from "@mui/icons-material";
import { Box, AppBar, Toolbar, Typography, IconButton, Tooltip, Fab, Zoom, Menu, ListItemIcon, ListItemText, MenuItem } from "@mui/material";
import { GridSelectionModel, DataGrid, GridRowParams, GridRenderCellParams, GridActionsCellItem } from "@mui/x-data-grid";
import { Item, Vault } from "cryptomator-ts";
import { Item, ItemPath, Vault } from "cryptomator-ts";
import { useEffect, useState, useMemo, useRef } from "react";
import { WebDAV } from "../../lib/cryptomator/WebDAV";
import { ItemDownloader } from "../ItemDownloader";
import { FileSidebar } from "./FileSidebar";
import { VaultDialog } from "./VaultDialog";

type DirCache = {
child: {[dir: string]: DirCache};
explored: boolean;
}

export function FileBrowser(props: {client: WebDAV, setVault: (vault: Vault) => void, download: (item: Item[]) => void}){
export function FileBrowser(props: {
client: WebDAV,
setVault: (vault: Vault) => void,
download: (item: Item[]) => void,
logout: () => void,
downloads: {[path: ItemPath]: ItemDownloader},
openDownloads: () => void
}){

const [dir, setDir] = useState<string[]>([]);
const [items, setItems] = useState<Item[]>([]);
Expand Down Expand Up @@ -173,32 +182,35 @@ export function FileBrowser(props: {client: WebDAV, setVault: (vault: Vault) =>
}

return (
<Box sx={{display: 'flex', flexDirection: 'column', height: '100%', flex: 1}}>
<AppBar position='static'>
{toolbar()}
</AppBar>
<Box m={1} sx={{flex: 1}}>
<DataGrid
onRowClick={onRowClick}
disableSelectionOnClick
isRowSelectable={(params: GridRowParams) => params.row.type !== 'parent'}
columns={columns}
rows={getRows()}
loading={loading}
checkboxSelection
selectionModel={sel}
onSelectionModelChange={items => {
if(!loading) setSel(items);
}}
/>
<Box sx={{display: 'flex', width: '100vw', height: '100vh'}}>
<FileSidebar logout={props.logout} downloads={props.downloads} openDownloads={props.openDownloads}/>
<Box sx={{display: 'flex', flexDirection: 'column', height: '100%', flex: 1}}>
<AppBar position='static'>
{toolbar()}
</AppBar>
<Box m={1} sx={{flex: 1}}>
<DataGrid
onRowClick={onRowClick}
disableSelectionOnClick
isRowSelectable={(params: GridRowParams) => params.row.type !== 'parent'}
columns={columns}
rows={getRows()}
loading={loading}
checkboxSelection
selectionModel={sel}
onSelectionModelChange={items => {
if(!loading) setSel(items);
}}
/>
</Box>
<Zoom in={showButton()}>
<Fab onClick={() => setOpen(true)} variant='extended' sx={{position: 'fixed', top: 'auto', left: 'auto', right: 20, bottom: 80}}>
<LockOpen/>
Unlock
</Fab>
</Zoom>
<VaultDialog open={open} close={() => setOpen(false)} decrypt={decrypt} setVault={props.setVault}/>
</Box>
<Zoom in={showButton()}>
<Fab onClick={() => setOpen(true)} variant='extended' sx={{position: 'fixed', top: 'auto', left: 'auto', right: 20, bottom: 80}}>
<LockOpen/>
Unlock
</Fab>
</Zoom>
<VaultDialog open={open} close={() => setOpen(false)} decrypt={decrypt} setVault={props.setVault}/>
</Box>
);
}
Expand Down
62 changes: 62 additions & 0 deletions src/web/fileBrowser/FileSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Download, Logout } from "@mui/icons-material";
import { Drawer, Toolbar, ListItem, ListItemText, Divider, Box, List, ListItemButton, ListItemIcon, Badge } from "@mui/material";
import { ItemPath } from "cryptomator-ts";
import { ItemDownloader, Progress } from "../ItemDownloader";

export function FileSidebar(props: {logout: () => void, downloads: {[path: ItemPath]: ItemDownloader}, openDownloads: () => void}){

const drawer = 240;

const getMessage = () => {
let done = 0;
let inProgress = 0;
for(const k in props.downloads){
const item = props.downloads[k as ItemPath];
if(item.progress.current === Progress.Done) done++;
else if(item.progress.current === Progress.Running) inProgress++;
}
const res = [];
if(inProgress !== 0) res.push(`${inProgress} in progress`);
if(done !== 0) res.push(`${done} completed`);
return res.join(', ');
}

const getCount = () => {
let inProgress = 0;
for(const k in props.downloads){
const item = props.downloads[k as ItemPath];
if(item.progress.current === Progress.Running) inProgress++;
}
return inProgress;
}

return (
<Drawer variant='permanent' sx={{ width: drawer }} open={true} anchor='left'>
<Toolbar sx={{ maxWidth: drawer }}>
<ListItem>
<ListItemText primary={'No vault selected'}/>
</ListItem>
</Toolbar>
<Divider/>
<Box sx={{display: 'flex', flexDirection: 'column', flex: 1, overflow: 'hidden'}}>
<Box sx={{flex: 1}}/>
<List sx={{ width: drawer, overflow: 'auto'}}>
<ListItemButton onClick={props.openDownloads}>
<ListItemIcon>
<Badge badgeContent={getCount()} color='primary'>
<Download/>
</Badge>
</ListItemIcon>
<ListItemText primary={'Downloads'} secondary={getMessage()}/>
</ListItemButton>
<ListItemButton onClick={props.logout}>
<ListItemIcon>
<Logout/>
</ListItemIcon>
<ListItemText primary={'Logout'}/>
</ListItemButton>
</List>
</Box>
</Drawer>
)
}
11 changes: 9 additions & 2 deletions src/web/vaultBrowser/VaultBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { ArrowBack, Article, Delete, Download, Folder, Refresh } from "@mui/icons-material";
import { Box, AppBar, Toolbar, Typography, Tooltip, IconButton } from "@mui/material";
import { DataGrid, GridActionsCellItem, GridRenderCellParams, GridRowParams, GridSelectionModel } from "@mui/x-data-grid";
import { DirID, EncryptedDir, EncryptedItem, Vault } from "cryptomator-ts";
import { DirID, EncryptedDir, EncryptedItem, ItemPath, Vault } from "cryptomator-ts";
import { useEffect, useMemo, useState } from "react";
import { WebDAV } from "../../lib/cryptomator/WebDAV";
import { ItemDownloader } from "../ItemDownloader";

export function VaultBrowser(props: {vault: Vault, client: WebDAV, download: (item: EncryptedItem[], vault: Vault) => void}){
export function VaultBrowser(props: {
vault: Vault,
client: WebDAV,
download: (item: EncryptedItem[], vault: Vault) => void,
downloads: {[path: ItemPath]: ItemDownloader},
openDownloads: () => void
}){

const [dir, setDir] = useState<EncryptedDir[]>([]);
const [items, setItems] = useState<EncryptedItem[]>([]);
Expand Down