some refactoring

pull/134/head
Alex Kern 1 year ago
parent cc69bece47
commit 36a70f1d29
No known key found for this signature in database
GPG Key ID: EF051FACCACBEE25

@ -14,6 +14,8 @@ import Wordmark from '../components/Wordmark'
import CancelButton from '../components/CancelButton' import CancelButton from '../components/CancelButton'
import { useMemo } from 'react' import { useMemo } from 'react'
import { getFileName } from '../fs' import { getFileName } from '../fs'
import TitleText from '../components/TitleText'
import SubtitleText from '../components/SubtitleText'
const queryClient = new QueryClient() const queryClient = new QueryClient()
@ -26,7 +28,7 @@ function PageWrapper({
}): JSX.Element { }): JSX.Element {
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<div className="flex flex-col items-center space-y-5 py-10 max-w-2xl mx-auto"> <div className="flex flex-col items-center space-y-5 py-10 max-w-2xl mx-auto px-4">
<Spinner direction="up" isRotating={isRotating} /> <Spinner direction="up" isRotating={isRotating} />
<Wordmark /> <Wordmark />
{children} {children}
@ -43,12 +45,10 @@ function InitialState({
return ( return (
<PageWrapper> <PageWrapper>
<div className="flex flex-col items-center space-y-1 max-w-md"> <div className="flex flex-col items-center space-y-1 max-w-md">
<p className="text-lg text-center text-stone-800"> <TitleText>Peer-to-peer file transfers in your browser.</TitleText>
Peer-to-peer file transfers in your browser. <SubtitleText>
</p>
<p className="text-sm text-center text-stone-600">
We never store anything. Files only served fresh. We never store anything. Files only served fresh.
</p> </SubtitleText>
</div> </div>
<DropZone onDrop={onDrop} /> <DropZone onDrop={onDrop} />
</PageWrapper> </PageWrapper>
@ -70,23 +70,23 @@ function ConfirmUploadState({
onChangePassword, onChangePassword,
onCancel, onCancel,
onStart, onStart,
onFileListChange, onRemoveFile,
}: { }: {
uploadedFiles: UploadedFile[] uploadedFiles: UploadedFile[]
password: string password: string
onChangePassword: (pw: string) => void onChangePassword: (pw: string) => void
onCancel: () => void onCancel: () => void
onStart: () => void onStart: () => void
onFileListChange: (updatedFiles: UploadedFile[]) => void onRemoveFile: (index: number) => void
}): JSX.Element { }): JSX.Element {
const fileListData = useUploaderFileListData(uploadedFiles) const fileListData = useUploaderFileListData(uploadedFiles)
return ( return (
<PageWrapper> <PageWrapper>
<p className="text-lg text-center text-stone-800 max-w-md"> <TitleText>
You are about to start uploading {uploadedFiles.length}{' '} You are about to start uploading {uploadedFiles.length}{' '}
{uploadedFiles.length === 1 ? 'file' : 'files'}. {uploadedFiles.length === 1 ? 'file' : 'files'}.
</p> </TitleText>
<UploadFileList files={fileListData} onChange={onFileListChange} /> <UploadFileList files={fileListData} onRemove={onRemoveFile} />
<PasswordField value={password} onChange={onChangePassword} /> <PasswordField value={password} onChange={onChangePassword} />
<div className="flex space-x-4"> <div className="flex space-x-4">
<CancelButton onClick={onCancel} /> <CancelButton onClick={onCancel} />
@ -108,10 +108,10 @@ function UploadingState({
const fileListData = useUploaderFileListData(uploadedFiles) const fileListData = useUploaderFileListData(uploadedFiles)
return ( return (
<PageWrapper isRotating={true}> <PageWrapper isRotating={true}>
<p className="text-lg text-center text-stone-800 max-w-md"> <TitleText>
You are uploading {uploadedFiles.length}{' '} You are uploading {uploadedFiles.length}{' '}
{uploadedFiles.length === 1 ? 'file' : 'files'}. {uploadedFiles.length === 1 ? 'file' : 'files'}.
</p> </TitleText>
<UploadFileList files={fileListData} /> <UploadFileList files={fileListData} />
<WebRTCProvider> <WebRTCProvider>
<Uploader files={uploadedFiles} password={password} onStop={onStop} /> <Uploader files={uploadedFiles} password={password} onStop={onStop} />
@ -146,8 +146,8 @@ export default function UploadPage(): JSX.Element {
setUploading(false) setUploading(false)
}, []) }, [])
const handleFileListChange = useCallback((updatedFiles: UploadedFile[]) => { const handleRemoveFile = useCallback((index: number) => {
setUploadedFiles(updatedFiles) setUploadedFiles((fs) => fs.filter((_, i) => i !== index))
}, []) }, [])
if (!uploadedFiles.length) { if (!uploadedFiles.length) {
@ -162,7 +162,7 @@ export default function UploadPage(): JSX.Element {
onChangePassword={handleChangePassword} onChangePassword={handleChangePassword}
onCancel={handleCancel} onCancel={handleCancel}
onStart={handleStart} onStart={handleStart}
onFileListChange={handleFileListChange} onRemoveFile={handleRemoveFile}
/> />
) )
} }

@ -21,6 +21,7 @@ import UploadFileList from './UploadFileList'
import DownloadButton from './DownloadButton' import DownloadButton from './DownloadButton'
import StopButton from './StopButton' import StopButton from './StopButton'
import ProgressBar from './ProgressBar' import ProgressBar from './ProgressBar'
import TitleText from './TitleText'
const baseURL = process.env.NEXT_PUBLIC_BASE_URL ?? 'http://localhost:3000' const baseURL = process.env.NEXT_PUBLIC_BASE_URL ?? 'http://localhost:3000'
@ -315,9 +316,7 @@ export default function Downloader({
if (done && filesInfo) { if (done && filesInfo) {
return ( return (
<div className="flex flex-col space-y-5 w-full"> <div className="flex flex-col space-y-5 w-full">
<p className="text-description"> <TitleText>You downloaded {filesInfo.length} files.</TitleText>
You downloaded {filesInfo.length} files.
</p>
<UploadFileList files={filesInfo} /> <UploadFileList files={filesInfo} />
<div className="w-full"> <div className="w-full">
<ProgressBar value={bytesDownloaded} max={totalSize} /> <ProgressBar value={bytesDownloaded} max={totalSize} />
@ -329,9 +328,9 @@ export default function Downloader({
if (downloading && filesInfo) { if (downloading && filesInfo) {
return ( return (
<div className="flex flex-col space-y-5 w-full"> <div className="flex flex-col space-y-5 w-full">
<p className="text-description"> <TitleText>
You are about to start downloading {filesInfo.length} files. You are about to start downloading {filesInfo.length} files.
</p> </TitleText>
<UploadFileList files={filesInfo} /> <UploadFileList files={filesInfo} />
<div className="w-full"> <div className="w-full">
<ProgressBar value={bytesDownloaded} max={totalSize} /> <ProgressBar value={bytesDownloaded} max={totalSize} />
@ -344,9 +343,9 @@ export default function Downloader({
if (open && filesInfo) { if (open && filesInfo) {
return ( return (
<div className="flex flex-col space-y-5 w-full"> <div className="flex flex-col space-y-5 w-full">
<p className="text-description"> <TitleText>
You are about to start downloading {filesInfo.length} files. You are about to start downloading {filesInfo.length} files.
</p> </TitleText>
<UploadFileList files={filesInfo} /> <UploadFileList files={filesInfo} />
<DownloadButton onClick={handleStartDownload} /> <DownloadButton onClick={handleStartDownload} />
</div> </div>
@ -371,9 +370,9 @@ export default function Downloader({
> >
<div className="flex flex-col space-y-5 w-full"> <div className="flex flex-col space-y-5 w-full">
{errorMessage ? ( {errorMessage ? (
<p className="text-description-error">{errorMessage}</p> <TitleText>{errorMessage}</TitleText>
) : ( ) : (
<p className="text-description">This download requires a password.</p> <TitleText>This download requires a password.</TitleText>
)} )}
<PasswordField <PasswordField
value={password} value={password}

@ -0,0 +1,11 @@
import React from 'react'
interface SubtitleTextProps {
children: React.ReactNode
}
const SubtitleText: React.FC<SubtitleTextProps> = ({ children }) => {
return <p className="text-sm text-center text-stone-600">{children}</p>
}
export default SubtitleText

@ -0,0 +1,11 @@
import React from 'react'
export default function TitleText({
children,
}: {
children: React.ReactNode
}): JSX.Element {
return (
<p className="text-lg text-center text-stone-800 max-w-md">{children}</p>
)
}

@ -8,30 +8,23 @@ type UploadedFileLike = {
export default function UploadFileList({ export default function UploadFileList({
files, files,
onChange, onRemove,
}: { }: {
files: UploadedFileLike[] files: UploadedFileLike[]
onChange?: (updatedFiles: UploadedFileLike[]) => void onRemove?: (index: number) => void
}): JSX.Element { }): JSX.Element {
function handleRemove(index: number): void {
if (onChange) {
const updatedFiles = files.filter((_, i) => i !== index)
onChange(updatedFiles)
}
}
const items = files.map((f: UploadedFileLike, i: number) => ( const items = files.map((f: UploadedFileLike, i: number) => (
<div <div
key={f.fileName} key={f.fileName}
className="w-full border border-stone-300 rounded-md mb-2 group" className={`w-full border-b border-stone-300 last:border-0`}
> >
<div className="flex justify-between items-center py-2 px-2.5"> <div className="flex justify-between items-center py-2 px-2.5">
<p className="truncate text-sm font-medium">{f.fileName}</p> <p className="truncate text-sm font-medium">{f.fileName}</p>
<div className="flex items-center"> <div className="flex items-center">
<TypeBadge type={f.type} /> <TypeBadge type={f.type} />
{onChange && ( {onRemove && (
<button <button
onClick={() => handleRemove(i)} onClick={() => onRemove?.(i)}
className="text-stone-500 hover:text-stone-700 focus:outline-none" className="text-stone-500 hover:text-stone-700 focus:outline-none"
> >
@ -42,5 +35,9 @@ export default function UploadFileList({
</div> </div>
)) ))
return <div className="w-full">{items}</div> return (
<div className="w-full border border-stone-300 rounded-md shadow-sm">
{items}
</div>
)
} }

Loading…
Cancel
Save