Skip to content

Added support for "sharedSlug" where multiple uploaders can share files #268

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/app/api/create/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { NextResponse } from 'next/server'
import { getOrCreateChannelRepo } from '../../../channel'

export async function POST(request: Request): Promise<NextResponse> {
const { uploaderPeerID } = await request.json()
const { uploaderPeerID, sharedSlug } = await request.json()

if (!uploaderPeerID) {
return NextResponse.json(
Expand All @@ -11,6 +11,6 @@ export async function POST(request: Request): Promise<NextResponse> {
)
}

const channel = await getOrCreateChannelRepo().createChannel(uploaderPeerID)
const channel = await getOrCreateChannelRepo().createChannel(uploaderPeerID, undefined, sharedSlug)
return NextResponse.json(channel)
}
}
12 changes: 10 additions & 2 deletions src/app/download/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getOrCreateChannelRepo } from '../../../channel'
import Spinner from '../../../components/Spinner'
import Wordmark from '../../../components/Wordmark'
import Downloader from '../../../components/Downloader'
import MultiDownloader from '../../../components/MultiDownloader'
import WebRTCPeerProvider from '../../../components/WebRTCProvider'
import ReportTermsViolationButton from '../../../components/ReportTermsViolationButton'

Expand Down Expand Up @@ -33,12 +34,19 @@ export default async function DownloadPage({
<Spinner direction="down" />
<Wordmark />
<WebRTCPeerProvider>
<Downloader uploaderPeerID={channel.uploaderPeerID} />
{channel.additionalUploaders && channel.additionalUploaders.length > 0 ? (
<MultiDownloader
primaryUploaderID={channel.uploaderPeerID}
additionalUploaders={channel.additionalUploaders}
/>
) : (
<Downloader uploaderPeerID={channel.uploaderPeerID} />
)}
<ReportTermsViolationButton
uploaderPeerID={channel.uploaderPeerID}
slug={slug}
/>
</WebRTCPeerProvider>
</div>
)
}
}
43 changes: 36 additions & 7 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
'use client'

import React, { JSX, useCallback, useState } from 'react'
import React, { JSX, useCallback, useState, useMemo } from 'react'
import { getFileName } from '../fs'
import { UploadedFile } from '../types'
import { pluralize } from '../utils/pluralize'
import WebRTCPeerProvider from '../components/WebRTCProvider'
import DropZone from '../components/DropZone'
import UploadFileList from '../components/UploadFileList'
import Uploader from '../components/Uploader'
import PasswordField from '../components/PasswordField'
import SharedLinkField from '../components/SharedLinkField'
import StartButton from '../components/StartButton'
import { UploadedFile } from '../types'
import Spinner from '../components/Spinner'
import Wordmark from '../components/Wordmark'
import CancelButton from '../components/CancelButton'
import { useMemo } from 'react'
import { getFileName } from '../fs'
import TitleText from '../components/TitleText'
import { pluralize } from '../utils/pluralize'
import TermsAcceptance from '../components/TermsAcceptance'

function PageWrapper({ children }: { children: React.ReactNode }): JSX.Element {
Expand Down Expand Up @@ -52,17 +52,33 @@ function useUploaderFileListData(uploadedFiles: UploadedFile[]) {
}, [uploadedFiles])
}

function extractSlugFromLink(link: string): string | undefined {
if (!link) return undefined

try {
const url = new URL(link)
const pathParts = url.pathname.split('/')
return pathParts[pathParts.length - 1]
} catch {
return link.trim() ? link.trim() : undefined
}
}

function ConfirmUploadState({
uploadedFiles,
password,
sharedLink,
onChangePassword,
onChangeSharedLink,
onCancel,
onStart,
onRemoveFile,
}: {
uploadedFiles: UploadedFile[]
password: string
sharedLink: string
onChangePassword: (pw: string) => void
onChangeSharedLink: (link: string) => void
onCancel: () => void
onStart: () => void
onRemoveFile: (index: number) => void
Expand All @@ -76,6 +92,7 @@ function ConfirmUploadState({
</TitleText>
<UploadFileList files={fileListData} onRemove={onRemoveFile} />
<PasswordField value={password} onChange={onChangePassword} />
<SharedLinkField value={sharedLink} onChange={onChangeSharedLink} />
<div className="flex space-x-4">
<CancelButton onClick={onCancel} />
<StartButton onClick={onStart} />
Expand All @@ -87,21 +104,25 @@ function ConfirmUploadState({
function UploadingState({
uploadedFiles,
password,
sharedLink,
onStop,
}: {
uploadedFiles: UploadedFile[]
password: string
sharedLink: string
onStop: () => void
}): JSX.Element {
const fileListData = useUploaderFileListData(uploadedFiles)
const sharedSlug = extractSlugFromLink(sharedLink)

return (
<PageWrapper>
<TitleText>
You are uploading {pluralize(uploadedFiles.length, 'file', 'files')}.
</TitleText>
<UploadFileList files={fileListData} />
<WebRTCPeerProvider>
<Uploader files={uploadedFiles} password={password} onStop={onStop} />
<Uploader files={uploadedFiles} password={password} sharedSlug={sharedSlug} onStop={onStop} />
</WebRTCPeerProvider>
</PageWrapper>
)
Expand All @@ -110,6 +131,7 @@ function UploadingState({
export default function UploadPage(): JSX.Element {
const [uploadedFiles, setUploadedFiles] = useState<UploadedFile[]>([])
const [password, setPassword] = useState('')
const [sharedLink, setSharedLink] = useState('')
const [uploading, setUploading] = useState(false)

const handleDrop = useCallback((files: UploadedFile[]): void => {
Expand All @@ -120,6 +142,10 @@ export default function UploadPage(): JSX.Element {
setPassword(pw)
}, [])

const handleChangeSharedLink = useCallback((link: string) => {
setSharedLink(link)
}, [])

const handleStart = useCallback(() => {
setUploading(true)
}, [])
Expand All @@ -146,7 +172,9 @@ export default function UploadPage(): JSX.Element {
<ConfirmUploadState
uploadedFiles={uploadedFiles}
password={password}
sharedLink={sharedLink}
onChangePassword={handleChangePassword}
onChangeSharedLink={handleChangeSharedLink}
onCancel={handleCancel}
onStart={handleStart}
onRemoveFile={handleRemoveFile}
Expand All @@ -158,7 +186,8 @@ export default function UploadPage(): JSX.Element {
<UploadingState
uploadedFiles={uploadedFiles}
password={password}
sharedLink={sharedLink}
onStop={handleStop}
/>
)
}
}
Loading