diff --git a/web/src/routes/clipboard/+page.svelte b/web/src/routes/clipboard/+page.svelte index 06b9cb4f..5ebd9aa0 100644 --- a/web/src/routes/clipboard/+page.svelte +++ b/web/src/routes/clipboard/+page.svelte @@ -22,6 +22,9 @@ receivedSize: number; } + // Constants + const CHUNK_SIZE = 64 * 1024; // 64KB chunks for file transfer + // State variables let sessionId = ''; let joinCode = ''; @@ -32,6 +35,9 @@ let peerConnected = false; let qrCodeUrl = ''; + // Navigation state + let activeTab: 'files' | 'text' = 'files'; + // WebSocket and WebRTC let ws: WebSocket | null = null; let peerConnection: RTCPeerConnection | null = null; @@ -40,17 +46,17 @@ // Encryption let keyPair: CryptoKeyPair | null = null; let remotePublicKey: CryptoKey | null = null; - let sharedKey: CryptoKey | null = null; - - // File transfer + let sharedKey: CryptoKey | null = null; // File transfer let files: File[] = []; let receivedFiles: FileItem[] = []; let textContent = ''; + let receivedText = ''; let dragover = false; let sendingFiles = false; let receivingFiles = false; let transferProgress = 0; let currentReceivingFile: ReceivingFile | null = null; + let fileInput: HTMLInputElement; // Session persistence let storedSessionId = ''; @@ -184,8 +190,7 @@ was: wasConnected, now: isNowConnected, readyState: dataChannel.readyState - }); - peerConnected = isNowConnected; + }); peerConnected = isNowConnected; } } }, 1000); @@ -709,9 +714,8 @@ const message = JSON.parse(decryptedMessage); console.log('📩 Decrypted message type:', message.type); - - if (message.type === 'text') { - textContent = message.data; + if (message.type === 'text') { + receivedText = message.data; console.log('📝 Text content received'); } else if (message.type === 'file_info') { currentReceivingFile = { @@ -1018,9 +1022,7 @@ } else { console.log('⚠️ Only creator can initiate restart. Waiting for creator to restart...'); } - } - - function cleanup(): void { + } function cleanup(): void { if (dataChannel) { dataChannel.close(); dataChannel = null; @@ -1040,6 +1042,11 @@ sharedKey = null; remotePublicKey = null; qrCodeUrl = ''; + clearStoredSession(); + } + + function switchTab(tab: 'files' | 'text'): void { + activeTab = tab; } @@ -1061,9 +1068,11 @@

{$t("clipboard.create_session")}

-

{$t("clipboard.create_description")}

{$t("clipboard.create_description")}

+ {isCreating ? $t("clipboard.creating") : $t("clipboard.create")} @@ -1082,7 +1091,8 @@ bind:value={joinCode} placeholder={$t("clipboard.enter_code")} disabled={isJoining} - /> + {:else} +
-

{$t("clipboard.session_active")}

{$t("clipboard.session_id")}: {sessionId} + + 📋 +
{#if isCreator && sessionId && !peerConnected && qrCodeUrl} @@ -1109,12 +1125,184 @@ QR Code
{/if} -
+ +
{peerConnected ? $t("clipboard.peer_connected") : $t("clipboard.waiting_peer")}
- -
+
+
+ + + {#if peerConnected} + +
+ + +
+ + + {#if activeTab === 'files'} + +
+
+

发送文件

+
+

拖放文件到这里或点击选择

+ + fileInput?.click()} + > + 选择文件 + +
+ + {#if files.length > 0} +
+

待发送文件:

+ {#each files as file, index} +
+ {file.name} + ({formatFileSize(file.size)}) + +
+ {/each} + + {sendingFiles ? '发送中...' : '发送文件'} + +
+ {/if} + + {#if sendingFiles} +
+

发送进度:

+
+
+
+ {Math.round(transferProgress)}% +
+ {/if} +
+ +
+

接收到的文件

+ {#if receivedFiles.length > 0} +
+ {#each receivedFiles as file, index} +
+ {file.name} + ({formatFileSize(file.size)}) + downloadReceivedFile(file)} + > + 下载 + + +
+ {/each} +
+ {:else} +

还没有接收到任何文件

+ {/if} + + {#if receivingFiles && currentReceivingFile} +
+

接收文件:{currentReceivingFile.name}

+
+
+
+ {Math.round(transferProgress)}% ({formatFileSize(currentReceivingFile.receivedSize)} / {formatFileSize(currentReceivingFile.size)}) +
+ {/if} +
+
+
+ {/if} + + + {#if activeTab === 'text'} + +
+
+

发送文本

+ + + 发送文本 + +
+

接收到的文本

+ {#if receivedText} +
+
{receivedText}
+ navigator.clipboard.writeText(receivedText)} + > + 复制文本 + +
+ {:else} +

还没有接收到任何文本

+ {/if} +
+
+ {/if} + {/if} + + + +
🔧 Connection Debug
@@ -1197,110 +1385,14 @@
  • NAT traversal problems
  • Try the "Restart WebRTC" button above. -
    - {/if} +
    {/if}
    -
    - - {#if peerConnected} - -
    -

    {$t("clipboard.send_text")}

    - - {$t("clipboard.send")} - -
    -
    - - -
    -

    {$t("clipboard.send_files")}

    -
    -
    -

    {$t("clipboard.drop_files")}

    - document.getElementById('file-input')?.click()}> - {$t("clipboard.select_files")} - -
    -
    - - {#if files.length > 0} -
    - {#each files as file, index} -
    - {file.name} - ({formatFileSize(file.size)}) - -
    - {/each} - {sendingFiles ? $t("clipboard.sending") : $t("clipboard.send")} - - - {#if sendingFiles || transferProgress > 0} -
    -
    -
    - {Math.round(transferProgress)}% - {/if} -
    - {/if} -
    -
    - - {#if receivedFiles.length > 0} - -
    -

    {$t("clipboard.received_files")}

    -
    - {#each receivedFiles as file, index} -
    - {file.name} - ({formatFileSize(file.size)}) -
    - - -
    -
    - {/each} -
    -
    -
    - {/if} - - {#if receivingFiles && currentReceivingFile} - -
    -

    {$t("clipboard.receiving")}: {currentReceivingFile.name}

    -
    -
    -
    - {Math.round(transferProgress)}% ({formatFileSize(currentReceivingFile.receivedSize)} / {formatFileSize(currentReceivingFile.size)}) -
    -
    - {/if} - {/if}
    + +
    {$t("clipboard.disconnect")} @@ -1309,6 +1401,200 @@