feat: Added top menu

This commit is contained in:
florian 2024-05-09 17:32:14 +02:00
parent b7c27ddc8a
commit b7949c38a4
6 changed files with 126 additions and 127 deletions

View File

@ -37,11 +37,13 @@ const ensureDecrypted = async (dvm: NDKUser, event: NDKEvent) => {
return event;
};
const NPUB_DVM_THUMBNAIL_CREATION = 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s';
const FileEventEditor = ({ data }: { data: FileEventData }) => {
const [fileEventData, setFileEventData] = useState(data);
const [thumbnailRequestEventId, setThumbnailRequestEventId] = useState<string | undefined>();
const { ndk, user } = useNDK();
const dvm = ndk.getUser({ npub: 'npub1q8cv87l47fql2xer2uyw509y5n5s9f53h76hvf9377efdptmsvusxf3n8s' });
const dvm = ndk.getUser({ npub: NPUB_DVM_THUMBNAIL_CREATION });
const thumbnailDvmFilter = useMemo(
() => ({ kinds: [6204 as NDKKind], '#e': [thumbnailRequestEventId || ''] }),

View File

@ -6,38 +6,11 @@
@apply flex flex-col self-center md:w-10/12 w-full min-h-[80vh] px-4 md:px-0;
}
.title {
@apply text-neutral-content text-4xl flex flex-row items-center gap-2 p-4 md:w-10/12 w-full self-center;
}
.title img {
@apply w-10;
}
.title a.action {
@apply flex flex-col text-sm items-center opacity-50 hover:opacity-100 cursor-pointer px-2;
}
.title a.logo {
@apply flex flex-row flex-grow items-center gap-2 cursor-pointer;
}
.title span {
@apply flex-grow;
}
.title svg {
@apply w-7;
}
.avatar {
@apply flex-shrink;
}
.avatar img {
@apply w-10 h-10 rounded-full;
}
.footer {
@apply justify-center gap-1 text-base-content pt-12 pb-6;
}
.btn svg {
@apply w-8;
}

View File

@ -1,7 +1,7 @@
import { Outlet, useNavigate } from 'react-router-dom';
import { useNDK } from '../../utils/ndk';
import './Layout.css';
import { ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
import { ArrowUpOnSquareIcon, MagnifyingGlassIcon, ServerStackIcon } from '@heroicons/react/24/outline';
import { useEffect } from 'react';
import ThemeSwitcher from '../ThemeSwitcher';
@ -15,22 +15,36 @@ export const Layout = () => {
return (
<div className="main">
<div className="title">
<a className="logo" onClick={() => navigate('/')}>
<img src="/bouquet.png" /> <span>bouquet</span>
</a>
<div>
<div className="navbar bg-base-300">
<div className="navbar-start">
<button className="btn btn-ghost text-xl">
<a className="logo" onClick={() => navigate('/')}>
<img className="w-8" src="/bouquet.png" />{' '}
</a>
<span>bouquet</span>
</button>
</div>
<div className="navbar-center">
<button className=" btn btn-ghost" onClick={() => navigate('/upload')}>
<ArrowUpOnSquareIcon /> Upload
</button>
<button className=" btn btn-ghost" onClick={() => navigate('/')}>
<MagnifyingGlassIcon /> Browse
</button>
<button className=" btn btn-ghost" onClick={() => navigate('/transfer')}>
<ServerStackIcon /> Sync
</button>
</div>
<div className="navbar-end">
<ThemeSwitcher />
<div className="tooltip tooltip-bottom" data-tip="Upload">
<button className=" btn btn-square btn-ghost" onClick={() => navigate('/upload')}>
<ArrowUpOnSquareIcon />
</button>
<div className="avatar px-4">
<div className="w-12 rounded-full">
<img src={user?.profile?.image} />
</div>
</div>
</div>
<div className="avatar">
<img src={user?.profile?.image} />
</div>
</div>
<div className="content">{<Outlet />}</div>
<div className="footer">
made with 💜 by{' '}

View File

@ -14,8 +14,8 @@ const ThemeSwitcher = () => {
<div className="tooltip tooltip-bottom" data-tip="Switch theme">
<label className="swap swap-rotate">
<input onClick={toggleTheme} type="checkbox" />
<MoonIcon className="tooltip swap-on" />
<SunIcon className="tooltip swap-off" />
<MoonIcon className="w-8 tooltip swap-on" />
<SunIcon className="w-8 *:tooltip swap-off" />
</label>
</div>
);

View File

@ -41,6 +41,7 @@ const router = createBrowserRouter(
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="/transfer/:source" element={<Transfer />} />
<Route path="/transfer" element={<Transfer />} />
<Route path="/upload" element={<Upload />} />
<Route path="/check/:source" element={<Check />} />
</Route>

View File

@ -27,7 +27,8 @@ type TransferStatus = {
};
export const Transfer = () => {
const { source: transferSource } = useParams();
const { source } = useParams();
const [transferSource, setTransferSource] = useState(source);
const navigate = useNavigate();
const { serverInfo } = useServerInfo();
const [transferTarget, setTransferTarget] = useState<string | undefined>();
@ -100,88 +101,96 @@ export const Transfer = () => {
return { ...stats, fullSize: transferJobs?.reduce((acc, b) => acc + b.size, 0) || 0 };
}, [transferLog, transferJobs]);
return (
transferSource && (
<>
<ServerList
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
onCancel={() => closeTransferMode()}
title={
<>
<ArrowUpOnSquareIcon /> Transfer Source
</>
}
></ServerList>
<ServerList
servers={Object.values(serverInfo)
.filter(s => s.name != transferSource)
.sort()}
selectedServer={transferTarget}
setSelectedServer={setTransferTarget}
title={
<>
<ArrowDownOnSquareIcon /> Transfer Target
</>
}
></ServerList>
{transferTarget && transferJobs && transferJobs.length > 0 ? (
return transferSource ? (
<>
<ServerList
servers={Object.values(serverInfo).filter(s => s.name == transferSource)}
onCancel={() => closeTransferMode()}
title={
<>
<div className=" bg-base-200 rounded-xl p-4 text-neutral-content gap-4 flex flex-col my-4">
<div className="message">
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
{!started && (
<button
className="action-button"
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
>
<ArrowUpOnSquareIcon />
Start
</button>
)}
</div>
<div className="w-5/6">
<ProgressBar
value={transferStatus.size}
max={transferStatus.fullSize}
description={
formatFileSize(transferStatus.size) +
' / ' +
formatFileSize(transferStatus.fullSize) +
' transferred'
}
/>
{<div className="message"></div>}
<div className="error-log">
{Object.values(transferLog)
.filter(b => b.status == 'error')
.map(t => (
<div>
<span>
<DocumentIcon />
</span>
<span>{t.sha256}</span>
<span>{formatFileSize(t.size)}</span>
<span>{t.status && (t.status == 'error' ? <ExclamationTriangleIcon /> : '')}</span>
<span>{t.message}</span>
</div>
))}
</div>
<ArrowUpOnSquareIcon /> Transfer Source
</>
}
></ServerList>
<ServerList
servers={Object.values(serverInfo)
.filter(s => s.name != transferSource)
.sort()}
selectedServer={transferTarget}
setSelectedServer={setTransferTarget}
title={
<>
<ArrowDownOnSquareIcon /> Transfer Target
</>
}
></ServerList>
{transferTarget && transferJobs && transferJobs.length > 0 ? (
<>
<div className=" bg-base-200 rounded-xl p-4 text-neutral-content gap-4 flex flex-col my-4">
<div className="message">
{transferJobs.length} object{transferJobs.length > 1 ? 's' : ''} to transfer{' '}
{!started && (
<button
className="action-button"
onClick={() => performTransfer(transferSource, transferTarget, transferJobs)}
>
<ArrowUpOnSquareIcon />
Start
</button>
)}
</div>
<div className="w-5/6">
<ProgressBar
value={transferStatus.size}
max={transferStatus.fullSize}
description={
formatFileSize(transferStatus.size) + ' / ' + formatFileSize(transferStatus.fullSize) + ' transferred'
}
/>
{<div className="message"></div>}
<div className="error-log">
{Object.values(transferLog)
.filter(b => b.status == 'error')
.map(t => (
<div>
<span>
<DocumentIcon />
</span>
<span>{t.sha256}</span>
<span>{formatFileSize(t.size)}</span>
<span>{t.status && (t.status == 'error' ? <ExclamationTriangleIcon /> : '')}</span>
<span>{t.message}</span>
</div>
))}
</div>
</div>
{!started && <BlobList blobs={transferJobs}></BlobList>}
</>
) : (
<div className="message">
{transferTarget ? (
<>
<CheckBadgeIcon /> no missing objects to transfer
</>
) : (
<>choose a transfer target above</>
)}
</div>
)}
</>
)
{!started && <BlobList blobs={transferJobs}></BlobList>}
</>
) : (
<div className="message">
{transferTarget ? (
<>
<CheckBadgeIcon /> no missing objects to transfer
</>
) : (
<>choose a transfer target above</>
)}
</div>
)}
</>
) : (
<>
<ServerList
title={
<>
<ArrowUpOnSquareIcon /> Transfer Source
</>
}
servers={Object.values(serverInfo).sort()}
selectedServer={transferSource}
setSelectedServer={s => setTransferSource(s)}
></ServerList>
</>
);
};