Skip to content
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
5 changes: 5 additions & 0 deletions servers/demo/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,10 @@
title="Customized default UI"
description="See how you can tailor Flottform's default UI to better match your design, while still retaining all the powerful features of the original interface. This demo lets you explore how easy it is to adapt the default elements to fit seamlessly with your brand's style."
/>
<DemoLink
href="{base}/remote-file-drop"
title="Remote File Drop"
description="Move files from your phone to your computer in seconds."
/>
</div>
</section>
172 changes: 172 additions & 0 deletions servers/demo/src/routes/remote-file-drop/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FlottformFileInputHost } from '@flottform/forms';
import { sdpExchangeServerBase, createCustomClientUrl } from '../../api';
let createWebRtcChannel: () => void;
let connectionStatus = 'new';
let connectionInfo = { link: '', qrCode: '' };
let progress = { currentFileNumber: 0, totalNumberOfFiles: 0, currentFileName: '' };
let error = '';
Comment on lines +5 to +9
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$state runes here?


const copyToClipboard = (link: string) => {
navigator.clipboard.writeText(link);
};

onMount(async () => {
const flottformFileInputHost = new FlottformFileInputHost({
flottformApi: sdpExchangeServerBase,
createClientUrl: createCustomClientUrl
});

flottformFileInputHost.on('new', () => {
createWebRtcChannel = flottformFileInputHost.start;
connectionStatus = 'new';
});

flottformFileInputHost.on('endpoint-created', ({ link, qrCode }) => {
connectionInfo.link = link;
connectionInfo.qrCode = qrCode;
connectionStatus = 'endpoint-created';
});

flottformFileInputHost.on('connected', () => {
connectionStatus = 'connected';
});

flottformFileInputHost.on('webrtc:waiting-for-ice', () => {});

flottformFileInputHost.on('receive', () => {
connectionStatus = 'receive';
});

flottformFileInputHost.on(
'progress',
({
fileIndex,
totalFileCount,
fileName,
currentFileProgress,
overallProgress
}: {
fileIndex: number;
totalFileCount: number;
fileName: string;
currentFileProgress: number;
overallProgress: number;
}) => {
connectionStatus = 'progress';
progress.currentFileName = fileName;
progress.currentFileNumber = fileIndex + 1;
progress.totalNumberOfFiles = totalFileCount;
}
);

flottformFileInputHost.on('single-file-transferred', (receivedFile) => {
connectionStatus = 'single-file-transferred';

const url = window.URL.createObjectURL(receivedFile);
const a = document.createElement('a');
a.href = url;
a.download = receivedFile.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
Comment on lines +67 to +74
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be put this into links for downloading

});

flottformFileInputHost.on('done', () => {
connectionStatus = 'done';
});

flottformFileInputHost.on('error', (e) => {
connectionStatus = 'error';
error = e.message;
});
});
</script>

<svelte:head>
<title>Flottform DEMO</title>
</svelte:head>

<div class="min-h-screen flex items-center justify-center overflow-hidden bg-gray-50">
<div class="max-w-screen-xl w-full p-4 box-border flex flex-col items-center">
<h1 class="text-2xl font-bold text-gray-800 mb-8">Remote File Drop</h1>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to add links to the individual files here as a list instead of starting a download of them directly - this allows users to change file names and the folder when they save it.

<div class="w-full max-w-md p-8 bg-white shadow-lg rounded-lg">
{#if connectionStatus === 'new'}
<div class="flex flex-col items-center w-full">
<p class="mb-8 text-center">Start a new connection to receive files</p>
<button
on:click={createWebRtcChannel}
class="bg-[#1a3066] hover:bg-[#2b4fa6] text-white px-4 py-2 rounded-lg text-base"
>Start Connection</button
>
</div>
{/if}

{#if connectionStatus === 'endpoint-created'}
Comment on lines +106 to +108
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these could be turned into {:else if connectionStatus === '...'}, so it's easier to see these parts are never shown at the same time

<div class="flex flex-col items-center space-y-4 w-full mb-8">
<div class="w-full max-w-xs">
<img src={connectionInfo.qrCode} alt="QR Code" class="w-full h-auto" />
</div>
<p class="mt-4 text-center">
Scan the QR code or use the link below to connect your device
</p>
<div class="w-full flex items-center gap-2 bg-slate-100 p-2 rounded mt-4">
<code class="flex-1 truncate text-sm">{connectionInfo.link}</code>
<button
class="shrink-0 bg-transparent bg-[#1a3066] hover:bg-[#2b4fa6] text-white px-4 py-2 rounded-lg text-base"
on:click={() => copyToClipboard(connectionInfo.link)}
>
Copy
</button>
</div>
</div>
{/if}

{#if connectionStatus === 'connected'}
<p class="text-center">Connected and Waiting to Receive file(s)</p>
{/if}

{#if connectionStatus === 'progress'}
<p class="mb-2 text-center">Receiving: {progress.currentFileName}</p>

<div class="w-full overflow-hidden rounded bg-[#f1f5f9] h-2">
<div
class="transition-[width] duration-300 ease-[ease] bg-[#3b82f6] h-full"
style="width: {(progress.currentFileNumber / progress.totalNumberOfFiles) * 100}%"
></div>
</div>
<p class="text-right text-[#64748b] text-sm mt-4">
{progress.currentFileNumber} of {progress.totalNumberOfFiles} files
</p>
{/if}

{#if connectionStatus === 'done'}
<div class="flex flex-col items-center w-full">
<div class="mb-2 text-4xl text-[#22c55e]">✓</div>
<p class="text-center">All files received successfully!</p>
<button
on:click={createWebRtcChannel}
class="bg-[#1a3066] hover:bg-[#2b4fa6] text-white px-4 py-2 rounded-lg text-base"
>Start New Transfer</button
>
</div>
{/if}

{#if connectionStatus === 'error'}
<div class="flex flex-col items-center w-full gap-4">
<p class="text-center text-red-500">
File Transfer Failed with the following error: {error}
</p>
<button
on:click={createWebRtcChannel}
class="bg-[#1a3066] hover:bg-[#2b4fa6] text-white px-4 py-2 rounded-lg text-base"
>Try Again</button
>
</div>
{/if}
</div>
</div>
</div>