# File Transfer Flow Source: https://docsdrop.erikraft.com/architecture/file-transfer-flow Complete file transfer process from selection to completion in ErikrafT Drop's peer-to-peer system. # File Transfer Flow ErikrafT Drop implements a sophisticated file transfer system that handles everything from small text messages to large multi-gigabyte files. The system uses WebRTC DataChannels for direct peer-to-peer transfers with WebSocket fallback when necessary. ## Transfer Lifecycle Overview ```mermaid theme={null} flowchart TD A[File Selection] --> B[Metadata Preparation] B --> C[Transfer Request] C --> D[Recipient Response] D --> E{Accepted?} E -->|Yes| F[Header Transmission] E -->|No| G[Transfer Cancelled] F --> H[File Chunking] H --> I[Sequential Transfer] I --> J[Progress Tracking] J --> K{Transfer Complete?} K -->|No| I K -->|Yes| L[Completion Notification] L --> M[File Assembly] ``` ## File Selection and Metadata ### File Processing ```javascript theme={null} // From network.js lines 675-702 async requestFileTransfer(files) { let header = []; let totalSize = 0; let imagesOnly = true; for (let i = 0; i < files.length; i++) { const file = files[i]; const fileHeader = { name: file.name, size: file.size, mime: file.type || mime.defaultMime }; header.push(fileHeader); totalSize += file.size; if (!mime.isImage(file)) { imagesOnly = false; } } this._filesRequested = files; this.sendJSON({ type: 'request', header: header, totalSize: totalSize, imagesOnly: imagesOnly }); } ``` ### MIME Type Detection The system automatically detects and adds missing MIME types: ```javascript theme={null} // From network.js line 1464 let files = mime.addMissingMimeTypesToFiles([...message.files]); ``` ## Transfer Request Protocol ### Request Message Structure ```javascript theme={null} { type: 'request', header: [ { name: 'document.pdf', size: 1048576, mime: 'application/pdf' } ], totalSize: 1048576, imagesOnly: false } ``` ### Request Handling ```javascript theme={null} // From network.js lines 813-839 _onFilesTransferRequest(request) { if (this._requestPending) { this.sendJSON({type: 'files-transfer-response', accepted: false}); return; } if (window.iOS && request.totalSize >= 200*1024*1024) { this.sendJSON({ type: 'files-transfer-response', accepted: false, reason: 'ios-memory-limit' }); return; } this._requestPending = request; Events.fire('files-transfer-request', { request: request, peerId: this._peerId }); } ``` ## File Chunking System ### FileChunker Class The `FileChunker` class breaks large files into manageable chunks: ```javascript theme={null} // From network.js lines 1668-1716 class FileChunker { constructor(file, onChunk, onPartitionEnd) { this._chunkSize = 64000; // 64 KB this._maxPartitionSize = 1e6; // 1 MB this._offset = 0; this._partitionSize = 0; this._file = file; this._onChunk = onChunk; this._onPartitionEnd = onPartitionEnd; this._reader = new FileReader(); this._reader.addEventListener('load', e => this._onChunkRead(e.target.result)); } } ``` ### Chunk Reading Process ```javascript theme={null} // From network.js lines 1687-1702 _readChunk() { const chunk = this._file.slice(this._offset, this._offset + this._chunkSize); this._reader.readAsArrayBuffer(chunk); } _onChunkRead(chunk) { this._offset += chunk.byteLength; this._partitionSize += chunk.byteLength; this._onChunk(chunk); if (this.isFileEnd()) return; if (this._isPartitionEnd()) { this._onPartitionEnd(this._offset); return; } this._readChunk(); } ``` ## Transfer Execution ### Header Transmission ```javascript theme={null} // From network.js lines 729-748 async _sendFile(file) { this.sendJSON({ type: 'header', size: file.size, name: file.name, mime: file.type || mime.defaultMime }); this._chunker = new FileChunker( file, chunk => this._send(chunk), offset => this._onPartitionEnd(offset) ); this._chunker.nextPartition(); } ``` ### Progress Tracking ```javascript theme={null} // From network.js lines 763-765 _sendProgress(progress) { this.sendJSON({ type: 'progress', progress: progress }); } ``` ### Partition Management ```javascript theme={null} // From network.js lines 750-756 _onPartitionEnd(offset) { this.sendJSON({ type: 'partition', offset: offset }); } _onReceivedPartitionEnd(offset) { this.sendJSON({ type: 'partition-received', offset: offset }); } ``` ## File Reception and Assembly ### FileDigester Class The `FileDigester` class reassembles received chunks: ```javascript theme={null} // From network.js lines 1718-1746 class FileDigester { constructor(meta, totalSize, totalBytesReceived, callback) { this._buffer = []; this._bytesReceived = 0; this._size = meta.size; this._name = meta.name; this._mime = meta.mime; this._totalSize = totalSize; this._totalBytesReceived = totalBytesReceived; this._callback = callback; } unchunk(chunk) { this._buffer.push(chunk); this._bytesReceived += chunk.byteLength || chunk.size; this.progress = (this._totalBytesReceived + this._bytesReceived) / this._totalSize; if (isNaN(this.progress)) this.progress = 1; if (this._bytesReceived < this._size) return; const blob = new Blob(this._buffer); this._buffer = null; this._callback(new File([blob], this._name, { type: this._mime || "application/octet-stream", lastModified: new Date().getTime() })); } } ``` ## Message Types and Protocols ### Transfer Control Messages #### Request Message ```javascript theme={null} { type: 'request', header: [...], totalSize: number, imagesOnly: boolean } ``` #### Response Message ```javascript theme={null} { type: 'files-transfer-response', accepted: boolean, reason?: string } ``` #### Header Message ```javascript theme={null} { type: 'header', name: string, size: number, mime: string } ``` #### Progress Message ```javascript theme={null} { type: 'progress', progress: number // 0.0 to 1.0 } ``` #### Partition Messages ```javascript theme={null} { type: 'partition', offset: number } { type: 'partition-received', offset: number } ``` #### Completion Messages ```javascript theme={null} { type: 'file-transfer-complete' } { type: 'message-transfer-complete' } ``` ## Error Handling and Recovery ### Transfer Cancellation ```javascript theme={null} // From network.js lines 841-847 _respondToFileTransferRequest(accepted) { this.sendJSON({type: 'files-transfer-response', accepted: accepted}); if (accepted) { this._requestAccepted = this._requestPending; this._totalBytesReceived = 0; this._filesReceived = []; } this._requestPending = null; } ``` ### Connection Error Handling ```javascript theme={null} // From network.js lines 869-873 _onChunkReceived(chunk) { if (!this._digester) { console.error("Received chunk but no digester active"); return; } this._digester.unchunk(chunk); } ``` ### Transfer Completion ```javascript theme={null} // From network.js lines 902-913 _onFileTransferCompleted() { const fileBlob = this._filesReceived[0]; this._totalBytesReceived += fileBlob.size; this._completeTransfer('receive', true); this.sendJSON({type: 'file-transfer-complete'}); const sameSize = fileBlob.size === acceptedHeader.size; const sameName = fileBlob.name === acceptedHeader.name; Events.fire('file-received', { file: fileBlob, peerId: this._peerId, imagesOnly: request.imagesOnly, sameSize, sameName }); } ``` ## Performance Optimizations ### Memory Management * **Streaming**: Files are processed in chunks to prevent memory overload * **Buffer Cleanup**: Automatic cleanup of completed transfers * **iOS Limits**: Special handling for iOS memory constraints ### Network Efficiency * **Chunk Size**: 64KB chunks balance memory usage and network efficiency * **Partition Tracking**: 1MB partitions for progress reporting * **Binary Transfer**: Direct binary data transfer via DataChannels ### Progress Feedback * **Real-time Updates**: Continuous progress reporting during transfer * **Partition Tracking**: Granular progress for large files * **UI Integration**: Seamless integration with user interface ## WebSocket Fallback When WebRTC is unavailable, transfers fall back to WebSocket: ```javascript theme={null} // From network.js lines 1322-1327 _send(chunk) { this.sendJSON({ type: 'ws-chunk', chunk: arrayBufferToBase64(chunk) }); } ``` ### Base64 Encoding ```javascript theme={null} // From network.js lines 1454-1456 const messageJSON = JSON.parse(message); if (messageJSON.type === 'ws-chunk') message = base64ToArrayBuffer(messageJSON.chunk); ``` This file transfer system provides robust, efficient file sharing with comprehensive error handling and fallback mechanisms for maximum compatibility. # Signaling Server Source: https://docsdrop.erikraft.com/architecture/signaling-server WebSocket-based signaling server architecture for peer discovery and WebRTC connection establishment. # Signaling Server Architecture The ErikrafT Drop signaling server facilitates peer discovery and WebRTC connection establishment through WebSocket communication. Built with Node.js and the `ws` library, it manages room-based peer grouping and message routing. ## Server Overview ### Main Server Entry Point The server is initialized in `server.js`: ```javascript theme={null} // From server.js lines 33-39 new ErikrafTdropWsServer(server, { rtcConfig, wsFallback: false, debugMode: process.env.DEBUG_MODE === "true", rateLimit: false, allowLocalOnly: true }); ``` ### Configuration Endpoints The server provides configuration via HTTP endpoints: ```javascript theme={null} // From server.js lines 14-21 if (req.url === "/config") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ lanOnly: true, rtcConfig })); return; } ``` ## WebSocket Server Implementation ### ErikrafTdropWsServer Class The core WebSocket server is implemented in `server/ws-server.js`: ```javascript theme={null} export default class ErikrafTdropWsServer { constructor(server, conf) { this._conf = conf; this._rooms = {}; // { roomId: peers[] } this._roomSecrets = {}; // { pairKey: roomSecret } this._keepAliveTimers = {}; this._wss = new WebSocketServer({ server }); this._wss.on('connection', (socket, request) => this._onConnection(new Peer(socket, request, conf))); } } ``` ## Connection Management ### Peer Connection Process #### 1. Connection Validation ```javascript theme={null} // From ws-server.js lines 46-54 _onConnection(peer) { if (this._conf.allowLocalOnly && !isLocalIp(peer.ip)) { try { peer.socket.close(1008, 'LAN only'); } catch (e) { peer.socket.terminate(); } return; } peer.socket.on('message', message => this._onMessage(peer, message)); peer.socket.onerror = e => console.error(e); this._keepAlive(peer); } ``` #### 2. IP Validation The server validates local IP addresses for LAN-only mode: ```javascript theme={null} // From ws-server.js lines 7-30 function isLocalIp(ip) { if (!ip) return false; if (ip === '127.0.0.1' || ip === '::1') return true; if (!ip.includes(":")) { return LOCAL_IPV4_PATTERNS.some(pattern => pattern.test(ip)); } // IPv6 local address validation const firstWord = ip.split(":").find(el => !!el); if (/^fe[c-f][0-9a-f]$/.test(firstWord)) return true; if (/^fc[0-9a-f]{2}$/.test(firstWord)) return true; if (/^fd[0-9a-f]{2}$/.test(firstWord)) return true; if (firstWord === "fe80") return true; if (firstWord === "100") return true; return false; } ``` #### 3. Initial Configuration ```javascript theme={null} // From ws-server.js lines 61-77 this._send(peer, { type: 'ws-config', wsConfig: { rtcConfig: this._conf.rtcConfig, wsFallback: this._conf.wsFallback } }); // send displayName this._send(peer, { type: 'display-name', displayName: peer.name.displayName, deviceName: peer.name.deviceName, clientType: peer.name.clientType, peerId: peer.id, peerIdHash: hasher.hashCodeSalted(peer.id) }); ``` ## Room Management ### Room Types The server manages three types of rooms: #### 1. IP-Based Rooms (Local Network) ```javascript theme={null} // From ws-server.js lines 349-351 _joinIpRoom(peer) { this._joinRoom(peer, 'ip', peer.ip); } ``` #### 2. Secret Rooms (Paired Devices) ```javascript theme={null} // From ws-server.js lines 353-358 _joinSecretRoom(peer, roomSecret) { this._joinRoom(peer, 'secret', roomSecret); peer.addRoomSecret(roomSecret); } ``` #### 3. Public Rooms (Temporary Rooms) ```javascript theme={null} // From ws-server.js lines 360-367 _joinPublicRoom(peer, publicRoomId) { this._leavePublicRoom(peer); // prevent joining multiple public rooms this._joinRoom(peer, 'public-id', publicRoomId); peer.publicRoomId = publicRoomId; } ``` ### Room Operations #### Generic Room Join ```javascript theme={null} // From ws-server.js lines 369-385 _joinRoom(peer, roomType, roomId) { if (this._rooms[roomId] && this._rooms[roomId][peer.id]) { this._leaveRoom(peer, roomType, roomId); } if (!this._rooms[roomId]) { this._rooms[roomId] = {}; } this._notifyPeers(peer, roomType, roomId); this._rooms[roomId][peer.id] = peer; } ``` #### Peer Notification ```javascript theme={null} // From ws-server.js lines 435-468 _notifyPeers(peer, roomType, roomId) { if (!this._rooms[roomId]) return; // notify all other peers that peer joined for (const otherPeerId in this._rooms[roomId]) { if (otherPeerId === peer.id) continue; const otherPeer = this._rooms[roomId][otherPeerId]; let msg = { type: 'peer-joined', peer: peer.getInfo(), roomType: roomType, roomId: roomId }; this._send(otherPeer, msg); } // notify peer about peers already in the room const otherPeers = []; for (const otherPeerId in this._rooms[roomId]) { if (otherPeerId === peer.id) continue; otherPeers.push(this._rooms[roomId][otherPeerId].getInfo()); } let msg = { type: 'peers', peers: otherPeers, roomType: roomType, roomId: roomId }; this._send(peer, msg); } ``` ## Device Pairing System ### Pairing Initiation ```javascript theme={null} // From ws-server.js lines 222-237 _onPairDeviceInitiate(sender) { let roomSecret = randomizer.getRandomString(256); let pairKey = this._createPairKey(sender, roomSecret); if (sender.pairKey) { this._removePairKey(sender.pairKey); } sender.pairKey = pairKey; this._send(sender, { type: 'pair-device-initiated', roomSecret: roomSecret, pairKey: pairKey }); this._joinSecretRoom(sender, roomSecret); } ``` ### Pair Key Generation ```javascript theme={null} // From ws-server.js lines 327-340 _createPairKey(creator, roomSecret) { let pairKey; do { pairKey = crypto.randomInt(1000000, 1999999).toString().substring(1); } while (pairKey in this._roomSecrets) this._roomSecrets[pairKey] = { roomSecret: roomSecret, creator: creator } return pairKey; } ``` ### Pairing Join Process ```javascript theme={null} // From ws-server.js lines 239-265 _onPairDeviceJoin(sender, message) { if (sender.rateLimitReached()) { this._send(sender, { type: 'join-key-rate-limit' }); return; } if (!this._roomSecrets[message.pairKey] || sender.id === this._roomSecrets[message.pairKey].creator.id) { this._send(sender, { type: 'pair-device-join-key-invalid' }); return; } const roomSecret = this._roomSecrets[message.pairKey].roomSecret; const creator = this._roomSecrets[message.pairKey].creator; this._removePairKey(message.pairKey); this._send(sender, { type: 'pair-device-joined', roomSecret: roomSecret, peerId: creator.id }); this._send(creator, { type: 'pair-device-joined', roomSecret: roomSecret, peerId: sender.id }); this._joinSecretRoom(sender, roomSecret); this._removePairKey(sender.pairKey); } ``` ## Message Handling ### Message Router ```javascript theme={null} // From ws-server.js lines 80-150 _onMessage(sender, message) { try { message = JSON.parse(message); } catch (e) { console.warn("WS: Received JSON is malformed"); return; } switch (message.type) { case 'disconnect': this._onDisconnect(sender); break; case 'pong': this._setKeepAliveTimerToNow(sender); break; case 'join-ip-room': this._joinIpRoom(sender); break; case 'room-secrets': this._onRoomSecrets(sender, message); break; case 'pair-device-initiate': this._onPairDeviceInitiate(sender); break; case 'signal': this._signalAndRelay(sender, message); break; // ... other message types } } ``` ### Signal Relay ```javascript theme={null} // From ws-server.js lines 152-168 _signalAndRelay(sender, message) { const room = message.roomType === 'ip' ? sender.ip : message.roomId; // relay message to recipient if (message.to && Peer.isValidUuid(message.to) && this._rooms[room]) { const recipient = this._rooms[room][message.to]; delete message.to; // add sender message.sender = { id: sender.id, rtcSupported: sender.rtcSupported }; this._send(recipient, message); } } ``` ## Connection Monitoring ### Keep-Alive System ```javascript theme={null} // From ws-server.js lines 489-509 _keepAlive(peer) { this._cancelKeepAlive(peer); let timeout = 1000; if (!this._keepAliveTimers[peer.id]) { this._keepAliveTimers[peer.id] = { timer: 0, lastBeat: Date.now() }; } if (Date.now() - this._keepAliveTimers[peer.id].lastBeat > 5 * timeout) { this._disconnect(peer); return; } this._send(peer, { type: 'ping' }); this._keepAliveTimers[peer.id].timer = setTimeout(() => this._keepAlive(peer), timeout); } ``` ### Rate Limiting ```javascript theme={null} // From peer.js lines 34-42 rateLimitReached() { if (this.requestRate >= 10) { return true; } this.requestRate += 1; setTimeout(() => this.requestRate -= 1, 10000); return false; } ``` ## Security Features ### IP Filtering * **LAN-Only Mode**: Restricts connections to local IP addresses * **IP Validation**: Comprehensive IPv4 and IPv6 local address detection * **Connection Rejection**: Automatic termination of non-local connections ### Input Validation * **JSON Parsing**: Safe parsing with error handling * **UUID Validation**: Strict peer ID format validation * **Room Secret Validation**: Length and character validation ### Rate Limiting * **Request Throttling**: 10 requests per 10 seconds per peer * **Pairing Limits**: Prevents brute force pairing attempts * **Connection Limits**: Configurable maximum connections ## Performance Optimization ### Memory Management * **Room Cleanup**: Automatic removal of empty rooms * **Timer Management**: Proper cleanup of keep-alive timers * **Connection Cleanup**: Graceful connection termination ### Message Efficiency * **Binary Support**: WebSocket binary frame support for file transfers * **Message Batching**: Efficient message routing within rooms * **Compression**: Optional message compression for large payloads This signaling server provides a robust foundation for peer discovery and WebRTC connection establishment while maintaining security and performance. # System Overview Source: https://docsdrop.erikraft.com/architecture/system-overview High-level architecture of ErikrafT Drop's peer-to-peer file sharing system. # ErikrafT Drop Architecture Diagram This diagram shows the internal architecture and system flow of ErikrafT Drop, a WebRTC-based peer-to-peer file transfer system inspired by PairDrop. The architecture is divided into logical layers that work together to enable secure and fast P2P file transfers. ## Layer 1 — HTTP + Configuration The Express server provides static files and configuration data. ### Responsibilities: * Serve HTML, CSS, and JavaScript files * Provide `/config` endpoint * Deliver application settings * Initialize client configuration ### Components: * Express Server (`server/index.js`) * Static Files * Configuration API *** ## Layer 2 — WebSocket Signaling The WebSocket server handles peer discovery and signaling required for WebRTC connections. ### Responsibilities: * Peer discovery * Room management * Signaling message exchange * Session coordination ### Components: * WebSocket Signaling Server (`server/ws-server.js`) * Rooms Manager * Peer Manager **Signaling is only used during connection setup.** **No files pass through the signaling server.** *** ## Layer 3 — WebRTC P2P Transfer File transfers occur directly between browsers using WebRTC DataChannels. ### Responsibilities: * Direct peer-to-peer communication * Encrypted file transfer * Chunked file streaming * Transfer reliability ### Components: * RTCPeer connections * RTCDataChannel * FileChunker * FileDigester **All transfers are encrypted using DTLS.** **The server is not involved during file transfer.** *** ## NAT Traversal STUN and TURN servers enable connectivity across different networks. ### Components: * STUN Server (NAT discovery) * TURN Server (Relay fallback) **STUN is used to discover public network addresses.** **TURN is used only if direct P2P connection fails.** *** ## System Flow 1. Browser loads configuration from the Express server 2. Browser connects to WebSocket signaling server 3. Peers discover each other 4. WebRTC handshake is performed 5. Secure P2P connection is established 6. Files transfer directly between devices *** ## System Architecture (Technical View) ```mermaid theme={null} flowchart LR %% Users (Outside) UA["User A"] UB["User B"] %% External Services subgraph External_Services STUN["STUN Server
NAT discovery"] TURN["TURN Server
Relay fallback"] end %% Network Layers subgraph Network_Layers L1["Layer 1
HTTP + Config + Static"] L2["Layer 2
WebSocket Signaling"] L3["Layer 3
WebRTC P2P Transfer"] end %% Server Side subgraph Server_Side ES["Express Server
HTTP + Static files
server/index.js"] WSS["WebSocket Signaling Server
Peer discovery
server/ws-server.js"] RM["Rooms Manager
IP / Secret / Public"] PMGR["Peer Manager
Peer tracking"] end %% Client Side subgraph Client_Side UI["UI Interface
PeersUI / PeerUI"] PM["PeersManager"] RTC["RTCPeer
WebRTC P2P"] WS["WSPeer fallback
WebSocket relay"] FC["FileChunker
64KB chunks"] FD["FileDigester
File reassembly"] DB["IndexedDB
PersistentStorage"] end %% Users connect UA --> UI UB --> UI %% HTTP Flow UI -->|"HTTP"| L1 L1 --> ES %% Signaling Flow PM -->|"WebSocket"| L2 L2 --> WSS WSS --> RM WSS --> PMGR %% Peer Creation UI --> PM PM --> RTC PM --> WS %% Transfer Flow RTC -->|"Chunks"| FC FC --> FD WS -->|"Fallback"| FC %% Storage UI --> DB %% WebRTC RTC -->|"ICE"| L3 L3 --> STUN L3 --> TURN %% Peer Connection UA -.->|"WebSocket signaling"| UB UA <-->|"WebRTC P2P"| UB %% Discovery Phase PM -.->|"Discovery Phase"| WSS %% Signaling Phase RTC -.->|"SDP Exchange"| WSS %% Transfer Phase RTC -.->|"Transfer Phase"| FD ``` This diagram represents the full signaling and peer-to-peer transfer workflow used by ErikrafT Drop. # WebRTC Connection Source: https://docsdrop.erikraft.com/architecture/webrtc-connection Detailed explanation of WebRTC implementation and peer-to-peer connection management in ErikrafT Drop. # WebRTC Connection Implementation ErikrafT Drop leverages WebRTC (Web Real-Time Communication) to establish direct peer-to-peer connections for secure file transfers. The implementation handles connection establishment, signaling, and data channel management. ## WebRTC Architecture ### RTCPeer Connection Class The core WebRTC functionality is implemented in the `RTCPeer` class in `network.js`: ```javascript theme={null} class RTCPeer extends Peer { constructor(serverConnection, isCaller, peerId, roomType, roomId, rtcConfig) { super(serverConnection, isCaller, peerId, roomType, roomId); this.rtcSupported = true; this.rtcConfig = rtcConfig; if (!this._isCaller) return; // we will listen for a caller this._connect(); } } ``` ### Connection Establishment Process #### 1. Connection Initialization ```javascript theme={null} // From network.js lines 1115-1121 _openConnection() { this._conn = new RTCPeerConnection(this.rtcConfig); this._conn.onicecandidate = e => this._onIceCandidate(e); this._conn.onicecandidateerror = e => this._onError(e); this._conn.onconnectionstatechange = _ => this._onConnectionStateChange(); this._conn.oniceconnectionstatechange = e => this._onIceConnectionStateChange(e); } ``` #### 2. Data Channel Creation ```javascript theme={null} // From network.js lines 1123-1137 _openChannel() { if (!this._conn) return; const channel = this._conn.createDataChannel('data-channel', { ordered: true, reliable: true // Obsolete. See MDN documentation }); channel.onopen = e => this._onChannelOpened(e); channel.onerror = e => this._onError(e); this._conn .createOffer() .then(d => this._onDescription(d)) .catch(e => this._onError(e)); } ``` ## Signaling Process ### Offer/Answer Pattern The WebRTC connection follows the standard offer/answer pattern: #### 1. Offer Creation (Caller) ```javascript theme={null} // From network.js lines 1139-1145 _onDescription(description) { this._conn .setLocalDescription(description) .then(_ => this._sendSignal({ sdp: description })) .catch(e => this._onError(e)); } ``` #### 2. Signal Relay ```javascript theme={null} // From network.js lines 1279-1285 _sendSignal(signal) { signal.type = 'signal'; signal.to = this._peerId; signal.roomType = this._getRoomTypes()[0]; signal.roomId = this._roomIds[this._getRoomTypes()[0]]; this._server.send(signal); } ``` #### 3. Answer Creation (Receiver) ```javascript theme={null} // From network.js lines 1155-1165 if (message.sdp) { this._conn .setRemoteDescription(message.sdp) .then(_ => { if (message.sdp.type === 'offer') { return this._conn .createAnswer() .then(d => this._onDescription(d)); } }) .catch(e => this._onError(e)); } ``` ### ICE Candidate Exchange #### 1. ICE Candidate Generation ```javascript theme={null} // From network.js lines 1147-1150 _onIceCandidate(event) { if (!event.candidate) return; this._sendSignal({ ice: event.candidate }); } ``` #### 2. ICE Candidate Processing ```javascript theme={null} // From network.js lines 1167-1171 else if (message.ice) { this._conn .addIceCandidate(new RTCIceCandidate(message.ice)) .catch(e => this._onError(e)); } ``` ## Data Channel Management ### Channel Configuration The data channel is configured for reliable, ordered delivery: ```javascript theme={null} const channel = this._conn.createDataChannel('data-channel', { ordered: true, // Maintain message order reliable: true // Ensure delivery (deprecated but maintained for compatibility) }); ``` ### Channel Event Handling #### 1. Channel Opened ```javascript theme={null} // From network.js lines 1174-1184 _onChannelOpened(event) { console.log('RTC: channel opened with', this._peerId); const channel = event.channel || event.target; channel.binaryType = 'arraybuffer'; channel.onmessage = e => this._onMessage(e.data); channel.onclose = _ => this._onChannelClosed(); this._channel = channel; Events.fire('peer-connected', {peerId: this._peerId, connectionHash: this.getConnectionHash()}); } ``` #### 2. Message Handling ```javascript theme={null} // From network.js lines 1186-1191 _onMessage(message) { if (typeof message === 'string') { console.log('RTC:', JSON.parse(message)); } super._onMessage(message); } ``` ## Connection State Management ### Connection States WebRTC connections progress through several states: ```javascript theme={null} // From network.js lines 1245-1257 _onConnectionStateChange() { console.log('RTC: state changed:', this._conn.connectionState); switch (this._conn.connectionState) { case 'disconnected': Events.fire('peer-disconnected', this._peerId); this._onError('rtc connection disconnected'); break; case 'failed': Events.fire('peer-disconnected', this._peerId); this._onError('rtc connection failed'); break; } } ``` ### ICE Connection States ```javascript theme={null} // From network.js lines 1259-1267 _onIceConnectionStateChange() { switch (this._conn.iceConnectionState) { case 'failed': this._onError('ICE Gathering failed'); break; default: console.log('ICE Gathering', this._conn.iceConnectionState); } } ``` ## Connection Hash Generation For security and identification, each connection generates a unique hash: ```javascript theme={null} // From network.js lines 1193-1217 getConnectionHash() { const localDescriptionLines = this._conn.localDescription.sdp.split("\r\n"); const remoteDescriptionLines = this._conn.remoteDescription.sdp.split("\r\n"); let localConnectionFingerprint, remoteConnectionFingerprint; // Extract fingerprints from SDP for (let i=0; i ``` #### File Association The app can handle various file types through MIME type registration: * **Documents**: PDF, DOC, TXT, etc. * **Images**: JPG, PNG, GIF, WebP, etc. * **Videos**: MP4, AVI, MOV, etc. * **Audio**: MP3, WAV, OGG, etc. * **Archives**: ZIP, RAR, 7Z, etc. ### Performance Optimizations #### Memory Management * **Efficient WebView**: Optimized WebView configuration * **Background Processing**: Non-blocking file operations * **Memory Leaks Prevention**: Proper lifecycle management * **Large File Handling**: Streaming for large files #### Battery Optimization * **Background Limits**: Respects Android battery optimization * **Efficient Networking**: Optimized WebSocket connections * **Resource Cleanup**: Proper resource management * **Wake Locks**: Minimal wake lock usage ### Security Features #### Permissions ```xml theme={null} {/* Required permissions */} {/* For QR scanning */} ``` #### Security Measures * **HTTPS Only**: Secure connections only * **Certificate Pinning**: SSL certificate validation * **Input Validation**: Proper input sanitization * **Privacy Compliance**: Follows Android privacy guidelines ## Installation and Distribution ### Official Distribution Channels #### Google Play Store **Primary distribution channel with automatic updates:** * **URL**: [https://play.google.com/store/apps/details?id=com.erikraft.drop](https://play.google.com/store/apps/details?id=com.erikraft.drop) * **Features**: Automatic updates, beta testing, review system * **Requirements**: Google Play account, Android 5.0+ #### F-Droid **Open-source distribution channel:** * **URL**: [https://f-droid.org/en/packages/com.erikraft.drop/](https://f-droid.org/en/packages/com.erikraft.drop/) * **Features**: FOSS-only, no tracking, community-curated * **Requirements**: F-Droid client, Android 5.0+ #### APKPure **Alternative APK distribution:** * **URL**: [https://apkpure.com/p/com.erikraft.drop](https://apkpure.com/p/com.erikraft.drop/) * **Features**: Direct APK downloads, version history * **Requirements**: Enable "Unknown Sources" in settings #### Direct GitHub Releases **Developer distribution channel:** * **URL**: [https://github.com/erikraft/Drop-Android/releases/latest/download/Drop-Android.apk](https://github.com/erikraft/Drop-Android/releases/latest/download/Drop-Android.apk) * **Features**: Latest releases, development versions * **Requirements**: Manual installation and updates ### Build Instructions #### Prerequisites * **Android Studio**: Latest version recommended * **Java Development Kit**: JDK 11 or higher * **Android SDK**: API level 35 * **Gradle**: Version 8.13.2 or higher #### Build Process ```bash theme={null} # Clone the repository git clone https://github.com/erikraft/Drop-Android.git cd Drop-Android # Build debug APK ./gradlew assembleDebug # Build release APK ./gradlew assembleRelease # Install on connected device ./gradlew installDebug ``` #### Release Build ```bash theme={null} # Generate signed bundle for Play Store ./gradlew bundleRelease # Generate signed APK for direct distribution ./gradlew assembleRelease ``` ## Development Workflow ### Automated Build Pipeline The project uses GitHub Actions for continuous integration: #### CI/CD Features * **Automated Testing**: Unit and integration tests * **Code Quality**: Static analysis and linting * **Build Verification**: Multi-environment builds * **Release Automation**: Automatic Play Store publishing #### Play Store Automation ```yaml theme={null} # GitHub Actions workflow for Play Store publishing - Build release bundle - Sign with production keystore - Upload to Google Play Console - Deploy to production track ``` #### F-Droid Automation ```yaml theme={null} # GitHub Actions workflow for F-Droid publishing - Build signed APK - Update F-Droid metadata - Generate repository index - Publish to fdroid branch ``` ### Translation Management Translations are managed through Crowdin: #### Supported Languages * English (en) * German (de) * French (fr) * Spanish (es) * Italian (it) * Portuguese (pt) * Russian (ru) * Chinese Simplified (zh-CN) * Japanese (ja) #### Translation Process 1. **Source Strings**: English strings in `res/values/strings.xml` 2. **Crowdin Integration**: Automatic sync with Crowdin platform 3. **Community Translation**: Community-contributed translations 4. **Automated Import**: Translations automatically imported to repository ## Comparison with Web App ### Advantages of Android App #### Performance * **Native Performance**: Better than WebView performance * **Memory Efficiency**: Optimized for mobile hardware * **Background Operation**: Works efficiently in background * **Battery Optimization**: Better battery management #### Integration * **System Share Menu**: Deep Android integration * **File Association**: Handles all file types natively * **Notification System**: Native notification handling * **Multi-window**: Split-screen support #### User Experience * **Material Design**: Consistent Android design language * **Touch Optimization**: Touch-optimized interface * **Gesture Support**: Android gesture navigation * **Accessibility**: Enhanced accessibility features ### Limitations * **Update Dependency**: Requires manual updates (sideloading) * **Platform Specific**: Android-only functionality * **Size**: Larger app size due to native components * **Permissions**: Requires more system permissions ## Troubleshooting ### Common Issues #### Installation Problems * **Unknown Sources**: Enable installation from unknown sources * **Storage Space**: Ensure sufficient storage available * **Android Version**: Verify minimum Android version (5.0+) * **Architecture**: Check device architecture compatibility #### Connection Issues * **Network Permissions**: Verify network permissions granted * **Firewall**: Check firewall settings * **VPN**: Disable VPN if causing connection issues * **Server Status**: Verify ErikrafT Drop server status #### Performance Issues * **Memory**: Close other apps to free memory * **Storage**: Clear app cache if storage full * **Background**: Check battery optimization settings * **WebView**: Clear WebView data if corrupted ### Debug Information Enable debug logging for troubleshooting: ```bash theme={null} # Enable debug logging adb shell setprop log.tag.ErikrafTDrop DEBUG # View logs adb logcat -s ErikrafTDrop ``` ## Future Development ### Planned Features * **Background Service**: Improved background operation * **Notification Channels**: Enhanced notification management * **Dark Mode**: System dark mode support * **Biometric Authentication**: Fingerprint/face unlock * **Widget**: Home screen widget for quick access ### Technical Improvements * **Kotlin Migration**: Gradual migration to Kotlin * **Modular Architecture**: Feature modules for better maintainability * **Performance**: Continued performance optimizations * **Security**: Enhanced security features The ErikrafT Drop Android application provides a robust, native file sharing solution that leverages the full capabilities of the Android platform while maintaining compatibility with the broader ErikrafT Drop ecosystem. # Discord Bot Integration Source: https://docsdrop.erikraft.com/ecosystem/discord Complete guide to the ErikrafT Drop Discord bot for file sharing within Discord servers. # Discord Bot Integration The ErikrafT Drop Discord bot brings file sharing capabilities directly to Discord servers, enabling users to send and receive files through Discord commands while maintaining the security and efficiency of the ErikrafT Drop peer-to-peer system. ## Bot Overview ### Core Functionality The Discord bot provides a bridge between Discord and ErikrafT Drop: * **Slash Commands**: `/drop` command for file sharing operations * **Real-time Integration**: Appears as paired device in ErikrafT Drop web interface * **Multi-file Support**: Send up to 3 files per command * **Text Messaging**: Send text messages alongside files * **Bidirectional Transfer**: Send and receive files through Discord ### Technical Architecture ```mermaid theme={null} graph TD A[Discord Server] --> B[Discord Bot] B --> C[ErikrafT Drop WebSocket] C --> D[Signaling Server] D --> E[Web App Clients] B --> F[File Processing] F --> G[Memory Management] G --> H[Transfer Completion] ``` ## Installation and Setup ### Bot Invitation **Invite the bot to your Discord server:** [https://discord.com/oauth2/authorize?client\_id=1367869058707492955](https://discord.com/oauth2/authorize?client_id=1367869058707492955) ### Prerequisites * **Node.js 18+**: Required for bot operation * **Discord Server**: Server with bot administration permissions * **ErikrafT Drop Instance**: With WebSocket fallback enabled * **Bot Application**: Registered on Discord Developer Portal ### Self-Hosting Setup #### 1. Discord Application Setup 1. **Create Application**: Visit [Discord Developer Portal](https://discord.com/developers/applications) 2. **Create Bot**: Add bot to application 3. **Configure Permissions**: Set appropriate bot permissions 4. **Generate Token**: Create bot token for authentication #### 2. Bot Configuration ```bash theme={null} # Clone or download the bot code git clone https://github.com/erikraft/Drop.git cd Drop/Discord/Bot # Copy environment configuration cp .env.example .env # Install dependencies npm install ``` #### 3. Environment Variables Configure `.env` file with required variables: ```bash theme={null} # Required Configuration DISCORD_TOKEN=your_discord_bot_token DISCORD_APPLICATION_ID=your_application_id # Optional Configuration DISCORD_GUILD_ID=your_server_id_for_testing DROP_BASE_URL=https://drop.erikraft.com DROP_SIGNALING_URL=wss://drop.erikraft.com/server ``` #### 4. Command Registration ```bash theme={null} # Register Discord slash commands npm run register:commands # Start the bot npm start ``` ## Bot Architecture ### Project Structure ``` Discord/Bot/ ├── src/ │ ├── index.js # Main bot initialization │ ├── registerCommands.js # Command registration utility │ ├── commands/ │ │ └── drop.js # /drop command implementation │ └── client/ │ └── dropClient.js # ErikrafT Drop WebSocket client ├── .env.example # Environment variables template ├── package.json # Node.js dependencies └── README.md # Bot documentation ``` ### Core Components #### Main Bot Instance (`src/index.js`) ```javascript theme={null} // Bot initialization and event handling class ErikrafTDropBot { constructor() { this.client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ] }); this.dropClient = new DropClient(); this.setupEventHandlers(); } setupEventHandlers() { this.client.on('ready', this.onReady.bind(this)); this.client.on('interactionCreate', this.onInteraction.bind(this)); } } ``` #### ErikrafT Drop Client (`src/client/dropClient.js`) ```javascript theme={null} // WebSocket client for ErikrafT Drop integration class DropClient { constructor() { this.ws = null; this.isConnected = false; this.clientType = 'discord-bot'; this.setupWebSocket(); } setupWebSocket() { this.ws = new WebSocket(this.getSignalingUrl()); this.ws.onopen = this.onOpen.bind(this); this.ws.onmessage = this.onMessage.bind(this); this.ws.onclose = this.onClose.bind(this); } onOpen() { this.isConnected = true; this.identifyClient(); } identifyClient() { this.ws.send(JSON.stringify({ type: 'identify', client_type: this.clientType })); } } ``` #### Drop Command (`src/commands/drop.js`) ```javascript theme={null} // /drop slash command implementation class DropCommand { constructor(dropClient) { this.dropClient = dropClient; } async execute(interaction) { const { key, name, message, file1, file2, file3 } = interaction.options; // Validate pairing key if (!this.validateKey(key)) { return interaction.reply({ content: 'Invalid pairing key format', ephemeral: true }); } // Process files and message const files = await this.processFiles([file1, file2, file3]); const textMessage = message || null; // Initiate transfer await this.initiateTransfer(key, name, files, textMessage); // Send response await interaction.reply({ content: 'Transfer initiated successfully', ephemeral: true }); } } ``` ## Command Usage ### /drop Command The primary command for file sharing operations: #### Command Options ``` /drop [name] [message] [file1] [file2] [file3] Required: key 6-digit pairing key from ErikrafT Drop Optional: name Custom display name for the bot message Text message to send (up to 2000 characters) file1 First file to attach file2 Second file to attach file3 Third file to attach ``` #### Usage Examples **Basic File Sharing:** ``` /drop key:123456 file1:@document.pdf ``` **With Custom Name:** ``` /drop key:123456 name:"Development Server" file1:@code.zip ``` **Text Message Only:** ``` /drop key:123456 message:"Here are the updated files" ``` **Multiple Files:** ``` /drop key:123456 file1:@image.png file2:@data.csv file3:@report.pdf ``` ### Command Features #### File Handling * **Multiple Files**: Support for up to 3 files per command * **File Types**: All file types supported * **Size Limits**: Respects Discord file size limits * **Processing**: Files processed in memory without disk storage #### Message Handling * **Text Messages**: Send text messages up to 2000 characters * **Formatting**: Supports Discord markdown formatting * **Encoding**: Proper character encoding for international text * **Validation**: Input validation and sanitization #### Response Handling * **Ephemeral Messages**: Responses visible only to command user * **Progress Feedback**: Real-time transfer progress updates * **Error Handling**: Graceful error handling and user feedback * **Completion Notification**: Transfer completion confirmation ## Integration Features ### Real-time Device Discovery The bot appears as a paired device in the ErikrafT Drop web interface: #### Device Identification ```javascript theme={null} // Device identification in web interface const discordDevice = { id: 'discord-bot-' + botId, name: 'Discord Bot', deviceName: 'Discord Integration', browser: 'Discord', type: 'discord-bot', rtcSupported: false, // Uses WebSocket fallback clientType: 'discord-bot' }; ``` #### Connection Status * **Online Indicator**: Shows when bot is connected * **Real-time Updates**: Connection status updates in real-time * **Auto-reconnection**: Automatic reconnection on disconnect * **Error Reporting**: Connection error notifications ### WebSocket Fallback Integration The bot uses WebSocket fallback for file transfers: #### Transfer Process ```mermaid theme={null} sequenceDiagram participant User as Discord User participant Bot as Discord Bot participant Server as ErikrafT Drop Server participant Web as Web Client User->>Bot: /drop command with files Bot->>Server: WebSocket connection Bot->>Server: Join secret room Bot->>Server: Transfer request Server->>Web: Relay transfer request Web->>Server: Accept transfer Server->>Bot: Relay acceptance Bot->>Server: File chunks (base64) Server->>Web: Relay chunks Web->>Server: Completion confirmation Server->>Bot: Relay confirmation Bot->>User: Transfer complete notification ``` #### Data Handling * **Base64 Encoding**: Files encoded as base64 for WebSocket transfer * **Chunking**: Large files chunked for efficient transfer * **Memory Management**: Files processed in memory without disk storage * **Error Recovery**: Automatic retry on transfer failures ## Security Features ### Authentication and Authorization #### Discord Authentication * **Bot Token**: Secure Discord bot token authentication * **Guild Permissions**: Server-specific permission validation * **Command Permissions**: Role-based command access control * **User Validation**: Discord user identity verification #### ErikrafT Drop Integration * **Pairing Key Validation**: 6-digit key format validation * **Room Access**: Secure room access through pairing keys * **Connection Authentication**: WebSocket connection authentication * **Transfer Authorization**: Transfer request authorization ### Data Protection #### Privacy Measures * **No Disk Storage**: Files never written to disk * **Memory Processing**: All processing in memory only * **Ephemeral Messages**: Discord responses are ephemeral * **Secure Transmission**: Encrypted WebSocket transmission #### Security Best Practices * **Token Security**: Secure token storage and handling * **Input Validation**: Comprehensive input validation and sanitization * **Rate Limiting**: Command rate limiting to prevent abuse * **Error Handling**: Secure error handling without information leakage ## Performance Optimization ### Memory Management * **Efficient Processing**: Optimized file processing algorithms * **Memory Cleanup**: Automatic memory cleanup after transfers * **Stream Processing**: Stream-based file processing for large files * **Garbage Collection**: Proper garbage collection practices ### Network Optimization * **Connection Pooling**: Efficient WebSocket connection management * **Compression**: Data compression for improved transfer speed * **Timeout Management**: Appropriate timeout settings * **Retry Logic**: Intelligent retry mechanisms ### Bot Performance * **Asynchronous Operations**: Non-blocking file processing * **Concurrent Handling**: Handle multiple concurrent transfers * **Resource Management**: Efficient resource utilization * **Scalability**: Designed for multiple server support ## Deployment Options ### Self-Hosting Deploy the bot on your own infrastructure: #### Local Deployment ```bash theme={null} # Local development setup npm install npm run register:commands npm start ``` #### Production Deployment ```bash theme={null} # Production setup with PM2 npm install --production pm2 start ecosystem.config.js ``` #### Docker Deployment ```dockerfile theme={null} FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["npm", "start"] ``` ### Cloud Hosting Deploy to cloud platforms for 24/7 operation: #### Recommended Platforms * **Shard Cloud**: [https://shardcloud.app/pt-br/dash](https://shardcloud.app/pt-br/dash) * **Discloud**: [https://discloud.com/dashboard](https://discloud.com/dashboard) * **Heroku**: Platform-as-a-Service deployment * **DigitalOcean**: Cloud VPS deployment #### Configuration Examples ```yaml theme={null} # Docker Compose example version: '3.8' services: erikraft-drop-bot: build: . environment: - DISCORD_TOKEN=${DISCORD_TOKEN} - DISCORD_APPLICATION_ID=${DISCORD_APPLICATION_ID} - DROP_BASE_URL=https://drop.erikraft.com restart: unless-stopped ``` ## Troubleshooting ### Common Issues #### Connection Problems * **WebSocket Connection**: Verify ErikrafT Drop server accessibility * **Discord API**: Check Discord API status and bot permissions * **Network Issues**: Verify network connectivity and firewall settings * **Token Issues**: Validate Discord bot token and application ID #### Command Issues * **Command Registration**: Ensure slash commands are properly registered * **Permissions**: Verify bot has necessary permissions in server * **Key Validation**: Check pairing key format and validity * **File Processing**: Verify file size and type constraints #### Transfer Issues * **File Size**: Check Discord file size limitations * **Memory Issues**: Monitor bot memory usage * **Network Stability**: Verify network stability during transfers * **Server Status**: Check ErikrafT Drop server status ### Debug Information #### Bot Diagnostics ```javascript theme={null} // Debug logging for troubleshooting console.log('ErikrafT Drop Bot Debug:', { version: package.version, discordUser: interaction.user.tag, guildId: interaction.guildId, connectionStatus: this.dropClient.isConnected, lastError: this.lastError }); ``` #### WebSocket Diagnostics ```javascript theme={null} // WebSocket connection debugging this.ws.onopen = () => { console.log('WebSocket connected to:', this.signalingUrl); console.log('Bot client type:', this.clientType); }; this.ws.onerror = (error) => { console.error('WebSocket error:', error); console.error('Connection state:', this.ws.readyState); }; ``` ## Future Development ### Planned Enhancements #### Feature Improvements * **Additional Commands**: More Discord slash commands * **File Type Support**: Enhanced file type handling * **Progress Indicators**: Better progress indication * **Error Handling**: Improved error handling and user feedback #### Integration Enhancements * **Multi-server Support**: Support for multiple Discord servers * **Role-based Access**: Advanced role-based permissions * **Custom Commands**: Custom command configuration * **Webhook Integration**: Discord webhook integration #### Performance Improvements * **Caching**: Implement intelligent caching mechanisms * **Load Balancing**: Support for load balancing * **Monitoring**: Enhanced monitoring and alerting * **Scalability**: Improved scalability for large servers The Discord bot integration provides a powerful bridge between Discord communities and the ErikrafT Drop ecosystem, enabling seamless file sharing within Discord servers while maintaining the security and efficiency of the peer-to-peer file transfer system. # Browser and IDE Extensions Source: https://docsdrop.erikraft.com/ecosystem/extensions Comprehensive guide to ErikrafT Drop browser extensions and IDE integrations for enhanced productivity. # Browser and IDE Extensions The ErikrafT Drop extension ecosystem provides seamless integration with popular browsers and development environments, enabling users to share files directly from their preferred tools without interrupting their workflow. ## Extension Overview ### Extension Categories * **Browser Extensions**: Chrome, Firefox, Opera, and Thunderbird extensions * **IDE Extensions**: VS Code and Open VSX Registry extensions * **Integration Types**: Context menu, toolbar, and command palette integration * **Functionality**: File sharing, code sharing, and workflow integration ### Supported Platforms #### Browser Extensions | Browser | Extension Store | Extension ID | Features | | ----------- | ------------------- | ------------- | ------------------------ | | Chrome | Chrome Web Store | Unavailable\* | Context menu, toolbar | | Firefox | Firefox Add-ons | Available | Context menu, toolbar | | Opera | Opera Add-ons | SHORTLY | Context menu, toolbar | | Thunderbird | Thunderbird Add-ons | Available | Email attachment sharing | \*The extension is not available on the Chrome Web Store because I haven't yet purchased the Extension Developer account, which costs \$5.00. If you'd like to donate, please do so at [https://ko-fi.com/erikraft](https://ko-fi.com/erikraft) #### IDE Extensions | Platform | Marketplace | Extension ID | Features | | -------- | ------------------- | ------------------------ | ------------------------- | | VS Code | VS Code Marketplace | `ErikrafT.erikraft-drop` | Command palette, explorer | | Open VSX | Open VSX Registry | `ErikrafT/erikraft-drop` | Command palette, explorer | ## Browser Extensions ### Architecture Overview Browser extensions use the WebExtensions API for cross-browser compatibility: ```mermaid theme={null} graph TD A[Extension Backend] --> B[Content Script] A --> C[Background Script] B --> D[Web Page Integration] C --> E[ErikrafT Drop WebSocket] D --> F[Context Menu] D --> G[Toolbar Button] E --> H[File Transfer] ``` ### Core Features #### Context Menu Integration * **Right-Click Menu**: Adds ErikrafT Drop options to context menu * **File Selection**: Works with selected files and text * **URL Sharing**: Share web page URLs directly * **Image Sharing**: Share images from web pages #### Toolbar Integration * **Quick Access**: One-click access to ErikrafT Drop * **Status Indicator**: Shows connection status * **Quick Actions**: Rapid file sharing actions * **Settings Access**: Extension configuration options #### WebSocket Connection * **Persistent Connection**: Maintains WebSocket connection * **Auto-Reconnection**: Automatic reconnection on disconnect * **Background Operation**: Works in background tabs * **Error Handling**: Graceful error handling and recovery ### Browser-Specific Implementation #### Chrome Extension ```javascript theme={null} // Chrome extension manifest structure { "manifest_version": 3, "name": "ErikrafT Drop", "version": "1.0.0", "permissions": [ "contextMenus", "activeTab", "storage" ], "background": { "service_worker": "background.js" }, "content_scripts": [{ "matches": [""], "js": ["content.js"] }] } ``` #### Firefox Extension ```javascript theme={null} // Firefox extension manifest structure { "manifest_version": 2, "name": "ErikrafT Drop", "version": "1.0.0", "permissions": [ "contextMenus", "activeTab", "storage" ], "background": { "scripts": ["background.js"] }, "content_scripts": [{ "matches": [""], "js": ["content.js"] }] } ``` ### Extension Features #### File Sharing Capabilities * **Multiple Files**: Select and share multiple files * **Directory Support**: Share entire directories * **Large Files**: Handle large file transfers * **Progress Tracking**: Monitor transfer progress #### Content Type Support * **Documents**: PDF, DOC, TXT, and other document formats * **Images**: JPG, PNG, GIF, WebP, and other image formats * **Code Files**: Source code files with syntax highlighting * **Archives**: ZIP, RAR, and other archive formats #### Integration Points * **File Explorer**: Integration with browser file explorer * **Download Manager**: Share downloaded files * **Web Pages**: Share web page content and URLs * **Developer Tools**: Integration with browser developer tools ## IDE Extensions ### VS Code Extension #### Architecture The VS Code extension integrates with the VS Code extension API: ```typescript theme={null} // VS Code extension activation export function activate(context: vscode.ExtensionContext) { // Register commands const shareFileCommand = vscode.commands.registerCommand( 'erikraft-drop.shareFile', shareFileHandler ); // Register context menu vscode.commands.executeCommand( 'setContext', 'erikraft-drop.enabled', true ); context.subscriptions.push(shareFileCommand); } ``` #### Features * **Command Palette Integration**: Access via Ctrl+Shift+P * **Explorer Context Menu**: Right-click files in explorer * **Editor Integration**: Share active editor content * **Workspace Integration**: Share entire workspace files #### Commands ```typescript theme={null} // Available VS Code commands - 'erikraft-drop.shareFile': Share selected file - 'erikraft-drop.shareFolder': Share selected folder - 'erikraft-drop.shareWorkspace': Share entire workspace - 'erikraft-drop.connect': Connect to ErikrafT Drop - 'erikraft-drop.disconnect': Disconnect from ErikrafT Drop ``` ### Open VSX Extension #### Compatibility The Open VSX extension provides the same functionality as the VS Code extension: * **Cross-Platform**: Works with VS Code forks * **Open Source**: Fully open-source implementation * **Feature Parity**: Same features as VS Code version * **Community Support**: Community-driven development #### Installation ```bash theme={null} # Install via Open VSX CLI ovsx install ErikrafT.erikraft-drop # Or install from VS Code code --install-extension ErikrafT.erikraft-drop ``` ## Installation and Setup ### Browser Extension Installation #### Chrome Web Store 1. **Visit Store**: [Chrome Web Store](https://chrome.google.com/webstore) 2. **Search**: Search for "ErikrafT Drop" 3. **Install**: Click "Add to Chrome" 4. **Permissions**: Review and grant permissions 5. **Setup**: Configure extension settings #### Firefox Add-ons 1. **Visit Add-ons**: [Firefox Add-ons](https://addons.mozilla.org/firefox/) 2. **Search**: Search for "ErikrafT Drop" 3. **Install**: Click "Add to Firefox" 4. **Permissions**: Review and grant permissions 5. **Setup**: Configure extension settings #### Opera Add-ons 1. **Visit Add-ons**: [Opera Add-ons](https://addons.opera.com/) 2. **Search**: Search for "ErikrafT Drop" 3. **Install**: Click "Add to Opera" 4. **Permissions**: Review and grant permissions 5. **Setup**: Configure extension settings #### Thunderbird Add-ons 1. **Visit Add-ons**: [Thunderbird Add-ons](https://addons.thunderbird.net/) 2. **Search**: Search for "ErikrafT Drop" 3. **Install**: Click "Add to Thunderbird" 4. **Permissions**: Review and grant permissions 5. **Setup**: Configure extension settings ### IDE Extension Installation #### VS Code Marketplace 1. **Open VS Code**: Launch VS Code 2. **Extensions View**: Press Ctrl+Shift+X 3. **Search**: Search for "ErikrafT Drop" 4. **Install**: Click "Install" 5. **Setup**: Configure extension settings #### Open VSX Registry 1. **Open VSX**: Visit [Open VSX](https://open-vsx.org/) 2. **Search**: Search for "ErikrafT Drop" 3. **Install**: Follow installation instructions 4. **Setup**: Configure extension settings ## Usage Patterns ### Browser Extension Usage #### File Sharing Workflow 1. **Select Files**: Select files in browser or file system 2. **Context Menu**: Right-click and select "Share with ErikrafT Drop" 3. **Choose Recipient**: Select target device from list 4. **Transfer**: Files transfer automatically 5. **Confirmation**: Receive transfer confirmation #### Web Content Sharing 1. **Web Page**: Open web page with content to share 2. **Select Content**: Select text, images, or links 3. **Share Action**: Use context menu or toolbar button 4. **Transfer**: Content transfers to selected device 5. **Completion**: Receive confirmation of successful transfer ### IDE Extension Usage #### Code Sharing Workflow 1. **Select File**: Select file in VS Code explorer 2. **Context Menu**: Right-click and select "Share with ErikrafT Drop" 3. **Choose Target**: Select destination device 4. **Transfer**: Code files transfer automatically 5. **Confirmation**: Receive transfer confirmation #### Project Sharing 1. **Select Folder**: Select project folder in explorer 2. **Command Palette**: Use Ctrl+Shift+P and search for ErikrafT Drop commands 3. **Share Project**: Choose "Share Workspace" option 4. **Transfer**: Entire project transfers to target device 5. **Progress**: Monitor transfer progress in status bar ## Technical Implementation ### Extension Architecture #### Background Script ```javascript theme={null} // Background script for WebSocket management class ErikrafTDropClient { constructor() { this.ws = null; this.isConnected = false; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; } connect() { this.ws = new WebSocket('wss://drop.erikraft.com/server'); this.ws.onopen = this.onOpen.bind(this); this.ws.onmessage = this.onMessage.bind(this); this.ws.onclose = this.onClose.bind(this); this.ws.onerror = this.onError.bind(this); } onOpen() { this.isConnected = true; this.reconnectAttempts = 0; this.updateStatus('connected'); } onMessage(event) { const message = JSON.parse(event.data); this.handleMessage(message); } onClose() { this.isConnected = false; this.updateStatus('disconnected'); this.attemptReconnect(); } onError(error) { console.error('WebSocket error:', error); this.updateStatus('error'); } } ``` #### Content Script ```javascript theme={null} // Content script for web page integration class WebPageIntegration { constructor() { this.setupContextMenu(); this.setupToolbarButton(); this.setupFileHandlers(); } setupContextMenu() { chrome.contextMenus.create({ id: 'share-with-erikraft-drop', title: 'Share with ErikrafT Drop', contexts: ['selection', 'image', 'link', 'page'] }); } setupToolbarButton() { chrome.action.onClicked.addListener((tab) => { this.openErikraftTDrop(tab); }); } setupFileHandlers() { document.addEventListener('contextmenu', (event) => { this.handleContextMenu(event); }); } } ``` ### IDE Extension Architecture #### VS Code Extension API Integration ```typescript theme={null} // VS Code extension API usage export class ErikrafTDropExtension { private client: ErikrafTDropClient; private statusBarItem: vscode.StatusBarItem; constructor() { this.client = new ErikrafTDropClient(); this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Right, 100 ); this.setupCommands(); this.setupContextMenus(); } private setupCommands() { const commands = [ vscode.commands.registerCommand( 'erikraft-drop.shareFile', this.shareFile.bind(this) ), vscode.commands.registerCommand( 'erikraft-drop.shareFolder', this.shareFolder.bind(this) ), vscode.commands.registerCommand( 'erikraft-drop.connect', this.connect.bind(this) ) ]; commands.forEach(command => { vscode.extensions.all.forEach(extension => { extension.subscriptions.push(command); }); }); } private setupContextMenus() { vscode.commands.executeCommand( 'setContext', 'erikraft-drop.contextMenu', true ); } } ``` ## Configuration and Settings ### Extension Settings #### Browser Extension Configuration ```javascript theme={null} // Extension settings structure const defaultSettings = { serverUrl: 'https://drop.erikraft.com', autoConnect: true, showNotifications: true, enableContextMenu: true, enableToolbarButton: true, connectionTimeout: 10000, retryAttempts: 3 }; ``` #### IDE Extension Configuration ```typescript theme={null} // VS Code extension settings interface ErikrafTDropSettings { serverUrl: string; autoConnect: boolean; showProgress: boolean; enableStatusBar: boolean; enableNotifications: boolean; maxFileSize: number; supportedFileTypes: string[]; } ``` ### Customization Options #### Server Configuration * **Custom Server**: Use self-hosted ErikrafT Drop instance * **Connection Settings**: Configure timeout and retry settings * **Authentication**: Set up authentication if required * **SSL/TLS**: Configure secure connection settings #### User Interface * **Theme**: Match editor or browser theme * **Notifications**: Configure notification preferences * **Status Indicators**: Show/hide connection status * **Progress Display**: Configure progress indication ## Troubleshooting ### Common Issues #### Extension Installation Problems * **Store Access**: Verify access to extension store * **Permissions**: Check extension permissions * **Browser Version**: Ensure browser compatibility * **System Requirements**: Verify system requirements #### Connection Issues * **Network Connectivity**: Check internet connection * **Server Status**: Verify ErikrafT Drop server status * **Firewall Settings**: Check firewall configuration * **Proxy Settings**: Verify proxy configuration #### File Transfer Problems * **File Size**: Check file size limitations * **File Type**: Verify supported file types * **Permissions**: Check file access permissions * **Storage Space**: Ensure sufficient storage space ### Debug Information #### Browser Extension Debugging ```javascript theme={null} // Debug logging console.log('ErikrafT Drop Extension Debug Info:', { version: chrome.runtime.getManifest().version, userAgent: navigator.userAgent, connectionStatus: this.isConnected, lastError: this.lastError }); ``` #### IDE Extension Debugging ```typescript theme={null} // VS Code extension debugging vscode.window.showInformationMessage( `ErikrafT Drop Debug: Version ${extensionManifest.version}, ` + `Connection: ${this.isConnected ? 'Connected' : 'Disconnected'}` ); ``` ## Future Development ### Planned Enhancements #### Browser Extensions * **Enhanced UI**: Improved user interface design * **Additional Browsers**: Support for additional browsers * **Advanced Features**: Enhanced file handling capabilities * **Performance**: Improved performance and responsiveness #### IDE Extensions * **Additional IDEs**: Support for additional IDEs * **Advanced Integration**: Enhanced IDE integration * **Collaboration Features**: Real-time collaboration capabilities * **Workflow Automation**: Automated workflow integration ### Technical Improvements * **WebSocket Optimization**: Enhanced WebSocket performance * **Security**: Improved security features * **Reliability**: Enhanced reliability and error handling * **Performance**: Optimized performance across platforms The browser and IDE extension ecosystem provides comprehensive integration options for users to access ErikrafT Drop functionality within their preferred tools and workflows, enhancing productivity and maintaining seamless file sharing capabilities. # Ecosystem Overview Source: https://docsdrop.erikraft.com/ecosystem/overview Complete overview of the ErikrafT Drop ecosystem including web app, mobile apps, extensions, and integrations. # ErikrafT Drop Ecosystem Overview The ErikrafT Drop ecosystem extends far beyond the core web application, encompassing native mobile apps, browser extensions, development tools, and platform integrations. This comprehensive ecosystem ensures that ErikrafT Drop can integrate seamlessly into any workflow or platform. ## Ecosystem Components ### Core Platform * **Web Application**: The primary browser-based file sharing system * **Signaling Server**: WebSocket server for peer discovery and signaling * **PWA Support**: Progressive Web App capabilities for native-like experience ### Mobile Applications * **Android App**: Native Android application with system integration * **iOS Shortcut**: Apple Shortcuts integration for iOS devices ### Desktop Integrations * **Browser Extensions**: Chrome, Firefox, Opera, and Thunderbird extensions * **IDE Extensions**: VS Code and Open VSX Registry extensions * **System Integration**: Native file system and share menu integration ### Communication Platforms * **Discord Bot**: File sharing directly within Discord servers * **API Integration**: RESTful API for custom integrations ## Architecture Overview ```mermaid theme={null} graph TB subgraph "Core Infrastructure" WS[WebSocket Server] Web[Web App] PWA[PWA Client] end subgraph "Mobile Ecosystem" Android[Android App] iOS[iOS Shortcut] end subgraph "Desktop Ecosystem" Browser[Browser Extensions] IDE[IDE Extensions] Thunderbird[Thunderbird Add-on] end subgraph "Communication Ecosystem" Discord[Discord Bot] API[REST API] end Web --> WS PWA --> WS Android --> WS iOS --> WS Browser --> WS IDE --> WS Thunderbird --> WS Discord --> WS API --> WS ``` ## Platform Capabilities ### Web Application * **Full Feature Set**: Complete ErikrafT Drop functionality * **Cross-Platform**: Works on any modern browser * **Real-time Updates**: Always using latest version * **PWA Installation**: Native app experience possible ### Android Application * **Native Integration**: Deep Android OS integration * **Share Menu**: Appears in Android share dialog * **Background Operation**: Works while using other apps * **Performance**: Optimized for mobile hardware ### iOS Shortcut * **Share Sheet Integration**: Native iOS sharing * **Universal Content**: Supports all shareable content types * **Quick Access**: One-tap file sharing * **System Integration**: Works with any iOS app ### Browser Extensions * **Context Menu**: Right-click file sharing * **Toolbar Integration**: Quick access from browser toolbar * **Tab Management**: Persistent connections across browser sessions * **Developer Tools**: Integration with development workflows ### IDE Extensions * **Code Sharing**: Share code files directly from IDE * **Project Integration**: Works with project files and directories * **Development Workflow**: Streamlined development file sharing * **Multi-platform**: VS Code and Open VSX support ### Discord Bot * **Slash Commands**: `/drop` command for file sharing * **Real-time Sync**: Appears as device in web interface * **Multi-file Support**: Send multiple files in one command * **Server Integration**: Works within Discord servers ## Integration Patterns ### Direct WebSocket Connection Most ecosystem components connect directly to the ErikrafT Drop WebSocket server: ```javascript theme={null} // Example connection pattern const ws = new WebSocket('wss://drop.erikraft.com/server'); ws.onopen = () => { ws.send(JSON.stringify({ type: 'join-ip-room', client_type: 'android' // or 'discord-bot', 'vs-code-extension', etc. })); }; ``` ### Client Type Identification Each ecosystem component uses a unique client type: | Component | Client Type | Purpose | | ----------------- | ------------------- | -------------------------- | | Web App | `browser` | Standard browser client | | Android App | `android` | Native Android application | | VS Code Extension | `vs-code-extension` | VS Code integration | | Discord Bot | `discord-bot` | Discord server integration | | Browser Extension | `browser` | Browser integration | ### Feature Mapping Different components support different feature sets: | Feature | Web App | Android | iOS | Extensions | Discord | | ------------------- | ------- | ------- | --- | ---------- | --------------- | | WebRTC P2P | ✅ | ✅ | ✅ | ✅ | ❌\* | | WebSocket Fallback | ✅ | ✅ | ✅ | ✅ | ✅ | | QR Code Scanning | ✅ | ✅ | ✅ | ✅ | ❌ | | System Integration | ❌ | ✅ | ✅ | ✅ | ❌ | | Auto-Accept | ✅ | ✅ | ✅ | ✅ | ✅ | | Multi-file Transfer | ✅ | ✅ | ✅ | ✅ | ✅ (3 files max) | \*Discord Bot uses WebSocket fallback exclusively ## Data Flow Architecture ### Standard WebRTC Flow ```mermaid theme={null} sequenceDiagram participant Client as Ecosystem Client participant Server as Signaling Server participant Peer as Remote Peer Client->>Server: Connect WebSocket Server-->>Client: Connected Client->>Server: Request peer list Server-->>Client: Send peer list Client->>Server: Send WebRTC offer Server->>Peer: Forward offer Peer->>Server: Send WebRTC answer Server->>Client: Forward answer Client->>Server: Send ICE candidates Server->>Peer: Forward ICE candidates Peer->>Server: Send ICE candidates Server->>Client: Forward ICE candidates Client->>Peer: P2P DataChannel established ``` ### WebSocket Fallback Flow ```mermaid theme={null} sequenceDiagram participant Client as Ecosystem Client participant Server as Signaling Server participant Peer as Remote Peer Client->>Server: WebSocket connection Server->>Client: Peer list Client->>Server: File transfer request Server->>Peer: Relay request Peer->>Server: Accept response Server->>Client: Relay acceptance Client->>Server: File chunks (base64) Server->>Peer: Relay chunks Peer->>Server: Completion confirmation Server->>Client: Relay confirmation ``` ## Security Considerations ### Authentication Methods * **Anonymous**: No registration required for web app * **Token-based**: Discord bot uses Discord tokens * **Device Pairing**: Persistent room secrets for trusted devices * **Session-based**: Temporary connections for one-time sharing ### Data Privacy * **No Server Storage**: Files never stored on servers * **End-to-End Encryption**: WebRTC provides encryption * **Local Processing**: All processing on client devices * **Temporary Data**: Only session data stored temporarily ### Platform-Specific Security * **Android**: Follows Android security guidelines * **iOS**: Uses iOS Shortcuts security model * **Browser Extensions**: Follows browser extension security policies * **Discord Bot**: Uses Discord's security framework ## Development Ecosystem ### Open Source Development All ecosystem components are open source: * **GitHub Repositories**: Separate repos for major components * **Community Contributions**: Welcomes community contributions * **Translation Support**: Crowdin integration for translations * **Issue Tracking**: GitHub Issues for bug reports and features ### Build and Deployment * **Automated Builds**: GitHub Actions for CI/CD * **Multi-Platform**: Different build pipelines for each platform * **Release Management**: Coordinated releases across ecosystem * **Quality Assurance**: Automated testing and code review ### API Consistency * **WebSocket Protocol**: Consistent across all clients * **Message Formats**: Standardized JSON message structure * **Error Handling**: Consistent error reporting across platforms * **Version Compatibility**: Backward compatibility maintained ## User Experience Design ### Consistent Interface * **Visual Design**: Consistent branding and design language * **Interaction Patterns**: Similar user interactions across platforms * **Feature Parity**: Core features available on all platforms * **Accessibility**: Accessibility features across ecosystem ### Platform-Specific Optimization * **Mobile**: Touch-optimized interfaces * **Desktop**: Keyboard shortcuts and mouse interactions * **Browser**: Context menus and toolbar integration * **Discord**: Slash command interface ### Onboarding Experience * **Quick Start**: Minimal setup required * **Progressive Disclosure**: Features revealed as needed * **Help Integration**: Context-sensitive help and documentation * **Error Recovery**: Graceful handling of errors ## Performance Optimization ### Network Optimization * **Connection Reuse**: Persistent connections where possible * **Chunked Transfer**: Optimized file chunking for different platforms * **Compression**: Data compression for WebSocket fallback * **Caching**: Local caching for improved performance ### Resource Management * **Memory Efficiency**: Optimized memory usage for mobile devices * **Battery Optimization**: Minimized battery impact on mobile * **Background Processing**: Efficient background operations * **Resource Cleanup**: Proper cleanup of connections and resources ## Future Ecosystem Development ### Planned Expansions * **Desktop Apps**: Native desktop applications * **API Platform**: Public API for third-party integrations * **Enterprise Features**: Advanced features for organizations * **Cloud Integration**: Integration with cloud storage services ### Technology Evolution * **WebRTC Improvements**: Leveraging new WebRTC capabilities * **PWA Enhancements**: Enhanced PWA features * **Mobile Optimization**: Continued mobile platform optimization * **Security Enhancements**: Ongoing security improvements The ErikrafT Drop ecosystem provides comprehensive file sharing capabilities across virtually all platforms and use cases, ensuring users can share files securely and efficiently regardless of their preferred tools or workflows. # iOS Shortcut Integration Source: https://docsdrop.erikraft.com/ecosystem/shortcut Complete guide to the ErikrafT Drop iOS Shortcut for seamless file sharing from iOS devices. # iOS Shortcut Integration The ErikrafT Drop iOS Shortcut provides seamless integration with Apple's Shortcuts app, enabling users to share files directly from the iOS share menu. This integration brings ErikrafT Drop functionality to iOS devices while maintaining the native iOS user experience. ## Overview ### What is the iOS Shortcut? The ErikrafT Drop iOS Shortcut is a custom Apple Shortcuts workflow that: * **Integrates with iOS Share Sheet**: Appears in the share menu across all iOS apps * **Supports Universal Content**: Handles images, files, folders, URLs, and text * **Provides Quick Access**: One-tap file sharing to ErikrafT Drop devices * **Maintains Native Experience**: Uses iOS-native interface and interactions ### Technical Approach The shortcut uses iOS Shortcuts app capabilities to: * **Receive Share Intent**: Capture content from iOS share menu * **Process Content**: Handle different content types appropriately * **Launch Web App**: Open ErikrafT Drop web application * **Initiate Transfer**: Automatically start file transfer process ## Installation and Setup ### Download Sources #### Primary Sources * **RoutineHub**: [https://routinehub.co/shortcut/24753/](https://routinehub.co/shortcut/24753/) * **iCloud Shortcuts**: [https://www.icloud.com/shortcuts/f81dbac00823445e8feefd0f834b40e7](https://www.icloud.com/shortcuts/f81dbac00823445e8feefd0f834b40e7) * **GitHub Direct**: [https://github.com/erikraft/Drop/raw/refs/heads/master/Shortcut/ErikrafT%20Drop.shortcut](https://github.com/erikraft/Drop/raw/refs/heads/master/Shortcut/ErikrafT%20Drop.shortcut) ### Installation Process #### Step 1: Download the Shortcut 1. Open one of the download links on your iOS device 2. The Shortcuts app will automatically open 3. Review the shortcut actions and permissions #### Step 2: Add to Shortcuts Library 1. Tap "Add Shortcut" to add it to your library 2. If prompted, enable "Allow Untrusted Shortcuts" in Settings 3. Go to **Settings > Shortcuts > Allow Untrusted Shortcuts** and toggle on #### Step 3: Test the Shortcut 1. Open any app with shareable content (Photos, Files, Safari) 2. Select content to share 3. Tap the Share button 4. Find "ErikrafT Drop" in the share sheet 5. Tap to test the integration ## Shortcut Architecture ### Internal Structure The iOS Shortcut consists of several key components: ```mermaid theme={null} graph TD A[Share Intent Received] --> B{Content Type Detection} B -->|Images| C[Process Image Files] B -->|Documents| D[Process Document Files] B -->|URLs| E[Process Web Links] B -->|Text| F[Process Text Content] C --> G[Format for Transfer] D --> G E --> G F --> G G --> H[Open ErikrafT Drop] H --> I[Initiate Transfer] ``` ### Content Type Handling #### Image Processing * **Supported Formats**: HEIC, JPEG, PNG, GIF, WebP, TIFF * **Metadata Preservation**: Maintains image metadata when possible * **Size Optimization**: Handles large images efficiently * **Multiple Selection**: Supports multiple image selection #### Document Processing * **File Types**: PDF, DOC, DOCX, TXT, RTF, and more * **File Size**: Handles large documents through streaming * **Metadata**: Preserves document metadata * **Compression**: Optimizes file transfer when needed #### URL Processing * **Web Links**: Captures and processes web URLs * **URL Validation**: Validates URL format and accessibility * **Title Extraction**: Attempts to extract page titles * **Metadata**: Preserves URL metadata when available #### Text Processing * **Plain Text**: Handles plain text content * **Rich Text**: Processes rich text formatting * **Character Encoding**: Handles various character encodings * **Length Limits**: Respects iOS text length limitations ## Technical Implementation ### Shortcut Actions The shortcut uses various iOS Shortcuts actions: #### Core Actions ```shortcuts theme={null} 1. Get Input from Share Sheet 2. Get Type of Input 3. Conditional Logic for Content Type 4. Format Content for Transfer 5. Open URL (ErikrafT Drop) 6. Wait for Web App Load 7. Trigger File Transfer ``` #### Error Handling * **Content Validation**: Validates input content before processing * **Network Check**: Verifies network connectivity * **Fallback Actions**: Provides alternative actions for errors * **User Feedback**: Shows appropriate error messages ### Integration Points #### iOS Share Sheet Integration The shortcut registers with iOS share sheet through: * **Content Type Registration**: Registers for multiple MIME types * **Share Menu Positioning**: Appears in appropriate share menu sections * **Icon Display**: Uses ErikrafT Drop branding in share menu * **Title Display**: Shows "ErikrafT Drop" as action name #### Web App Communication Communicates with ErikrafT Drop web app through: * **URL Scheme Integration**: Uses custom URL schemes if available * **Web App Launch**: Opens web app with pre-populated transfer data * **State Management**: Maintains transfer state across app switches * **Completion Handling**: Handles transfer completion and errors ## Usage Patterns ### Common Use Cases #### Photo Sharing 1. **Open Photos App**: Select photos to share 2. **Share Menu**: Tap share button 3. **Select ErikrafT Drop**: Choose from share sheet 4. **Auto-Transfer**: Photos automatically transfer to paired devices #### Document Sharing 1. **Files App**: Select documents or folders 2. **Share Action**: Tap share button 3. **Choose ErikrafT Drop**: Select from share menu 4. **Transfer Initiation**: Documents transfer to target device #### Web Content Sharing 1. **Safari Browser**: Find content to share 2. **Share Button**: Tap share icon 3. **Select ErikrafT Drop**: Choose from share options 4. **Link Transfer**: URL transfers to paired device #### Text Sharing 1. **Notes App**: Select text content 2. **Share Function**: Use share feature 3. **ErikrafT Drop**: Select from share menu 4. **Text Transfer**: Text content transfers to target device ### Advanced Usage #### Batch Operations * **Multiple Files**: Select multiple files for batch transfer * **Mixed Content**: Share different content types simultaneously * **Sequential Transfer**: Process multiple items in sequence * **Progress Tracking**: Monitor transfer progress for multiple items #### Workflow Integration * **Automation**: Combine with other shortcuts for automated workflows * **Conditional Logic**: Add conditional logic based on content type * **Multi-Device**: Share to multiple devices in sequence * **Scheduling**: Schedule transfers for optimal timing ## Limitations and Constraints ### iOS Platform Limitations #### Background Processing * **Background Limits**: Limited background execution * **App Switching**: Requires app switching for completion * **State Management**: Limited state persistence * **Resource Constraints**: Memory and processing limitations #### File System Access * **Sandboxing**: iOS app sandboxing restrictions * **File Access**: Limited file system access * **Storage Limits**: Temporary storage constraints * **Permission Model**: iOS permission system limitations #### Network Constraints * **Network Dependency**: Requires active network connection * **Background Network**: Limited background network access * **Connection Stability**: Vulnerable to network interruptions * **Timeout Limits**: iOS timeout constraints ### Shortcut-Specific Limitations #### Action Limitations * **Action Count**: Limited number of actions per shortcut * **Complexity**: Limited logical complexity * **Performance**: Performance constraints for complex shortcuts * **Debugging**: Limited debugging capabilities #### Content Limitations * **File Size**: Large file handling limitations * **Content Types**: Limited content type support * **Metadata**: Limited metadata preservation * **Encoding**: Character encoding limitations ## Troubleshooting ### Common Issues #### Installation Problems * **Untrusted Shortcuts**: Enable "Allow Untrusted Shortcuts" in Settings * **iOS Version**: Verify iOS compatibility (iOS 12+) * **Shortcuts App**: Ensure Shortcuts app is updated * **Storage Space**: Check available device storage #### Share Menu Issues * **Missing from Share Menu**: Check shortcut is properly installed * **Wrong Section**: Look in appropriate share menu section * **Content Type**: Verify content type is supported * **App Permissions**: Check app permissions for content access #### Transfer Issues * **Network Connection**: Verify active internet connection * **Web App Loading**: Ensure ErikrafT Drop web app loads properly * **Device Pairing**: Verify devices are properly paired * **Transfer Completion**: Wait for transfer to complete #### Performance Issues * **Large Files**: Large files may take longer to process * **Multiple Items**: Batch processing may be slower * **Device Performance**: Older devices may be slower * **Network Speed**: Network speed affects transfer time ### Debug Information #### Shortcut Diagnostics * **Action Log**: Review shortcut action log in Shortcuts app * **Error Messages**: Note any error messages displayed * **Performance**: Monitor shortcut execution time * **Success Rate**: Track success vs failure rate #### iOS Diagnostics * **System Logs**: Check iOS logs for relevant information * **Network Status**: Verify network connectivity and speed * **Storage Status**: Check available storage space * **App Status**: Verify app and system status ## Best Practices ### Usage Recommendations #### Content Selection * **Appropriate Content**: Share appropriate content types * **File Size**: Consider file size for performance * **Network Conditions**: Use on stable network connections * **Device Compatibility**: Ensure target device compatibility #### Workflow Optimization * **Batch Processing**: Group similar content for efficiency * **Timing**: Use during optimal network conditions * **Device Preparation**: Ensure target devices are ready * **Completion Verification**: Verify transfer completion ### Security Considerations #### Content Security * **Sensitive Content**: Be cautious with sensitive content * **Network Security**: Use secure network connections * **Device Trust**: Only share with trusted devices * **Content Verification**: Verify content before sharing #### Privacy Protection * **Personal Data**: Protect personal information * **Sharing Scope**: Limit sharing to intended recipients * **Content Lifecycle**: Manage content lifecycle appropriately * **Access Control**: Control access to shared content ## Future Development ### Potential Enhancements #### iOS Integration Improvements * **Background Processing**: Enhanced background operation * **Native App**: Potential native iOS app development * **Widget Support**: Home screen widget for quick access * **Siri Integration**: Voice command integration #### Feature Enhancements * **Advanced Content Types**: Support for additional content types * **Batch Operations**: Enhanced batch processing capabilities * **Progress Tracking**: Improved progress indication * **Error Recovery**: Enhanced error handling and recovery #### Performance Optimizations * **Speed Improvements**: Faster processing and transfer * **Memory Efficiency**: Improved memory usage * **Network Optimization**: Enhanced network performance * **Battery Efficiency**: Reduced battery consumption The iOS Shortcut integration provides an elegant, native solution for iOS users to access ErikrafT Drop functionality while maintaining the familiar iOS user experience and leveraging the capabilities of Apple's Shortcuts ecosystem. # Device Pairing Source: https://docsdrop.erikraft.com/features/device-pairing Persistent device pairing system using encrypted room secrets stored in IndexedDB for cross-network device discovery. # Device Pairing System ErikrafT Drop's device pairing feature allows devices to maintain persistent connections across different networks. Paired devices can discover each other regardless of their current network location, providing seamless file sharing capabilities. ## Pairing Architecture ### Room Secret System Device pairing uses cryptographically secure room secrets: ```javascript theme={null} // From ws-server.js lines 223-224 let roomSecret = randomizer.getRandomString(256); let pairKey = this._createPairKey(sender, roomSecret); ``` ### Persistent Storage Paired device information is stored using IndexedDB: ```javascript theme={null} // From persistent-storage.js class PersistentStorage { async saveRoomSecret(roomSecret) { return new Promise((resolve, reject) => { const request = indexedDB.open('pairdrop-db'); request.onsuccess = (event) => { const db = event.target.result; const transaction = db.transaction(['room-secrets'], 'readwrite'); const store = transaction.objectStore('room-secrets'); store.put({ id: roomSecret, secret: roomSecret }); }; }); } } ``` ## Pairing Process ### 1. Initiation Phase #### Pair Device Dialog ```javascript theme={null} // From ui.js lines 1954-1956 _pairDeviceInitiate() { Events.fire('pair-device-initiate'); } ``` #### Server-Side Initiation ```javascript theme={null} // From ws-server.js lines 222-237 _onPairDeviceInitiate(sender) { let roomSecret = randomizer.getRandomString(256); let pairKey = this._createPairKey(sender, roomSecret); if (sender.pairKey) { this._removePairKey(sender.pairKey); } sender.pairKey = pairKey; this._send(sender, { type: 'pair-device-initiated', roomSecret: roomSecret, pairKey: pairKey }); this._joinSecretRoom(sender, roomSecret); } ``` ### 2. Key Generation #### Secure Pair Key Creation ```javascript theme={null} // From ws-server.js lines 327-340 _createPairKey(creator, roomSecret) { let pairKey; do { // Generate 6-digit numeric key pairKey = crypto.randomInt(1000000, 1999999).toString().substring(1); } while (pairKey in this._roomSecrets) this._roomSecrets[pairKey] = { roomSecret: roomSecret, creator: creator } return pairKey; } ``` #### Key Format * **Length**: 6 digits * **Format**: Numeric string (e.g., "123456") * **Uniqueness**: Guaranteed unique within server instance * **Expiration**: Temporary, expires after pairing or timeout ### 3. QR Code Generation #### QR Code Display ```javascript theme={null} // From ui.js lines 1966-1981 _setKeyAndQRCode() { this.$key.innerText = `${this.pairKey.substring(0, 3)} ${this.pairKey.substring(3, 6)}` // Display QR code for the url const qr = new QRCode({ content: this._getPairUrl(), width: 130, height: 130, color: { dark: "#000000", light: "#FFFFFF" }, ecl: "L", join: true }); this.$qrCode.innerHTML = qr.svg(); } ``` #### Pair URL Generation ```javascript theme={null} // From ui.js lines 1983-2002 _getPairUrl() { const url = new URL(location.href); url.searchParams.delete('pair_key'); url.hash = ''; if (this.pairKey) { url.searchParams.append('pair_key', this.pairKey); } return url.href; } ``` ## Joining a Pair ### 1. Key Entry ```javascript theme={null} // From ui.js lines 2004-2014 _submit() { let inputKey = this.inputKeyContainer._getInputKey(); this._pairDeviceJoin(inputKey); } _pairDeviceJoin(pairKey) { if (/^\d{6}$/g.test(pairKey)) { Events.fire('pair-device-join', pairKey); this.inputKeyContainer.focusLastChar(); } } ``` ### 2. Server Validation ```javascript theme={null} // From ws-server.js lines 239-265 _onPairDeviceJoin(sender, message) { if (sender.rateLimitReached()) { this._send(sender, { type: 'join-key-rate-limit' }); return; } if (!this._roomSecrets[message.pairKey] || sender.id === this._roomSecrets[message.pairKey].creator.id) { this._send(sender, { type: 'pair-device-join-key-invalid' }); return; } const roomSecret = this._roomSecrets[message.pairKey].roomSecret; const creator = this._roomSecrets[message.pairKey].creator; this._removePairKey(message.pairKey); this._send(sender, { type: 'pair-device-joined', roomSecret: roomSecret, peerId: creator.id }); this._send(creator, { type: 'pair-device-joined', roomSecret: roomSecret, peerId: sender.id }); this._joinSecretRoom(sender, roomSecret); this._removePairKey(sender.pairKey); } ``` ### 3. Pair Confirmation ```javascript theme={null} // From ui.js lines 2016-2037 _onPairDeviceJoined(peerId, roomSecret) { // abort if peer is another tab on the same browser if (BrowserTabsConnector.peerIsSameBrowser(peerId)) { this._cleanUp(); return; } // save pairPeer and wait for it to connect this.pairPeer = { "peerId": peerId, "roomSecret": roomSecret }; // save roomSecret PersistentStorage .saveRoomSecret(roomSecret) .then(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.pairing-success")); this.hide(); }) .catch(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.pairing-not-persistent")); }); } ``` ## Paired Device Management ### Storage Structure ```javascript theme={null} // IndexedDB stores paired device information { id: "room-secret-256-char-string", secret: "256-character-encrypted-room-secret", displayName: "User-chosen-device-name", autoAccept: false, timestamp: 1640995200000 } ``` ### Device List Management ```javascript theme={null} // From ui.js lines 2162-2243 async _initDOM() { const roomSecretsEntries = await PersistentStorage.getAllRoomSecretEntries(); roomSecretsEntries.forEach(roomSecretsEntry => { let $pairedDevice = document.createElement('div'); $pairedDevice.classList.add('paired-device'); // Device display information const displayDiv = document.createElement('div'); displayDiv.className = 'display-name'; displayDiv.textContent = roomSecretsEntry.displayName; // Auto-accept toggle const input = document.createElement('input'); input.type = 'checkbox'; input.checked = roomSecretsEntry.autoAccept; input.addEventListener('change', e => { PersistentStorage.updateRoomSecret(roomSecretsEntry.id, { autoAccept: e.target.checked }); }); $pairedDevice.appendChild(displayDiv); $pairedDevice.appendChild(input); this.$pairedDevicesWrapper.appendChild($pairedDevice); }); } ``` ### Auto-Accept Feature ```javascript theme={null} // From network.js lines 841-847 _respondToFileTransferRequest(accepted) { this.sendJSON({type: 'files-transfer-response', accepted: accepted}); if (accepted) { this._requestAccepted = this._requestPending; this._totalBytesReceived = 0; this._filesReceived = []; } this._requestPending = null; } ``` ## Security Features ### Cryptographic Security * **Room Secrets**: 256-character cryptographically random strings * **Hash Validation**: SHA3-512 hashing for integrity verification * **Rate Limiting**: 10 pairing attempts per 10 seconds * **Temporary Keys**: Pair keys expire after use ### Privacy Protection ```javascript theme={null} // From peer.js lines 128-136 _setPeerId(request) { const searchParams = new URL(request.url, "http://server").searchParams; let peerId = searchParams.get('peer_id'); let peerIdHash = searchParams.get('peer_id_hash'); if (peerId && Peer.isValidUuid(peerId) && this.isPeerIdHashValid(peerId, peerIdHash)) { this.id = peerId; } else { this.id = crypto.randomUUID(); } } ``` ## Cross-Network Discovery ### Persistent Connections Paired devices maintain discoverability across different networks: 1. **Local Network**: Automatic discovery via IP-based rooms 2. **Remote Networks**: Discovery via shared room secrets 3. **Network Switching**: Seamless transition between networks 4. **Offline Support**: Pairing information persists offline ### Room Secret Synchronization ```javascript theme={null} // From ws-server.js lines 188-198 _onRoomSecrets(sender, message) { if (!message.roomSecrets) return; const roomSecrets = message.roomSecrets.filter(roomSecret => { return /^[\x00-\x7F]{64,256}$/.test(roomSecret); }); if (!roomSecrets) return; this._joinSecretRooms(sender, roomSecrets); } ``` ## Pairing Management ### Edit Paired Devices ```javascript theme={null} // From ui.js lines 2141-2252 class EditPairedDevicesDialog extends Dialog { constructor() { super('edit-paired-devices-dialog'); this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper'); Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e)); Events.on('keydown', e => this._onKeyDown(e)); } } ``` ### Unpairing Devices ```javascript theme={null} // From ui.js lines 2221-2240 input.addEventListener('click', e => { PersistentStorage .deleteRoomSecret(roomSecretsEntry.id) .then(roomSecret => { Events.fire('room-secrets-deleted', [roomSecret]); Events.fire('evaluate-number-room-secrets'); $pairedDevice.innerText = ''; }); }); ``` ## Use Cases ### Personal Device Ecosystem * **Phone to Computer**: Quick photo and document transfer * **Tablet to Laptop**: Seamless file synchronization * **Work to Home**: Access files across different networks ### Family Sharing * **Parent-Child Devices**: Easy family file sharing * **Multi-Device Households**: Shared family devices * **Guest Access**: Temporary pairing for visitors ### Professional Use * **Team Collaboration**: Persistent team device connections * **Conference Sharing**: Quick setup for presentations * **Remote Work**: Home-office device integration ## Troubleshooting ### Common Issues * **Invalid Key**: Ensure 6-digit key is entered correctly * **Expired Key**: Pair keys expire after use or timeout * **Network Issues**: Both devices need internet connection for pairing * **Browser Storage**: Ensure IndexedDB is enabled and not cleared ### Recovery Options * **Re-pairing**: Devices can be re-paired if needed * **Backup**: Export/import pairing information (planned feature) * **Manual Discovery**: Use local network discovery if pairing fails This device pairing system provides a robust, secure method for maintaining persistent connections between devices across different networks while ensuring user privacy and security. # P2P Transfer Source: https://docsdrop.erikraft.com/features/p2p-transfer Direct peer-to-peer file transfers using WebRTC DataChannels for secure, efficient communication. # Peer-to-Peer File Transfer ErikrafT Drop's core feature is direct peer-to-peer file transfer using WebRTC technology. This enables devices to communicate directly without routing files through central servers, providing both privacy and performance benefits. ## WebRTC DataChannel Implementation ### Connection Establishment The P2P transfer system uses WebRTC DataChannels for direct communication: ```javascript theme={null} // From network.js lines 1126-1129 const channel = this._conn.createDataChannel('data-channel', { ordered: true, reliable: true // Obsolete but maintained for compatibility }); ``` ### Binary Data Transfer Files are transferred as binary data for maximum efficiency: ```javascript theme={null} // From network.js lines 1177-1178 channel.binaryType = 'arraybuffer'; channel.onmessage = e => this._onMessage(e.data); ``` ## Transfer Capabilities ### Supported File Types * **All File Types**: No restrictions on file formats * **Large Files**: Limited only by browser memory and network constraints * **Multiple Files**: Simultaneous transfer of multiple files and folders * **Directory Support**: Complete directory structure preservation ### Transfer Performance * **Direct Connection**: No server bandwidth consumption * **Network Speed**: Limited only by local network capabilities * **Concurrent Transfers**: Multiple simultaneous transfers supported * **Resume Capability**: Automatic retry for interrupted transfers ## Security Features ### End-to-End Encryption ```javascript theme={null} // WebRTC provides automatic DTLS/SRTP encryption this._conn = new RTCPeerConnection(this.rtcConfig); // All data is encrypted by the browser automatically ``` ### Connection Authentication * **Certificate Exchange**: WebRTC handles certificate exchange automatically * **Fingerprint Verification**: Connection hashes for security validation * **Perfect Forward Secrecy**: Each session uses unique encryption keys ## Transfer Process ### 1. Discovery Phase Devices discover each other through: * **Local Network**: Automatic IP-based discovery * **Device Pairing**: Persistent connections using room secrets * **Public Rooms**: Temporary 5-character room codes ### 2. Connection Phase ```javascript theme={null} // From network.js lines 1104-1113 _connect() { if (!this._conn || this._conn.signalingState === "closed") this._openConnection(); if (this._isCaller) { this._openChannel(); } else { this._conn.ondatachannel = e => this._onChannelOpened(e); } } ``` ### 3. Transfer Phase * **Request/Accept**: Transfer request and user confirmation * **Metadata Exchange**: File information transmission * **Chunked Transfer**: 64KB chunks for memory efficiency * **Progress Tracking**: Real-time progress updates ## File Chunking System ### Chunk Size Optimization ```javascript theme={null} // From network.js lines 1671-1672 this._chunkSize = 64000; // 64 KB chunks this._maxPartitionSize = 1e6; // 1 MB partitions ``` ### Memory Management * **Streaming**: Files processed in chunks to prevent memory overload * **Buffer Control**: Efficient buffer management for large files * **iOS Optimization**: Special handling for iOS memory limits ## Network Optimization ### Connection Reuse ```javascript theme={null} // From network.js lines 1287-1295 refresh() { if (this._isConnected() || this._isConnecting()) return; if (!this._isCaller) return; this._connect(); } ``` ### Adaptive Performance * **ICE Candidate Selection**: Optimal network path selection * **Connection Monitoring**: Real-time connection quality assessment * **Automatic Fallback**: WebSocket fallback when WebRTC fails ## Error Handling ### Connection Recovery ```javascript theme={null} // From network.js lines 1241-1243 _onChannelClosed() { console.log('RTC: channel closed', this._peerId); Events.fire('peer-disconnected', this._peerId); if (!this._isCaller) return; this._connect(); // reopen the channel } ``` ### Transfer Reliability * **Automatic Retry**: Failed chunks are automatically resent * **Progress Preservation**: Transfer progress is maintained during retries * **Graceful Degradation**: Fallback to WebSocket when necessary ## Performance Metrics ### Transfer Speed * **Local Network**: Typically 50-200+ MB/s on Gigabit networks * **WiFi Networks**: 10-50 MB/s depending on signal quality * **Mobile Networks**: 1-10 MB/s depending on connection quality ### Latency * **Connection Setup**: 1-3 seconds for WebRTC establishment * **Transfer Latency**: Sub-millisecond for local networks * **Response Time**: Real-time progress updates ## Browser Compatibility ### WebRTC Support Detection ```javascript theme={null} // From network.js lines 1425-1434 if (window.isRtcSupported && rtcSupported) { this.peers[peerId] = new RTCPeer(this._server, isCaller, peerId, roomType, roomId, this._wsConfig.rtcConfig); } else if (this._wsConfig.wsFallback) { this.peers[peerId] = new WSPeer(this._server, isCaller, peerId, roomType, roomId); } ``` ### Supported Browsers * **Chrome 23+**: Full WebRTC support * **Firefox 22+**: Full WebRTC support * **Safari 11+**: WebRTC support with some limitations * **Edge 79+**: Full WebRTC support (Chromium-based) ## Advanced Features ### Connection Hashing ```javascript theme={null} // From network.js lines 1193-1217 getConnectionHash() { const localDescriptionLines = this._conn.localDescription.sdp.split("\r\n"); const remoteDescriptionLines = this._conn.remoteDescription.sdp.split("\r\n"); // Extract and combine fingerprints for unique connection identification const combinedFingerprints = this._isCaller ? localConnectionFingerprint + remoteConnectionFingerprint : remoteConnectionFingerprint + localConnectionFingerprint; return cyrb53(combinedFingerprints).toString(); } ``` ### Multi-Room Support * **Simultaneous Rooms**: Single peer in multiple room types * **Flexible Discovery**: IP-based, secret-based, and public rooms * **Dynamic Switching**: Seamless switching between room types ## Use Cases ### Personal File Sharing * **Document Transfer**: Quick sharing between work and personal devices * **Media Sharing**: Photo and video sharing between devices * **Backup**: Simple backup between computers and mobile devices ### Professional Use * **Collaboration**: File sharing during meetings * **Development**: Quick code and asset sharing * **Presentations**: Transfer presentation files between devices ### Emergency Scenarios * **No Internet**: Works completely offline on local networks * **Remote Areas**: No dependency on cloud services * **Privacy**: No third-party access to transferred files This P2P transfer system provides a robust, secure, and efficient method for direct file sharing between devices while maintaining user privacy and maximizing transfer speeds. # QR Connection Source: https://docsdrop.erikraft.com/features/qr-connection QR code-based device pairing system for quick and secure connections using camera scanning or manual key entry. # QR Code Connection System ErikrafT Drop's QR code feature provides a fast, user-friendly method for device pairing. The system generates QR codes containing pairing information that can be scanned by another device's camera, eliminating the need for manual key entry. ## QR Code Architecture ### QR Code Generation The QR code system uses the `qr-code.min.js` library to generate scannable codes: ```javascript theme={null} // From ui.js lines 1969-1980 const qr = new QRCode({ content: this._getPairUrl(), width: 130, height: 130, color: { dark: "#000000", light: "#FFFFFF" }, ecl: "L", // Error correction level L (Low) join: true }); this.$qrCode.innerHTML = qr.svg(); ``` ### Pair URL Structure The QR code contains a URL with the pairing key as a parameter: ```javascript theme={null} // From ui.js lines 1983-2002 _getPairUrl() { const url = new URL(location.href); url.searchParams.delete('pair_key'); url.hash = ''; if (this.pairKey) { url.searchParams.append('pair_key', this.pairKey); } return url.href; } ``` **Example URL:** ``` https://drop.erikraft.com/?pair_key=123456 ``` ## QR Code Components ### Visual Elements The QR code interface includes several key components: #### Pair Key Display ```javascript theme={null} // From ui.js lines 1967 this.$key.innerText = `${this.pairKey.substring(0, 3)} ${this.pairKey.substring(3, 6)}` ``` #### QR Code Container ```javascript theme={null} // From ui.js lines 1903 this.$qrCode = this.$el.querySelector('.key-qr-code'); ``` #### Copy Functionality ```javascript theme={null} // From ui.js lines 1931 this.$qrCode.addEventListener('click', _ => this._copyPairUrl()); ``` ### Error Correction Levels The system uses Error Correction Level L (Low) which provides: * **7% error correction capability** * **Maximum data capacity** * **Optimal for digital displays** ## QR Code Usage Flow ### 1. Generation Phase #### User Initiates Pairing ```javascript theme={null} // From ui.js lines 1954-1956 _pairDeviceInitiate() { Events.fire('pair-device-initiate'); } ``` #### Server Response ```javascript theme={null} // From ws-server.js lines 231-236 this._send(sender, { type: 'pair-device-initiated', roomSecret: roomSecret, pairKey: pairKey }); ``` #### QR Code Display ```javascript theme={null} // From ui.js lines 1958-1964 _onPairDeviceInitiated(msg) { this.pairKey = msg.pairKey; this.roomSecret = msg.roomSecret; this._setKeyAndQRCode(); this.inputKeyContainer._enableChars(); this.show(); } ``` ### 2. Scanning Phase #### Camera Access Request The system requests camera access for QR code scanning: ```javascript theme={null} // Camera access is handled by the browser's getUserMedia API navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }) .then(stream => { // Initialize QR code scanner }) .catch(error => { console.error('Camera access denied:', error); }); ``` #### QR Code Detection The QR code scanning uses the browser's built-in capabilities or third-party libraries for real-time detection: ```javascript theme={null} // QR code scanning implementation (conceptual) function scanQRCode(videoElement) { // Use qr-scanner library or similar // Detect QR codes in video stream // Extract pair_key parameter // Auto-fill the pairing key } ``` ### 3. Auto-Pairing Process #### URL Parameter Detection ```javascript theme={null} // Automatic detection on page load const urlParams = new URLSearchParams(window.location.search); const pairKey = urlParams.get('pair_key'); if (pairKey) { // Auto-fill the pairing key document.querySelector('.pair-key-input').value = pairKey; // Auto-submit the pairing request submitPairingRequest(pairKey); } ``` #### Automatic Pair Submission ```javascript theme={null} // From ui.js lines 2009-2014 _pairDeviceJoin(pairKey) { if (/^\d{6}$/g.test(pairKey)) { Events.fire('pair-device-join', pairKey); this.inputKeyContainer.focusLastChar(); } } ``` ## QR Code Features ### Click to Copy Users can copy the pairing URL by clicking the QR code: ```javascript theme={null} // Copy functionality implementation _copyPairUrl() { const url = this._getPairUrl(); navigator.clipboard.writeText(url) .then(() => { Events.fire('notify-user', 'Pair URL copied to clipboard'); }) .catch(err => { console.error('Failed to copy URL:', err); }); } ``` ### Manual Key Entry For devices without camera access, users can manually enter the 6-digit key: ```javascript theme={null} // Key validation if (/^\d{6}$/g.test(pairKey)) { Events.fire('pair-device-join', pairKey); } ``` ### Visual Feedback The system provides visual feedback throughout the process: #### Loading States * **QR Code Generation**: Shows loading indicator * **Camera Initialization**: Displays camera permission request * **Scanning Process**: Shows scanning animation #### Success/Error States * **Successful Scan**: Highlights detected key * **Invalid Key**: Shows error message * **Connection Success**: Displays success notification ## Browser Compatibility ### Camera Access Requirements * **HTTPS Required**: Camera access requires secure context * **User Permission**: Explicit user permission required * **Modern Browsers**: Chrome 53+, Firefox 52+, Safari 11+ ### Fallback Options When camera access is unavailable: 1. **Manual Entry**: 6-digit key input field 2. **Copy URL**: Copy pairing URL to clipboard 3. **Share Link**: Use browser's share functionality ## Security Considerations ### QR Code Security * **Temporary Keys**: Pair keys expire after use * **Rate Limiting**: Prevents brute force attacks * **Secure Context**: Requires HTTPS for camera access ### URL Security ```javascript theme={null} // URL validation and sanitization function validatePairUrl(url) { const parsedUrl = new URL(url); const pairKey = parsedUrl.searchParams.get('pair_key'); // Validate pair key format if (!/^\d{6}$/.test(pairKey)) { throw new Error('Invalid pair key format'); } // Validate domain if (!allowedDomains.includes(parsedUrl.hostname)) { throw new Error('Unauthorized domain'); } return pairKey; } ``` ## Performance Optimization ### QR Code Rendering * **SVG Format**: Scalable vector graphics for crisp display * **Optimized Size**: 130x130 pixels for balance of scannability and screen space * **Low Error Correction**: Maximum data capacity for simple URLs ### Camera Performance * **Environment Camera**: Uses rear camera on mobile devices * **Resolution Optimization**: Balanced resolution for scanning performance * **Frame Rate**: Optimized for real-time detection ## User Experience ### Mobile-First Design * **Large Touch Targets**: Easy tapping on mobile devices * **Responsive Layout**: Adapts to different screen sizes * **Gesture Support**: Swipe and tap interactions ### Accessibility Features * **Keyboard Navigation**: Full keyboard accessibility * **Screen Reader Support**: Proper ARIA labels * **High Contrast**: Clear visual contrast ## Use Cases ### Quick Device Pairing * **Mobile to Desktop**: Scan QR code on desktop with phone * **Desktop to Mobile**: Display QR code on desktop, scan with phone * **Tablet to Phone**: Cross-device pairing without typing ### Public Sharing * **Presentations**: Audience members can quickly connect * **Classrooms**: Students connect to teacher's device * **Meetings**: Quick file sharing during presentations ### Accessibility Scenarios * **Motor Impairments**: QR code eliminates typing requirements * **Visual Impairments**: Screen reader support for manual entry * **Temporary Disabilities**: Voice command support for hands-free operation ## Troubleshooting ### Common QR Code Issues #### Camera Not Working * **Check Permissions**: Ensure camera access is granted * **HTTPS Required**: Verify the site is loaded over HTTPS * **Browser Support**: Use a modern browser with camera support #### QR Code Not Scanning * **Lighting Conditions**: Ensure adequate lighting * **Screen Glare**: Adjust screen angle to reduce glare * **Distance**: Maintain appropriate distance from screen #### Invalid Pair Key * **Expired Key**: Generate a new QR code * **Already Used**: Each key can only be used once * **Network Issues**: Both devices need internet connection ### Recovery Options 1. **Manual Entry**: Type the 6-digit key manually 2. **Copy URL**: Copy and share the pairing URL 3. **Regenerate**: Create a new QR code 4. **Local Discovery**: Use IP-based discovery on same network This QR code system provides an efficient, user-friendly method for device pairing that combines modern web capabilities with robust security measures. # Getting ErikrafT Drop Source: https://docsdrop.erikraft.com/introduction/getting-erikraft-drop Complete guide to downloading and installing ErikrafT Drop across all platforms and integrations. # Getting ErikrafT Drop ErikrafT Drop is available across multiple platforms and integrations, making it accessible for virtually any device or workflow. Whether you prefer the web app, native applications, or platform-specific extensions, there's an ErikrafT Drop solution for your needs. ## Web Application The primary way to use ErikrafT Drop is through the web application - no installation required. [**🌐 https://drop.erikraft.com/**](https://drop.erikraft.com/) ### Web App Features * **Instant Access**: No download or installation required * **Cross-Platform**: Works on any modern browser * **Progressive Web App**: Installable as a native application * **Automatic Updates**: Always using the latest version * **Full Feature Set**: Complete ErikrafT Drop functionality ### Browser Requirements * Chrome 23+, Firefox 22+, Safari 11+, Edge 79+ * WebRTC support required * JavaScript must be enabled ## Mobile Applications ### Android App The Android application provides native integration with the operating system for enhanced file sharing capabilities. #### Download Sources **📱 Google Play Store** [https://play.google.com/store/apps/details?id=com.erikraft.drop](https://play.google.com/store/apps/details?id=com.erikraft.drop) **📦 F-Droid** [https://f-droid.org/en/packages/com.erikraft.drop/](https://f-droid.org/en/packages/com.erikraft.drop/) **📲 APKPure** [https://apkpure.com/p/com.erikraft.drop](https://apkpure.com/p/com.erikraft.drop) **⬇️ Direct APK** [https://github.com/erikraft/Drop-Android/releases/latest/download/Drop-Android.apk](https://github.com/erikraft/Drop-Android/releases/latest/download/Drop-Android.apk) #### Android App Features * **Native Integration**: Share directly from any Android app * **Background Operation**: Works while using other apps * **System Integration**: Appears in Android share menu * **Optimized Performance**: Native Android optimizations * **Offline Pairing**: Works with paired devices offline #### Requirements * Android 5.0+ (API level 21) * WebRTC support * Network connection for initial pairing ### iOS Integration #### iOS Shortcut For iOS users, ErikrafT Drop is available through the Shortcuts app, providing seamless integration with the iOS share menu. **🍎 iOS Shortcut** [https://routinehub.co/shortcut/24753/](https://routinehub.co/shortcut/24753/) #### Shortcut Features * **Share Menu Integration**: Appears in iOS share sheet * **Universal Content**: Share images, files, URLs, and text * **Quick Access**: One-tap file sharing * **System Integration**: Works with any iOS app that supports sharing #### Requirements * iOS 12+ (Shortcuts app required) * ErikrafT Drop running on target device * Internet connection ## Desktop Integrations ### Browser Extensions Enhance your browser experience with dedicated extensions for quick access and system integration. #### VS Code Extension **💻 VS Code Marketplace** [https://marketplace.visualstudio.com/items?itemName=ErikrafT.erikraft-drop](https://marketplace.visualstudio.com/items?itemName=ErikrafT.erikraft-drop) **🔧 Open VSX Registry** [https://open-vsx.org/extension/ErikrafT/erikraft-drop](https://open-vsx.org/extension/ErikrafT/erikraft-drop) #### Browser Extensions **🌍 Opera Extension** [https://addons.opera.com/en/extensions/details/erikraft-drop/](https://addons.opera.com/en/extensions/details/erikraft-drop/) **📧 Thunderbird Add-on** [https://addons.thunderbird.net/pt-BR/thunderbird/addon/erikraft-drop/](https://addons.thunderbird.net/pt-BR/thunderbird/addon/erikraft-drop/) **🦊 Firefox Extension** [https://addons.mozilla.org/pt-BR/firefox/addon/erikraft-drop/](https://addons.mozilla.org/pt-BR/firefox/addon/erikraft-drop/) #### Extension Features * **Quick Access**: One-click file sharing from browser * **Context Menu**: Right-click file sharing options * **System Integration**: Native file browser integration * **Persistent Connection**: Maintains ErikrafT Drop connection ### Discord Integration #### Discord Bot Bring ErikrafT Drop functionality directly to your Discord server with the official bot. **🤖 Discord Bot** [https://discord.com/oauth2/authorize?client\_id=1367869058707492955](https://discord.com/oauth2/authorize?client_id=1367869058707492955) #### Bot Features * **Slash Commands**: `/drop` command for file sharing * **File Transfer**: Send and receive files through Discord * **Real-time Sync**: Appears as paired device in web interface * **Multi-file Support**: Send up to 3 files per command * **Text Messages**: Send text messages alongside files #### Requirements * Discord server with bot permissions * ErikrafT Drop instance with WebSocket fallback * Node.js 18+ for self-hosting ## Installation Guide ### Quick Start 1. **Choose Your Platform**: Select the appropriate version for your device 2. **Download**: Use the provided download links 3. **Install**: Follow platform-specific installation instructions 4. **Connect**: Pair devices and start sharing files ### Platform-Specific Setup #### Web App 1. Open [https://drop.erikraft.com/](https://drop.erikraft.com/) in your browser 2. Allow camera permissions for QR code scanning (optional) 3. Install as PWA for native app experience (optional) #### Android App 1. Download from Google Play Store or F-Droid 2. Grant necessary permissions during installation 3. Open app and connect to ErikrafT Drop network 4. Enable system integration for share menu access #### iOS Shortcut 1. Download the shortcut from RoutineHub 2. Add to Shortcuts library 3. Enable "Allow Untrusted Shortcuts" if needed 4. Access from share menu in any app #### Browser Extensions 1. Install from respective extension store 2. Grant necessary permissions 3. Configure ErikrafT Drop server URL if self-hosting 4. Use extension toolbar or context menu #### Discord Bot 1. Invite bot to Discord server 2. Configure bot with Discord token 3. Set up ErikrafT Drop connection 4. Use `/drop` command for file sharing ## Self-Hosting Options For users who prefer to run their own ErikrafT Drop instance: ### Server Requirements * Node.js 20.18.1+ * 512MB RAM minimum * Network connectivity * Domain (optional but recommended) ### Deployment Methods * **Docker**: Containerized deployment * **Direct**: Node.js application * **Cloud**: Various cloud platform options * **Local**: On-premise installation ### Configuration * Custom domain setup * SSL/TLS certificates * Rate limiting * LAN-only mode ## Choosing the Right Version ### For Personal Use * **Web App**: Most convenient, no installation * **Android App**: Best for Android users with frequent sharing * **iOS Shortcut**: Essential for iOS users ### For Development Teams * **VS Code Extension**: Integrate with development workflow * **Browser Extensions**: Quick sharing during development * **Self-Hosting**: Control over data and infrastructure ### For Organizations * **Self-Hosting**: Complete control over data * **Discord Bot**: Integration with team communication * **Android App**: Mobile workforce support ### For Privacy-Conscious Users * **Self-Hosting**: Data never leaves your infrastructure * **LAN Mode**: Local-only file sharing * **No Registration**: No personal data required ## Compatibility Matrix | Platform | WebRTC Support | Auto-Accept | QR Code | System Integration | | ------------------ | -------------- | ----------- | ------- | ------------------ | | Web App | ✅ | ✅ | ✅ | ❌ | | Android | ✅ | ✅ | ✅ | ✅ | | iOS Shortcut | ✅ | ✅ | ✅ | ✅ | | VS Code | ✅ | ✅ | ❌ | ✅ | | Browser Extensions | ✅ | ✅ | ❌ | ✅ | | Discord Bot | ❌\* | ✅ | ❌ | ✅ | \*Discord Bot uses WebSocket fallback instead of WebRTC ## Support and Community ### Getting Help * **Documentation**: Comprehensive guides and API references * **GitHub Issues**: Report bugs and request features * **Community**: Join discussions and share experiences * **Discord**: Real-time community support ### Contributing * **Open Source**: All platforms are open source * **Translations**: Help translate to your language * **Development**: Contribute code and improvements * **Testing**: Test pre-release versions ## Updates and Maintenance ### Automatic Updates * **Web App**: Always latest version * **Android App**: Google Play automatic updates * **Browser Extensions**: Auto-update through extension stores * **Discord Bot**: Manual updates for self-hosted instances ### Version Compatibility * **Cross-Platform**: All versions work together * **Backward Compatibility**: Older versions work with newer * **API Stability**: Consistent API across platforms * **Migration**: Easy migration between versions Choose the ErikrafT Drop version that best fits your workflow and start sharing files securely and efficiently across all your devices. # Getting Started Source: https://docsdrop.erikraft.com/introduction/getting-started Quick start guide for setting up and using ErikrafT Drop for file sharing. # Getting Started with ErikrafT Drop ErikrafT Drop requires minimal setup and works immediately on most modern browsers. Follow this guide to start sharing files between devices. ## Quick Start ### 1. Open ErikrafT Drop Navigate to [https://drop.erikraft.com/](https://drop.erikraft.com/) in your web browser on all devices you want to connect. ### 2. Discover Devices * **Local Network**: Devices on the same network automatically appear after a few seconds * **Paired Devices**: Previously paired devices appear automatically if they're online * **Manual Pairing**: Use QR codes or 6-digit keys to connect devices on different networks ### 3. Share Files * **Drag & Drop**: Drag files onto the browser window * **Click to Select**: Click the main area to open file selector * **Share Menu**: Use the browser's share menu (on mobile devices) ## System Requirements ### Browser Support ErikrafT Drop works with all modern browsers that support WebRTC: | Browser | Minimum Version | WebRTC Support | Notes | | ------- | --------------- | -------------- | ---------------- | | Chrome | 23+ | Full | Recommended | | Firefox | 22+ | Full | Good alternative | | Safari | 11+ | Full | iOS and macOS | | Edge | 79+ | Full | Chromium-based | ### Network Requirements * **Local Network**: Automatic discovery works on any local network * **Internet Connection**: Required for initial signaling server connection * **No Special Configuration**: Works with most home and office networks ### Device Requirements * **Memory**: Sufficient RAM for file transfers (recommended 4GB+ for large files) * **Storage**: Available disk space for received files * **Browser**: Modern browser with JavaScript enabled ## Installation Options ### Web Application (Recommended) No installation required - simply use the web application directly. ### Progressive Web App (PWA) Install as a native application: 1. **Chrome/Edge**: Click the install icon in the address bar 2. **Firefox**: Use the "Install Site" option in the menu 3. **Safari**: Tap "Share" → "Add to Home Screen" ### Command Line Interface For power users, the CLI tool enables file sharing from the terminal: ```bash theme={null} # Install (Linux/Mac) wget https://github.com/erikraft/Drop/releases/download/v1.12.4/erikraftdrop-cli.zip unzip erikraftdrop-cli.zip sudo chmod +x erikraftdrop sudo ln -s erikraftdrop /usr/local/bin/erikraftdrop # Usage erikraftdrop file1.txt file2.jpg erikraftdrop -t "Hello world" ``` ## Ecosystem Components ErikrafT Drop provides a comprehensive ecosystem of applications and integrations across multiple platforms: ### Discord Bot Integration The official Discord bot enables seamless file sharing directly within Discord servers and direct messages. **Key Features:** * **Slash Commands**: Use `/drop` command with 6-digit pairing keys * **File Transfer**: Send up to 3 files simultaneously (max 25MB each per Discord limits) * **Text Messages**: Send text messages up to 1800 characters inline, larger as attachments * **Bidirectional Transfer**: Both send and receive files through Discord * **Real-time Progress**: Live transfer progress updates with emoji indicators * **Error Handling**: Comprehensive error reporting and retry mechanisms **Technical Implementation:** * Built with Discord.js v14 using modern slash command architecture * WebRTC integration for peer-to-peer connections * Automatic file downloading and re-uploading through Discord's API * Environment-based configuration for deployment flexibility * Portuguese language support with localized error messages **Usage Example:** ``` /drop key:123456 name:"MyDevice" message:"Hello world!" /drop key:123456 file1:@image.png ``` ### Browser Extensions Native browser extensions provide enhanced integration and quick access to ErikrafT Drop functionality. **Supported Browsers:** * **Chrome**: Manifest V3 extension with popup interface * **Firefox**: WebExtension with enhanced privacy features * **Edge**: Chromium-based extension with Microsoft Store integration * **Opera**: Opera extension with sidebar support **Extension Features:** * **Quick Launch**: One-click access to ErikrafT Drop * **Context Menu**: Right-click files to share directly * **Popup Interface**: Compact UI for rapid file sharing * **Icon Integration**: Native browser toolbar integration * **No Special Permissions**: Minimal permission requirements for privacy **Technical Details:** * Manifest V3 compliance for modern browser security * Host permissions limited to [https://drop.erikraft.com/](https://drop.erikraft.com/) * No background scripts or persistent storage * Lightweight design with minimal resource usage ### iOS Shortcut Integration Apple Shortcuts integration brings ErikrafT Drop functionality to iOS devices with native system integration. **Shortcut Features:** * **Native iOS Integration**: Works with iOS Shortcuts app * **System-wide Access**: Launch from anywhere using Siri or Shortcuts * **File Sharing**: Share files from other apps directly to ErikrafT Drop * **URL Scheme Support**: Deep linking for seamless app switching * **Background Processing**: Works in background for enhanced user experience **Implementation Details:** * Uses iOS Shortcuts framework for native integration * Leverages WebKit for embedded browser functionality * Supports file picker integration with iOS file system * Optimized for both iPhone and iPad layouts ### Web Application The core web application provides the full ErikrafT Drop experience with modern web technologies. **Web Features:** * **Progressive Web App**: Installable as native application * **Responsive Design**: Optimized for all screen sizes and devices * **Offline Support**: Core functionality available without internet * **Real-time Updates**: Live connection status and transfer progress * **Multi-language Support**: Internationalization with JSON language files **Technical Stack:** * **Frontend**: Vanilla JavaScript with modern ES6+ features * **Styling**: Custom CSS with OpenSans and custom icon fonts * **WebRTC**: Peer-to-peer file transfer technology * **Service Workers**: PWA functionality and offline support * **IndexedDB**: Local storage for device pairing and preferences **Web Application Architecture:** * **Single Page Application**: Dynamic content loading without page refreshes * **Component-based Design**: Modular JavaScript architecture * **Event-driven Communication**: Real-time updates using WebRTC and WebSocket * **Security**: Content Security Policy and HTTPS enforcement * **Performance**: Lazy loading and resource optimization ### Android Native Application The official Android app provides native integration with the Android operating system and enhanced features. **App Features:** * **Native Android UI**: Material Design 3 with system integration * **Background Service**: Continuous operation even when app is closed * **File System Integration**: Full access to Android storage and media * **Notification Support**: Transfer status and completion notifications * **Multi-device Support**: Phone, tablet, TV, and XR variants **Technical Specifications:** * **Package**: `com.erikraft.drop` * **Minimum SDK**: Android 5.0 (API 21) * **Target SDK**: Android 15 (API 35) * **Version**: 9.0.4 (Version Code 13) * **Build System**: Gradle with Android plugin **Android Architecture:** * **ViewBinding**: Modern UI binding approach * **Lifecycle Components**: Android Architecture Components integration * **WebView Integration**: Embedded browser for core functionality * **Storage Framework**: Android Storage Access Framework integration * **Material Design**: Google Material Design 3 components **Advanced Features:** * **Multi-window Support**: Split-screen and picture-in-picture modes * **Accessibility**: Full accessibility support with screen readers * **Dark Mode**: System theme integration * **Auto-start**: Optional automatic startup on device boot * **Network Awareness**: Automatic network change detection **Development and Distribution:** * **Google Play Store**: Official distribution channel * **Open Source**: Full source code available on GitHub * **Automated Builds**: CI/CD pipeline for automated testing and deployment * **Multi-language**: Crowdin-based translation management * **Privacy-focused**: No tracking or analytics integration ## First Time Setup ### Network Discovery 1. **Connect Multiple Devices**: Open ErikrafT Drop on at least two devices 2. **Same Network**: Ensure devices are on the same WiFi/network 3. **Wait for Discovery**: Devices should appear within 10-30 seconds 4. **Test Transfer**: Send a small test file to verify connectivity ### Device Pairing (Optional) For persistent connections across networks: 1. **Initiate Pairing**: Click "Pair Device" on one device 2. **Scan QR Code**: Use the camera to scan the QR code on the second device 3. **Or Enter Key**: Manually enter the 6-digit pairing key 4. **Confirm Connection**: Both devices should show as paired ### Browser Permissions ErikrafT Drop may request: * **Camera Access**: For QR code scanning (optional) * **File Access**: For reading files to share * **Storage Access**: For saving received files * **Notifications**: For transfer status updates (optional) ## Troubleshooting Common Issues ### Devices Not Discovering Each Other **Check Network Connection:** * Ensure both devices are on the same network * Verify internet connectivity is active * Try refreshing both browser windows **Browser Issues:** * Update to the latest browser version * Clear browser cache and cookies * Disable VPN or proxy services * Try a different browser **Network Configuration:** * Check firewall settings * Verify router doesn't block peer-to-peer connections * Try switching between WiFi and cellular data ### Transfer Failures **Large Files:** * iOS devices have 200MB memory limits per transfer * Break large files into smaller chunks * Ensure sufficient available RAM **Connection Drops:** * WebRTC connections may drop on unstable networks * Files can be resumed if transfer is interrupted * Consider using WiFi for more stable connections ### Performance Optimization **For Best Performance:** * Use modern browsers (Chrome/Edge recommended) * Connect via WiFi rather than cellular data * Close unnecessary browser tabs * Ensure sufficient available memory **Network Tips:** * 5GHz WiFi provides better performance than 2.4GHz * Ethernet connections are most stable * Avoid network congestion during large transfers ## Next Steps Once you have ErikrafT Drop working: * **Explore Features**: Try the chat functionality and file preview * **Set Up Pairing**: Pair frequently used devices for quick access * **Install PWA**: Install as a native app for easier access * **CLI Integration**: Set up command-line tools for power users For detailed technical information, see the [Architecture](../architecture/system-overview) section. # How It Works Source: https://docsdrop.erikraft.com/introduction/how-it-works Understanding the technical architecture of ErikrafT Drop's peer-to-peer file sharing system. # How ErikrafT Drop Works ErikrafT Drop uses a hybrid approach combining WebRTC for direct peer-to-peer communication and WebSocket servers for signaling and discovery. The system is designed to work primarily on local networks while supporting remote connections through pairing. ## Connection Flow ### 1. Initial Connection When a user opens ErikrafT Drop in their browser: 1. **WebSocket Connection**: The client connects to the signaling server via WebSocket 2. **Device Identification**: A unique peer ID is generated and stored in sessionStorage 3. **Network Detection**: The server identifies the client's IP address for local network grouping 4. **WebRTC Capability Check**: The browser's WebRTC support is detected and reported ### 2. Device Discovery Devices discover each other through multiple mechanisms: #### Local Network Discovery * Devices on the same IP address are automatically grouped together by the server * The server maintains rooms based on IP addresses (`_rooms[roomId]`) * When a device connects, it receives a list of peers already in its IP-based room * New connections trigger `peer-joined` events for existing devices #### Device Pairing * Paired devices use encrypted 256-character room secrets stored in IndexedDB * Room secrets are persisted across browser sessions using the PersistentStorage class * The server matches devices with identical room secrets regardless of IP address * Paired devices remain discoverable even when on different networks ### 3. WebRTC Connection Process #### Signaling Phase 1. **Offer Creation**: The initiating peer creates a WebRTC offer using `RTCPeerConnection.createOffer()` 2. **Signal Relay**: The offer is sent through the WebSocket server to the target peer 3. **Answer Creation**: The receiving peer creates an answer using `RTCPeerConnection.createAnswer()` 4. **ICE Exchange**: Both peers exchange ICE candidates for network path discovery 5. **Connection Establishment**: WebRTC establishes a direct connection when possible #### DataChannel Setup ```javascript theme={null} // From network.js lines 1126-1129 const channel = this._conn.createDataChannel('data-channel', { ordered: true, reliable: true }); ``` The DataChannel handles all file transfers and messaging once the WebRTC connection is established. ## File Transfer Process ### 1. Transfer Request When files are selected for transfer: 1. **File Metadata**: The sender creates headers with file information (name, size, MIME type) 2. **Transfer Request**: A `request` message is sent to the recipient 3. **User Confirmation**: The recipient displays a transfer request dialog 4. **Accept/Decline**: The recipient responds with `files-transfer-response` ### 2. File Chunking Large files are divided into manageable chunks: ```javascript theme={null} // From network.js lines 1671-1672 this._chunkSize = 64000; // 64 KB chunks this._maxPartitionSize = 1e6; // 1 MB partitions ``` * **FileChunker Class**: Breaks files into 64KB chunks * **Partition Management**: Groups chunks into 1MB partitions for progress tracking * **Memory Management**: Prevents browser memory overload with large files ### 3. Data Transfer Once the transfer is accepted: 1. **Header Transmission**: File metadata is sent first 2. **Chunk Streaming**: File chunks are sent sequentially via DataChannel 3. **Progress Tracking**: Both sender and receiver track transfer progress 4. **Completion Notification**: `file-transfer-complete` message confirms successful transfer ## Security Architecture ### WebRTC Encryption * **DTLS/SRTP**: All WebRTC communications are encrypted by the browser * **Certificate Exchange**: Peers exchange certificates during connection setup * **Perfect Forward Secrecy**: Each session uses unique encryption keys ### Server Security * **No File Storage**: The server never handles file content, only signaling * **Rate Limiting**: Pairing attempts are limited to prevent abuse * **IP Validation**: LAN-only mode restricts connections to local networks * **Hashed IDs**: Peer IDs are salted and hashed for privacy ## Fallback Mechanisms ### WebSocket Fallback When WebRTC is unavailable: 1. **Detection**: The server detects WebRTC capability via `webrtc_supported` parameter 2. **WSPeer Class**: Creates WebSocket-based peer connections 3. **Base64 Encoding**: File chunks are encoded as base64 for WebSocket transmission 4. **Server Relay**: The WebSocket server relays all data between peers ### iOS Memory Management Special handling for iOS devices: ```javascript theme={null} // From network.js lines 819-822 if (window.iOS && request.totalSize >= 200*1024*1024) { // Request to send them in chunks of 200MB instead this.sendJSON({type: 'files-transfer-response', accepted: false, reason: 'ios-memory-limit'}); return; } ``` ## Room Management The server maintains different types of rooms: * **IP Rooms**: `roomType: 'ip'` - Devices on the same local network * **Secret Rooms**: `roomType: 'secret'` - Paired devices using room secrets * **Public Rooms**: `roomType: 'public-id'` - Temporary rooms with 5-character codes Each room manages peer membership, handles join/leave events, and coordinates signaling between members. # Overview Source: https://docsdrop.erikraft.com/introduction/overview ErikrafT Drop is a browser-based P2P file sharing system using WebRTC technology for direct device-to-device transfers. # ErikrafT Drop Overview ErikrafT Drop is a progressive web application that enables secure peer-to-peer file sharing directly between web browsers without requiring intermediate servers. Built on WebRTC technology, it provides encrypted, real-time file transfers with automatic device discovery on local networks. ## Key Features * **Direct P2P Transfers**: Files are transferred directly between devices using WebRTC DataChannels * **Local Network Discovery**: Automatic detection of devices on the same network * **Device Pairing**: Persistent device connections using encrypted room secrets * **QR Code Pairing**: Quick device pairing using QR codes and 6-digit keys * **Cross-Platform**: Works on all modern browsers with WebRTC support * **Progressive Web App**: Installable as a native application * **No File Size Limits**: Limited only by browser memory and network constraints * **Real-time Chat**: Built-in messaging functionality * **WebSocket Fallback**: Alternative transfer method when WebRTC is unavailable ## Technology Stack * **Frontend**: Vanilla JavaScript with WebRTC API * **Backend**: Node.js with Express and WebSocket (ws) server * **Storage**: IndexedDB for persistent device pairing data * **Protocol**: WebRTC for P2P, WebSocket for signaling * **Security**: DTLS/SRTP encryption provided by WebRTC ## Use Cases * **Local File Sharing**: Quickly share files between devices on the same network * **Cross-Platform Transfer**: Share between iOS, Android, Windows, macOS, and Linux * **No Internet Required**: Works entirely on local networks * **Temporary Sharing**: No account registration or setup required * **Secure Transfers**: End-to-end encryption via WebRTC ## Browser Support ErikrafT Drop requires modern browsers with WebRTC support: * Chrome 23+ * Firefox 22+ * Safari 11+ * Edge 79+ The application automatically detects WebRTC capabilities and falls back to WebSocket-based transfers when necessary. # Configuration Source: https://docsdrop.erikraft.com/reference/configuration Complete configuration guide for ErikrafT Drop server, client, and deployment settings. # Configuration Guide ErikrafT Drop provides extensive configuration options for different deployment scenarios, from local development to production environments. This guide covers all available configuration options. ## Server Configuration ### Environment Variables #### Basic Server Settings ```bash theme={null} # Server port (default: 3000) PORT=3000 # Server host binding (default: 0.0.0.0) HOST=0.0.0.0 # Debug mode for development (default: false) DEBUG_MODE=true # Production mode NODE_ENV=production ``` #### Network Configuration ```bash theme={null} # LAN-only mode - restrict to local networks ALLOW_LOCAL_ONLY=true # WebSocket fallback for WebRTC failures WS_FALLBACK=true # Rate limiting for pairing attempts RATE_LIMIT=true # IPv6 localization (number of segments) IPV6_LOCALIZE=2 ``` #### Redis Configuration (Optional) ```bash theme={null} # Redis connection URL REDIS_URL=redis://localhost:6379 # Redis connection options REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= REDIS_DB=0 ``` ### RTC Configuration #### STUN/TURN Servers ```json theme={null} { "sdpSemantics": "unified-plan", "iceServers": [ { "urls": "stun:stun.l.google.com:19302" }, { "urls": "turn:turn.example.com:3478", "username": "user", "credential": "password" } ] } ``` #### LAN Mode Configuration ```javascript theme={null} // From server.js lines 8-11 const rtcConfig = { sdpSemantics: "unified-plan", iceServers: [] }; ``` ### Server Options #### Rate Limiting ```javascript theme={null} // From peer.js lines 34-42 rateLimitReached() { if (this.requestRate >= 10) { return true; } this.requestRate += 1; setTimeout(() => this.requestRate -= 1, 10000); return false; } ``` #### Local IP Detection ```javascript theme={null} // From ws-server.js lines 7-30 function isLocalIp(ip) { if (!ip) return false; if (ip === '127.0.0.1' || ip === '::1') return true; if (!ip.includes(":")) { return LOCAL_IPV4_PATTERNS.some(pattern => pattern.test(ip)); } // IPv6 validation logic } ``` ## Client Configuration ### Browser Settings #### WebRTC Configuration ```javascript theme={null} // From network.js lines 153-155 if (this._lanMode.enabled && msg.wsConfig) { msg.wsConfig.rtcConfig = { iceServers: [] }; } ``` #### LAN Mode Storage ```javascript theme={null} // From network.js lines 1-4 const LAN_STORAGE_KEYS = { enabled: 'lan_mode_enabled', server: 'lan_signaling_server' }; ``` ### Persistent Storage Configuration #### IndexedDB Settings ```javascript theme={null} // From persistent-storage.js class PersistentStorage { constructor() { this._db = null; this._dbName = 'pairdrop-db'; this._version = 1; this._stores = ['room-secrets', 'settings']; } } ``` #### Room Secret Storage ```javascript theme={null} // Room secret structure { id: "room-secret-256-char-string", secret: "256-character-encrypted-room-secret", displayName: "User-chosen-device-name", autoAccept: false, timestamp: 1640995200000 } ``` ## Deployment Configuration ### Docker Configuration #### Docker Compose ```yaml theme={null} # docker-compose.yml version: '3.8' services: erikraftdrop: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DEBUG_MODE=false - RATE_LIMIT=true - ALLOW_LOCAL_ONLY=false restart: unless-stopped volumes: - ./logs:/app/logs ``` #### Dockerfile ```dockerfile theme={null} FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["npm", "start"] ``` ### Docker Swarm Configuration ```yaml theme={null} # docker-compose-swarm.yml version: '3.8' services: erikraftdrop: image: erikraftdrop:latest ports: - "3000:3000" environment: - NODE_ENV=production deploy: replicas: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback monitor: 5s max_failure_ratio: 0.3 ``` ## Reverse Proxy Configuration ### Nginx Configuration ```nginx theme={null} server { listen 80; server_name drop.example.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /server { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; } } ``` ### Apache Configuration ```apache theme={null} ServerName drop.example.com ProxyPreserveHost On ProxyRequests Off ProxyPass / ws://localhost:3000/ ProxyPassReverse / ws://localhost:3000/ ProxyPassReverse /server ws://localhost:3000/ ``` ## Security Configuration ### SSL/TLS Setup #### Let's Encrypt with Nginx ```bash theme={null} # Install certbot sudo apt install certbot python3-certbot-nginx # Generate certificate sudo certbot --nginx -d drop.example.com # Auto-renewal sudo crontab -e # Add: 0 12 * * * /usr/bin/certbot renew --quiet ``` #### SSL Configuration ```nginx theme={null} server { listen 443 ssl http2; server_name drop.example.com; ssl_certificate /etc/letsencrypt/live/drop.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/drop.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512; ssl_prefer_server_ciphers off; location / { proxy_pass http://localhost:3000; # ... proxy headers } } ``` ### Firewall Configuration #### UFW (Ubuntu) ```bash theme={null} # Allow HTTP/HTTPS sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Allow WebSocket port sudo ufw allow 3000/tcp # Enable firewall sudo ufw enable ``` #### iptables ```bash theme={null} # Allow HTTP/HTTPS iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT # Allow WebSocket port iptables -A INPUT -p tcp --dport 3000 -j ACCEPT # Save rules iptables-save > /etc/iptables/rules.v4 ``` ## Performance Configuration ### Node.js Optimization #### Process Management ```bash theme={null} # Increase file descriptor limit ulimit -n 65536 # Set Node.js options export NODE_OPTIONS="--max-old-space-size=4096" # Production optimizations export NODE_ENV=production ``` #### Clustering ```javascript theme={null} // cluster.js example const cluster = require('cluster'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { require('./server/index.js'); } ``` ### Memory Management #### iOS Memory Limits ```javascript theme={null} // From network.js lines 819-822 if (window.iOS && request.totalSize >= 200*1024*1024) { this.sendJSON({ type: 'files-transfer-response', accepted: false, reason: 'ios-memory-limit' }); return; } ``` #### File Chunking Configuration ```javascript theme={null} // From network.js lines 1671-1672 this._chunkSize = 64000; // 64 KB chunks this._maxPartitionSize = 1e6; // 1 MB partitions ``` ## Monitoring and Logging ### Application Logging #### Development Logging ```javascript theme={null} // Debug mode logging if (this._conf.debugMode) { console.debug("\n"); console.debug("----DEBUGGING-PEER-IP-START----"); console.debug("ErikrafTdrop uses:", this.ip); console.debug("----DEBUGGING-PEER-IP-END----"); } ``` #### Production Logging ```bash theme={null} # Log rotation /var/log/erikraftdrop/ ├── access.log ├── error.log └── debug.log # Logrotate configuration /var/log/erikraftdrop/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 www-data www-data } ``` ### Health Checks #### HTTP Endpoints ```javascript theme={null} // From server.js lines 23-27 if (req.url === "/health") { res.writeHead(200, { "Content-Type": "text/plain" }); res.end("ok"); return; } ``` #### Configuration Endpoint ```javascript theme={null} // From server.js lines 14-21 if (req.url === "/config") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ lanOnly: true, rtcConfig })); return; } ``` ## Development Configuration ### Local Development ```bash theme={null} # Clone repository git clone https://github.com/erikraft/Drop.git cd Drop # Install dependencies npm install # Start development server npm run dev # Enable debug mode DEBUG_MODE=true npm start ``` ### Environment Files ```bash theme={null} # .env file NODE_ENV=development PORT=3000 DEBUG_MODE=true RATE_LIMIT=false ALLOW_LOCAL_ONLY=true # .env.production file NODE_ENV=production PORT=3000 DEBUG_MODE=false RATE_LIMIT=true ALLOW_LOCAL_ONLY=false ``` ## CLI Configuration ### Command Line Interface ```bash theme={null} # Configuration file location ~/.erikraftdrop-cli-config # Configuration options domain=https://drop.erikraft.com/ default_browser=chrome download_folder=~/Downloads ``` ### CLI Usage ```bash theme={null} # Show configuration erikraftdrop --config # Set custom domain erikraftdrop -d "https://custom.example.com/" # Specify browser erikraftdrop -b firefox file.txt ``` This comprehensive configuration guide covers all aspects of deploying and customizing ErikrafT Drop for different use cases and environments. # Docker Swarm Usage Source: https://docsdrop.erikraft.com/reference/docker-swarm-usage Guide for deploying ErikrafT Drop using Docker Swarm with health checks # Docker Swarm Usage ## Healthcheck The [Docker Image](../Dockerfile) includes a health check with the following options: ``` --interval=30s ``` > Specifies the time interval to run the health check. \ > In this case, the health check is performed every 30 seconds. ``` --timeout=10s ``` > Specifies the amount of time to wait for a response from the "HEALTHCHECK" command. \ > If the response does not arrive within 10 seconds, the health check fails. ``` --start-period=5s ``` > Specifies the amount of time to wait before starting the health check process. \ > In this case, the health check process will begin 5 seconds after the container is started. ``` --retries=3 ``` > Specifies the number of times Docker should retry the health check \ > before considering the container to be unhealthy. The CMD instruction is used to define the command that will be run as part of the health check. \ In this case, the command is `wget --quiet --tries=1 --spider http://localhost:3000/ || exit 1`. \ This command will attempt to connect to `http://localhost:3000/` \ and if it fails it will exit with a status code of `1`. \ If this command returns a status code other than `0`, the health check fails. Overall, this "HEALTHCHECK" instruction is defining a health check process \ that runs every 30 seconds, and waits up to 10 seconds for a response, # Frequently Asked Questions Source: https://docsdrop.erikraft.com/reference/faq Common questions and answers about ErikrafT Drop # Frequently Asked Questions
Help! I can't install the PWA!
Here is a good guide on how to install PWAs on different platforms: \ [https://www.cdc.gov/niosh/mining/tools/installpwa.html](https://www.cdc.gov/niosh/mining/tools/installpwa.html) **Chromium-based browser on Desktop (Chrome, Comet, Edge, Vivaldi, Brave, etc.)** \ Easily install ErikrafT Drop PWA on your desktop by clicking the install-button in the top-right corner while on [drop.erikraft.com](https://drop.erikraft.com). Example on how to install a pwa with Edge **Desktop Firefox** \ On Firefox, PWAs are installable via [this browser extensions](https://addons.mozilla.org/de/firefox/addon/pwas-for-firefox/) **Android** \ PWAs are installable only by using Google Chrome or Samsung Browser: 1. Visit [drop.erikraft.com](https://drop.erikraft.com/) 2. Click *Install* on the installation pop-up or use the three-dot-menu and click on *Add to Home screen* 3. Click *Add* on the pop-up **iOS** \ PWAs are installable only by using Safari: 1. Visit [drop.erikraft.com](https://drop.erikraft.com/) 2. Click on the share icon 3. Click *Add to Home Screen* 4. Click *Add* in the top right corner
**Self-Hosted Instance?** \ To be able to install the PWA from a self-hosted instance, the connection needs to be [established through HTTPS](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Installable_PWAs). See [this host your own section](https://github.com/schlagmichdoch/ErikrafTDrop/blob/master/docs/host-your-own.md#testing-pwa-related-features) for more info.
Shortcuts?
Available shortcuts: * Send a message with `CTRL + ENTER` * Close all "Send" and "Pair" dialogs by pressing `Esc`. * Copy a received message to the clipboard with `CTRL/⌘ + C`. * Accept file-transfer requests with `Enter` and decline with `Esc`.
How to save images directly to the gallery on iOS?
~~Apparently, iOS does not allow images shared from a website to be saved to the gallery directly.~~ ~~It simply does not offer that option for images shared from a website.~~ iOS Shortcuts saves the day: I created the official iOS shortcut for ErikrafT Drop, designed to let you easily share photos, files, and text directly from the iOS share menu using ErikrafT Drop:
[https://routinehub.co/shortcut/24753/](https://routinehub.co/shortcut/24753/)
(Official ErikrafT Drop Shortcut) Update: \ Apparently, this was only a bug that is fixed in recent iOS version ([https://github.com/WebKit/WebKit/pull/13111](https://github.com/WebKit/WebKit/pull/13111)). \ If you use an older affected iOS version this might still be of use. \ Luckily, you can now simply use `Save Image`/`Save X Images` 🎉
Is it possible to send files or text directly from the "Context" or "Share" menu?
Yes, it finally is. * [Send files directly from the "Context" menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) * [Send directly from the "Share" menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) * [Send directly from the "Share" menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android)
Is it possible to send files or text directly via CLI?
Yes. * [Send directly from a command-line interface](/docs/how-to.md#send-directly-via-command-line-interface)
Posso enviar arquivos pelo Bot do Discord?
Sim! O repositório inclui um bot de exemplo em `Discord/Bot` que usa o fallback WebSocket do ErikrafT Drop. 1. No site do ErikrafT Drop, abra o menu **Parear Dispositivo** e gere uma chave de 6 dígitos. 2. No Discord, execute o comando `/drop`, informe a chave e anexe os arquivos desejados. 3. O bot baixa os anexos, conecta-se ao servidor de sinalização como `client_type=discord-bot` e envia a solicitação de transferência. 4. Assim que o destinatário aceitar no site, os arquivos são transmitidos em tempo real e aparecem na interface web com o ícone do Discord. > Observação: a instância do ErikrafT Drop precisa ter o fallback WebSocket habilitado (`wsFallback: true`). A instância pública oficial já vem preparada para isso.
OFFICIAL ErikrafT Drop Apps!
Extension, App, and ErikrafT Drop OFFICIAL Website: 1. [ErikrafT Drop](https://github.com/erikraft/Drop) 2. [ErikrafT Drop Android App](https://github.com/erikraft/Drop-Android) 3. [ErikrafT Drop Extension](https://github.com/erikraft/Drop/tree/master/Browser%20Extension) 4. [ErikrafT Drop Extension VS Code](https://github.com/erikraft/Drop/tree/master/VS%20Code%20Extension)
What about the connection? Is it a P2P connection directly from device to device or is there any third-party-server?
It uses a WebRTC peer-to-peer connection. WebRTC needs a signaling server that is only used to establish a connection. The server is not involved in the file transfer. If the devices are on the same network, none of your files are ever sent to any server. If your devices are paired and behind a NAT, the ErikrafT Drop TURN Server is used to route your files and messages. See the [Technical Documentation](technical-documentation.md#encryption-webrtc-stun-and-turn) to learn more about STUN, TURN and WebRTC. If you host your own instance and want to support devices that do not support WebRTC, you can [start the ErikrafT Drop instance with an activated WebSocket fallback](https://github.com/erikraft/Drop/blob/master/docs/host-your-own.md#websocket-fallback-for-vpn).
What about privacy? Will files be saved on third-party servers?
Files are sent directly between peers. ErikrafT Drop doesn't even use a database. If curious, study [the signaling server](https://github.com/erikraft/Drop/blob/master/server/ws-server.js). WebRTC encrypts the files in transit. If the devices are on the same network, none of your files are ever sent to any server. If your devices are paired and behind a NAT, the ErikrafT Drop TURN Server is used to route your files and messages. See the [Technical Documentation](technical-documentation.md#encryption-webrtc-stun-and-turn) to learn more about STUN, TURN and WebRTC.
What about security? Are my files encrypted while sent between the computers?
Yes. Your files are sent using WebRTC, encrypting them in transit. Still you have to trust the ErikrafT Drop server. To ensure the connection is secure and there is no [MITM](https://en.m.wikipedia.org/wiki/Man-in-the-middle_attack) there is a plan to make ErikrafT Drop zero trust by encrypting the signaling and implementing a verification process. See [issue #180](https://github.com/schlagmichdoch/PairDrop/issues/180) to keep updated.
Transferring many files with paired devices takes too long
Naturally, if traffic needs to be routed through the TURN server because your devices are behind different NATs, transfer speed decreases. You can open a hotspot on one of your devices to bridge the connection, which omits the need of the TURN server. * [How to open a hotspot on Windows](https://support.microsoft.com/en-us/windows/use-your-windows-pc-as-a-mobile-hotspot-c89b0fad-72d5-41e8-f7ea-406ad9036b85#WindowsVersion=Windows_11) * [How to open a hotspot on macOS](https://support.apple.com/guide/mac-help/share-internet-connection-mac-network-users-mchlp1540/mac) * [Library to open a hotspot on Linux](https://github.com/lakinduakash/linux-wifi-hotspot) You can also use mobile hotspots on phones to do that. Then, all data should be sent directly between devices and not use your data plan.
Why don't you implement feature xyz?
Snapdrop and ErikrafT Drop are a study in radical simplicity. The user interface is insanely simple. Features are chosen very carefully because complexity grows quadratically since every feature potentially interferes with each other feature. We focus very narrowly on a single use case: instant file transfer. Not facilitating optimal edge-cases means better flow for average users. Don't be sad. We may decline your feature request for the sake of simplicity. Read *Insanely Simple: The Obsession that Drives Apple's Success*, and/or *Thinking, Fast and Slow* to learn more.
ErikrafT Drop is awesome. How can I support it?
* [Donation](https://www.paypal.com/donate/?business=QKLABC97EXJSN\&no_recurring=0\&item_name=ErikrafT\¤cy_code=BRL) to pay for the domain and the server, and support libre software. * [File bugs, give feedback, submit suggestions](https://github.com/erikraft/Drop/issues) * Share ErikrafT Drop on social media. * Fix bugs and create a pull request. * Do some security analysis and make suggestions. * Participate in [active discussions](https://github.com/erikraft/Drop/discussions)
How does it work?
[See here for info about the technical implementation](/docs/technical-documentation.md)
*** ## 🌍 Help with Translation Want to help make ErikrafT Drop available in more languages? You can contribute to the translation efforts at: [**https://crowdin.com/project/erikraft-drop**](https://crowdin.com/project/erikraft-drop) Join our community of translators and help bring ErikrafT Drop to users around the world! # Host Your Own Source: https://docsdrop.erikraft.com/reference/host-your-own Complete guide to deploying and hosting your own ErikrafT Drop instance # Deployment Notes ## TURN server for Internet Transfer Beware that you have to host your own TURN server to enable transfers between different networks. Follow [this guide](https://gabrieltanner.org/blog/turn-server/) to either install coturn directly on your system (Step 1) or deploy it via Docker (Step 5). You can use the `docker-compose-coturn.yml` in this repository. See [Coturn and ErikrafT Drop via Docker Compose](#coturn-and-pairdrop-via-docker-compose). Alternatively, use a free, pre-configured TURN server like [OpenRelay](https://www.metered.ca/tools/openrelay/)
## ErikrafT Drop via HTTPS On some browsers ErikrafT Drop must be served over TLS in order for some features to work properly. These may include: * Copying an incoming message via the 'copy' button * Installing ErikrafT Drop as PWA * Persistent pairing of devices * Changing of the display name * Notifications Naturally, this is also recommended to increase security.
## Deployment with Docker The easiest way to get ErikrafT Drop up and running is by using Docker. ### Docker Image from Docker Hub ```bash theme={null} docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 lscr.io/linuxserver/pairdrop ``` > ⚠️ **This is a third-party community image** hosted by [linuxserver.io](https://linuxserver.io). This is based on PairDrop (a similar but unofficial project), not the official ErikrafT Drop. For more information visit [https://hub.docker.com/r/linuxserver/pairdrop](https://hub.docker.com/r/linuxserver/pairdrop) > > **For official ErikrafT Drop images, build from source using the Dockerfile below.**
### Docker Image from GitHub Container Registry (ghcr.io) ```bash theme={null} docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 ghcr.io/schlagmichdoch/pairdrop ``` > ⚠️ **This is the non-official PairDrop image** from the original PairDrop project. This is based on PairDrop (a similar but unofficial project), not the official ErikrafT Drop.
### Docker Image self-built #### Build the image ```bash theme={null} docker build --pull . -f Dockerfile -t pairdrop ``` > A GitHub action is set up to do this step automatically at the release of new versions. > > `--pull` ensures always the latest node image is used. #### Run the image ```bash theme={null} docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 -it pairdrop ``` > You must use a server proxy to set the `X-Forwarded-For` header to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > To prevent bypassing the proxy by reaching the docker container directly, `127.0.0.1` is specified in the run command.
### Flags Set options by using the following flags in the `docker run` command: #### Port ```bash theme={null} -p 127.0.0.1:8080:3000 ``` > Specify the port used by the docker image > > * 3000 -> `-p 127.0.0.1:3000:3000` > * 8080 -> `-p 127.0.0.1:8080:3000` #### Set Environment Variables via Docker Environment Variables are set directly in the `docker run` command: \ e.g. `docker run -p 127.0.0.1:3000:3000 -it pairdrop -e DEBUG_MODE="true"` Overview of available Environment Variables are found [here](#environment-variables). Example: ```bash theme={null} docker run -d \ --name=pairdrop \ --restart=unless-stopped \ -p 127.0.0.1:3000:3000 \ -e PUID=1000 \ -e PGID=1000 \ -e WS_SERVER=false \ -e WS_FALLBACK=false \ -e RTC_CONFIG=false \ -e RATE_LIMIT=false \ -e DEBUG_MODE=false \ -e TZ=Etc/UTC \ lscr.io/linuxserver/pairdrop ```
## Deployment with Docker Compose Here's an example docker compose file: ```yaml theme={null} version: "3" services: pairdrop: image: "lscr.io/linuxserver/pairdrop:latest" container_name: pairdrop restart: unless-stopped environment: - PUID=1000 # UID to run the application as - PGID=1000 # GID to run the application as - WS_FALLBACK=false # Set to true to enable websocket fallback if the peer to peer WebRTC connection is not available to the client. - RATE_LIMIT=false # Set to true to limit clients to 1000 requests per 5 min. - RTC_CONFIG=false # Set to the path of a file that specifies the STUN/TURN servers. - DEBUG_MODE=false # Set to true to debug container and peer connections. - TZ=Etc/UTC # Time Zone ports: - "127.0.0.1:3000:3000" # Web UI ``` Run the compose file with `docker compose up -d`. > You must use a server proxy to set the `X-Forwarded-For` header to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > To prevent bypassing the proxy by reaching the Docker container directly, `127.0.0.1` is specified in the `ports` argument.
## Deployment with Node.js Clone this repository and enter the folder ```bash theme={null} git clone https://github.com/erikraft/Drop.git && cd Drop ``` Install all dependencies with NPM: ```bash theme={null} npm install ``` Start the server with: ```bash theme={null} npm start ``` > By default, the node server listens on port 3000.
### Options / Flags These are some flags only reasonable when deploying via Node.js #### Port ```bash theme={null} PORT=3000 ``` > Default: `3000` > > Environment variable to specify the port used by the Node.js server \ > e.g. `PORT=3010 npm start` #### Local Run ```bash theme={null} npm start -- --localhost-only ``` > Only allow connections from localhost. > > You must use a server proxy to set the `X-Forwarded-For` header to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > Use this when deploying ErikrafT Drop with node to prevent bypassing the reverse proxy by reaching the Node.js server directly. #### Automatic restart on error ```bash theme={null} npm start -- --auto-restart ``` > Restarts server automatically on error #### Production (autostart and rate-limit) ```bash theme={null} npm run start:prod ``` > shortcut for `RATE_LIMIT=5 npm start -- --auto-restart` #### Production (autostart, rate-limit, localhost-only) ```bash theme={null} npm run start:prod -- --localhost-only ``` > To prevent connections to the node server from bypassing \ > the proxy server you should always use "--localhost-only" on production. #### Set Environment Variables via Node.js To specify environment variables set them in the run command in front of `npm start`. The syntax is different on Unix and Windows. On Unix based systems ```bash theme={null} PORT=3000 RTC_CONFIG="rtc_config.json" npm start ``` On Windows ```bash theme={null} $env:PORT=3000 RTC_CONFIG="rtc_config.json"; npm start ``` Overview of available Environment Variables are found [here](#environment-variables).
## Environment Variables ### Debug Mode ```bash theme={null} DEBUG_MODE="true" ``` > Default: `false` > > Logs the used environment variables for debugging. > > Prints debugging information about the connecting peers IP addresses. > > This is quite useful to check whether the [#HTTP-Server](#http-server) is configured correctly, so the auto-discovery feature works correctly. Otherwise, all clients discover each other mutually, independently of their network status. > > If this flag is set to `"true"` each peer that connects to the ErikrafT Drop server will produce a log to STDOUT like this: > > ``` > ----DEBUGGING-PEER-IP-START---- > remoteAddress: ::ffff:172.17.0.1 > x-forwarded-for: 19.117.63.126 > cf-connecting-ip: undefined > ErikrafT Drop uses: 19.117.63.126 > IP is private: false > if IP is private, '127.0.0.1' is used instead > ----DEBUGGING-PEER-IP-END---- > ``` > > If the IP address "ErikrafT Drop uses" matches the public IP address of the client device, everything is set up correctly. \ > To find out the public IP address of the client device visit [https://whatsmyip.com/](https://whatsmyip.com/). > > To preserve your clients' privacy: \ > **Never use this environment variable in production!**
### Rate limiting requests ```bash theme={null} RATE_LIMIT=1 ``` > Default: `false` > > Limits clients to 1000 requests per 5 min > > "If you are behind a proxy/load balancer (usually the case with most hosting services, e.g. Heroku, Bluemix, AWS ELB, Render, Nginx, Cloudflare, Akamai, Fastly, Firebase Hosting, Rackspace LB, Riverbed Stingray, etc.), the IP address of the request might be the IP of the load balancer/reverse proxy (making the rate limiter effectively a global one and blocking all requests once the limit is reached) or undefined." (See: [https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues](https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues)) > > To find the correct number to use for this setting: > > 1. Start ErikrafT Drop with `DEBUG_MODE=True` and `RATE_LIMIT=1` > 2. Make a `get` request to `/ip` of the ErikrafT Drop instance (e.g. `https://pairdrop-example.net/ip`) > 3. Check if the IP address returned in the response matches your public IP address (find out by visiting e.g. [https://whatsmyip.com/](https://whatsmyip.com/)) > 4. You have found the correct number if the IP addresses match. If not, then increase `RATE_LIMIT` by one and redo 1. - 4. > > e.g. on Render you must use RATE\_LIMIT=5
### IPv6 Localization ```bash theme={null} IPV6_LOCALIZE=4 ``` > Default: `false` > > To enable Peer Auto-Discovery among IPv6 peers, you can specify a reduced number of segments \ > of the client IPv6 address to be evaluated as the peer's IP. \ > This can be especially useful when using Cloudflare as a proxy. > > The flag must be set to an **integer** between `1` and `7`. \ > The number represents the number of IPv6 [hextets](https://en.wikipedia.org/wiki/IPv6#Address_representation) \ > to match the client IP against. The most common value would be `4`, \ > which will group peers within the same `/64` subnet.
### Websocket Fallback (for VPN) ```bash theme={null} WS_FALLBACK=true ``` > Default: `false` > > Provides ErikrafT Drop to clients with an included websocket fallback \ > if the peer to peer WebRTC connection is not available to the client. > > This is not used on the official [https://pairdrop.net](https://pairdrop.net) website, but you can activate it on your self-hosted instance.\ > This is especially useful if you connect to your instance via a VPN (as most VPN services block WebRTC completely in order to hide your real IP address). ([Read more here](https://privacysavvy.com/security/safe-browsing/disable-webrtc-chrome-firefox-safari-opera-edge/)). > > **Warning:** \ > All traffic sent between devices using this fallback is routed through the server and therefor not peer to peer! > > Beware that the traffic routed via this fallback is readable by the server. \ > Only ever use this on instances you can trust. > > Additionally, beware that all traffic using this fallback debits the servers data plan.
### Specify STUN/TURN Servers ```bash theme={null} RTC_CONFIG="rtc_config.json" ``` > Default: `false` > > Specify the STUN/TURN servers ErikrafT Drop clients use by setting \ > `RTC_CONFIG` to a JSON file including the configuration. \ > You can use `rtc_config_example.json` as a starting point. > > To host your own TURN server you can follow this guide: [https://gabrieltanner.org/blog/turn-server/](https://gabrieltanner.org/blog/turn-server/) Alternatively, use a free, pre-configured TURN server like [OpenRelay](https://www.metered.ca/tools/openrelay/) > > Default configuration: > > ```json theme={null} > { > "sdpSemantics": "unified-plan", > "iceServers": [ > { > "urls": "stun:stun.l.google.com:19302" > } > ] > } > ```
You can host an instance that uses another signaling server This can be useful if you don't want to trust the client files that are hosted on another instance but still want to connect to devices that use [https://pairdrop.net](https://pairdrop.net). ### Specify Signaling Server ```bash theme={null} SIGNALING_SERVER="pairdrop.net" ``` > Default: `false` > > By default, clients connecting to your instance use the signaling server of your instance to connect to other devices. > > By using `SIGNALING_SERVER`, you can host an instance that uses another signaling server. > > This can be useful if you want to ensure the integrity of the client files and don't want to trust the client files that are hosted on another ErikrafT Drop instance but still want to connect to devices that use the other instance. E.g. host your own client files under *pairdrop.your-domain.com* but use the official signaling server under *pairdrop.net* This way devices connecting to *pairdrop.your-domain.com* and *pairdrop.net* can discover each other. > > Beware that the version of your ErikrafT Drop server must be compatible with the version of the signaling server. > > `SIGNALING_SERVER` must be a valid url without the protocol prefix. Examples of valid values: `pairdrop.net`, `pairdrop.your-domain.com:3000`, `your-domain.com/pairdrop`
### Customizable buttons for the *About ErikrafT Drop* page ```bash theme={null} DONATION_BUTTON_ACTIVE=true DONATION_BUTTON_LINK="https://ko-fi.com/erikraft" DONATION_BUTTON_TITLE="Buy me a coffee" TWITTER_BUTTON_ACTIVE=true TWITTER_BUTTON_LINK="https://twitter.com/account" TWITTER_BUTTON_TITLE="Find me on Twitter" MASTODON_BUTTON_ACTIVE=true MASTODON_BUTTON_LINK="https://mastodon.social/account" MASTODON_BUTTON_TITLE="Find me on Mastodon" BLUESKY_BUTTON_ACTIVE=true BLUESKY_BUTTON_LINK="https://bsky.app/profile/account" BLUESKY_BUTTON_TITLE="Find me on Bluesky" CUSTOM_BUTTON_ACTIVE=true CUSTOM_BUTTON_LINK="https://your-custom-social-network.net/account" CUSTOM_BUTTON_TITLE="Find me on this custom social network" PRIVACYPOLICY_BUTTON_ACTIVE=true PRIVACYPOLICY_BUTTON_LINK="https://link-to-your-privacy-policy.net" PRIVACYPOLICY_BUTTON_TITLE="Open our privacy policy" ``` > Default: unset > > By default, clients will show the default button configuration: GitHub, BuyMeACoffee, Twitter, and FAQ on GitHub. > > The GitHub and FAQ on GitHub buttons are essential, so they are always shown. > > The other buttons can be customized: > > * `*_BUTTON_ACTIVE`: set this to `true` to show a natively hidden button or to `false` to hide a normally shown button > * `*_BUTTON_LINK`: set this to any URL to overwrite the href attribute of the button > * `*_BUTTON_TITLE`: set this to overwrite the hover title of the button. This will prevent the title from being translated.
## Healthcheck > The Docker Image hosted on `ghcr.io` and the self-built Docker Image include a healthcheck. > > Read more about [Docker Swarm Usage](docker-swarm-usage.md#docker-swarm-usage).
## HTTP-Server When running ErikrafT Drop, the `X-Forwarded-For` header has to be set by a proxy. \ Otherwise, all clients will be mutually visible. To check if your setup is configured correctly [`use the environment variable DEBUG_MODE="true"`](#debug-mode). ### Using nginx #### Allow http and https requests ``` server { listen 80; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } server { listen 443 ssl http2; ssl_certificate /etc/ssl/certs/pairdrop-dev.crt; ssl_certificate_key /etc/ssl/certs/pairdrop-dev.key; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } ``` #### Automatic http to https redirect: ``` server { listen 80; expires epoch; location / { return 301 https://$host:3000$request_uri; } } server { listen 443 ssl http2; ssl_certificate /etc/ssl/certs/pairdrop-dev.crt; ssl_certificate_key /etc/ssl/certs/pairdrop-dev.key; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } ```
### Using Apache install modules `proxy`, `proxy_http`, `mod_proxy_wstunnel` ```bash theme={null} a2enmod proxy ``` ```bash theme={null} a2enmod proxy_http ```
Create a new configuration file under `/etc/apache2/sites-available` (on Debian) **pairdrop.conf** #### Allow HTTP and HTTPS requests ```apacheconf theme={null} ProxyPass / http://127.0.0.1:3000/ upgrade=websocket ProxyPass / https://127.0.0.1:3000/ upgrade=websocket ``` #### Automatic HTTP to HTTPS redirect: ```apacheconf theme={null} Redirect permanent / https://127.0.0.1:3000/ ProxyPass / http://127.0.0.1:3000/ upgrade=websocket ``` Activate the new virtual host and reload Apache: ```bash theme={null} a2ensite pairdrop ``` ```bash theme={null} service apache2 reload ```
## Coturn and ErikrafT Drop via Docker Compose ### Setup container To run coturn and ErikrafT Drop at once by using the `docker-compose-coturn.yml` with TURN over TLS enabled you need to follow these steps: 1. Generate or retrieve certificates for your `` (e.g. letsencrypt / certbot) 2. Create `./ssl` folder: `mkdir ssl` 3. Copy your ssl-certificates and the privkey to `./ssl` 4. Restrict access to `./ssl`: `chown -R nobody:nogroup ./ssl` 5. Create a dh-params file: `openssl dhparam -out ./ssl/dhparams.pem 4096` 6. Copy `rtc_config_example.json` to `rtc_config.json` 7. Copy `turnserver_example.conf` to `turnserver.conf` 8. Change `` in both files to the domain where your ErikrafT Drop instance is running 9. Change `username` and `password` in `turnserver.conf` and `rtc-config.json` 10. To start the container including coturn run: \ `docker compose -f docker-compose-coturn.yml up -d`
#### Setup container To restart the container including coturn run: \ `docker compose -f docker-compose-coturn.yml restart`
#### Setup container To stop the container including coturn run: \ `docker compose -f docker-compose-coturn.yml stop`
### Firewall To run ErikrafT Drop including its own coturn-server you need to punch holes in the firewall. These ports must be opened additionally: * 3478 tcp/udp * 5349 tcp/udp * 10000:20000 tcp/udp
## Local Development ### Install All files needed for developing are available in the folder `./dev`. For convenience, there is also a docker compose file for developing: #### Developing with docker compose First, [Install docker with docker compose.](https://docs.docker.com/compose/install/) Then, clone the repository and run docker compose: ```bash theme={null} git clone https://github.com/erikraft/Drop.git && cd Drop ``` ```bash theme={null} docker compose -f docker-compose-dev.yml up --no-deps --build ``` Now point your web browser to `http://localhost:8080`. * To debug the Node.js server, run `docker logs pairdrop`. * After changes to the code you have to rerun the `docker compose` command
#### Testing PWA related features PWAs requires the app to be served under a correctly set up and trusted TLS endpoint. The NGINX container creates a CA certificate and a website certificate for you. To correctly set the common name of the certificate, you need to change the FQDN environment variable in `docker-compose-dev.yml` to the fully qualified domain name of your workstation. (Default: localhost) If you want to test PWA features, you need to trust the CA of the certificate for your local deployment. \ For your convenience, you can download the crt file from `http://:8080/ca.crt`. \ Install that certificate to the trust store of your operating system. \\ ##### Windows * Make sure to install it to the `Trusted Root Certification Authorities` store. ##### macOS * Double-click the installed CA certificate in `Keychain Access`, * expand `Trust`, and select `Always Trust` for SSL. ##### Firefox Firefox uses its own trust store. To install the CA: * point Firefox at `http://:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`) * When prompted, select `Trust this CA to identify websites` and click *OK*. Alternatively: 1. Download `ca.crt` from `http://:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`) 2. Go to `about:preferences#privacy` scroll down to `Security` and `Certificates` and click `View Certificates` 3. Import the downloaded certificate file (step 1) ##### Chrome * When using Chrome, you need to restart Chrome so it reloads the trust store (`chrome://restart`). * Additionally, after installing a new cert, you need to clear the Storage (DevTools → Application → Clear storage → Clear site data). ##### Google Chrome * To skip the installation of the certificate, you can also open `chrome://flags/#unsafely-treat-insecure-origin-as-secure` * The feature `Insecure origins treated as secure` must be enabled and the list must include your ErikrafT Drop test instance. E.g.: `http://127.0.0.1:3000,https://127.0.0.1:8443` Please note that the certificates (CA and webserver cert) expire after a day. Also, whenever you restart the NGINX Docker container new certificates are created. The site is served on `https://:8443` (Default: `https://localhost:8443`). # How-To Guides Source: https://docsdrop.erikraft.com/reference/how-to Step-by-step guides for using ErikrafT Drop on different platforms # How-To ## Send directly from share menu on iOS I created a shortcut on iOS to send images, files, folders, URLs, or text directly from the share menu. To download, go to the link: [https://routinehub.co/shortcut/24753/](https://routinehub.co/shortcut/24753/) or [https://www.icloud.com/shortcuts/f81dbac00823445e8feefd0f834b40e7](https://www.icloud.com/shortcuts/f81dbac00823445e8feefd0f834b40e7) [//]: # "Todo: Add screenshots"
## Send directly from share menu on Android The [Web Share Target API](https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target) is implemented. When the PWA is installed, it will register itself to the share-menu of the device automatically.
## Send directly via command-line interface Send files or text with ErikrafT Drop via command-line interface. \ This opens ErikrafT Drop in the default browser where you can choose the receiver. ### Usage ```bash theme={null} erikraftdrop -h ``` ``` Send files or text with ErikrafT Drop via command-line interface. Current domain: https://drop.erikraft.com/ Usage: Open ErikrafT Drop: erikraftdrop Send files: erikraftdrop file1/directory1 (file2/directory2 file3/directory3 ...) Send text: erikraftdrop -t "text" Specify domain: erikraftdrop -d "https://drop.erikraft.com/" Show this help text: erikraftdrop (-h|--help) This erikraftdrop-cli version was released alongside v1.10.4 ```
### Setup #### Linux / Mac 1. Download the latest *erikraftdrop-cli.zip* from the [releases page](https://github.com/erikraft/Drop/releases/) ```shell theme={null} wget "https://github.com/erikraft/Drop/releases/download/v1.12.4/erikraftdrop-cli.zip" ``` or ```shell theme={null} curl -LO "https://github.com/erikraft/Drop/releases/download/v1.12.4/erikraftdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/erikraftdrop-cli/` ```shell theme={null} sudo unzip erikraftdrop-cli.zip -d /usr/share/erikraftdrop-cli/ ``` 3. Copy the file *.erikraftdrop-cli-config.example* to *.erikraftdrop-cli-config* ```shell theme={null} sudo cp /usr/share/erikraftdrop-cli/.erikraftdrop-cli-config.example /usr/share/erikraftdrop-cli/.erikraftdrop-cli-config ``` 4. Make the bash file *erikraftdrop* executable ```shell theme={null} sudo chmod +x /usr/share/erikraftdrop-cli/erikraftdrop ``` 5. Add a symlink to /usr/local/bin/ to include *erikraftdrop* to *PATH* ```shell theme={null} sudo ln -s /usr/share/erikraftdrop-cli/erikraftdrop /usr/local/bin/erikraftdrop ```
#### Windows 1. Download the latest *erikraftdrop-cli.zip* from the [releases page](https://github.com/schlagmichdoch/ErikrafTDrop/releases) 2. Put file in a preferred folder e.g. `C:\Program Files\erikraftdrop-cli` 3. Inside this folder, copy the file *.erikraftdrop-cli-config.example* to *.erikraftdrop-cli-config* 4. Search for and open `Edit environment variables for your account` 5. Click `Environment Variables…` 6. Under *System Variables* select `Path` and click *Edit...* 7. Click *New*, insert the preferred folder (`C:\Program Files\erikraftdrop-cli`), click *OK* until all windows are closed 8. Reopen Command prompt window **Requirements** As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/). Then, you can also use erikraftdrop-cli from the default Windows Command Prompt by using the shell file instead of the bash file which then itself executes *erikraftdrop-cli* (the bash file) via the Git Bash. ```shell theme={null} erikraftdrop.sh -h ```
## Send multiple files and directories directly from context menu on Windows ### Registering to open files with ErikrafT Drop It is possible to send multiple files with ErikrafT Drop via the context menu by adding erikraftdrop-cli to Windows `Send to` menu: 1. Download the latest *erikraftdrop-cli.zip* from the [releases page](https://github.com/erikraft/Drop/releases/) 2. Unzip the archive to a folder of your choice e.g. `C:\Program Files\erikraftdrop-cli\` 3. Inside this folder, copy the file *.erikraftdrop-cli-config.example* to *.erikraftdrop-cli-config* 4. Copy the shortcut *send with ErikrafT Drop.lnk* 5. Hit Windows Key+R, type: `shell:sendto` and hit Enter. 6. Paste the copied shortcut into the directory 7. Open the properties window of the shortcut and edit the link field to point to *send-with-erikraftdrop.ps1* located in the folder you used in step 2: \ `"C:\Program Files\PowerShell\7\pwsh.exe" -File "C:\Program Files\erikraftdrop-cli\send-with-erikraftdrop.ps1"` 8. You are done! You can now send multiple files and directories directly via ErikrafT Drop: *context menu* > *Send to* > *ErikrafT Drop* ##### Requirements As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/).
## Send multiple files and directories directly from context menu on Ubuntu using Nautilus ### Registering to open files with ErikrafT Drop It is possible to send multiple files with ErikrafT Drop via the context menu by adding erikraftdrop-cli to Nautilus `Scripts` menu: 1. Register *erikraftdrop* as executable via [guide above](#linux). 2. Copy the shell file *send-with-erikraftdrop* to `~/.local/share/nautilus/scripts/` to include it in the context menu ```shell theme={null} cp /usr/share/erikraftdrop-cli/send-with-erikraftdrop ~/.local/share/nautilus/scripts/ ``` 3. Make the shell file *send-with-erikraftdrop* executable ```shell theme={null} chmod +x ~/.local/share/nautilus/scripts/send-with-erikraftdrop ``` 4. You are done! You can now send multiple files and directories directly via ErikrafT Drop: *context menu* > *Scripts* > *send-with-erikraftdrop*
## File Handling API The [File Handling API](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files) was implemented, but it was removed as default file associations were overwritten ([#17](https://github.com/schlagmichdoch/PairDrop/issues/17), [#116](https://github.com/schlagmichdoch/PairDrop/issues/116) [#190](https://github.com/schlagmichdoch/PairDrop/issues/190)) and it only worked with explicitly specified file types and couldn't handle directories at all. # Project Structure Source: https://docsdrop.erikraft.com/reference/project-structure Complete overview of ErikrafT Drop's file structure, organization, and key components. # Project Structure ErikrafT Drop follows a well-organized structure separating client-side and server-side components, with clear separation of concerns for maintainability and scalability. ## Root Directory Structure ``` Drop/ ├── public/ # Client-side application ├── server/ # Server-side application ├── docs/ # Documentation ├── scripts/ # Build and utility scripts ├── Android/ # Android application ├── Extensions/ # Browser extensions ├── Discord/ # Discord bot/activity ├── erikraftdrop-cli/ # Command-line interface ├── Shortcut/ # iOS shortcut ├── Website About/ # Website assets ├── package.json # Node.js dependencies ├── server.js # Main server entry point ├── docker-compose.yml # Docker configuration └── README.md # Project documentation ``` ## Client-Side Structure (`public/`) ### Main Application Files ``` public/ ├── index.html # Main application entry point ├── manifest.json # PWA manifest ├── service-worker.js # PWA service worker ├── styles/ # CSS stylesheets ├── scripts/ # JavaScript modules ├── images/ # Image assets ├── fonts/ # Font files ├── sounds/ # Audio files ├── lang/ # Localization files └── .well-known/ # Web app configuration ``` ### JavaScript Modules (`public/scripts/`) ``` scripts/ ├── main.js # Main application controller ├── network.js # WebRTC and networking logic ├── ui.js # User interface components ├── ui-main.js # Main UI controller ├── util.js # Utility functions ├── localization.js # Internationalization ├── persistent-storage.js # IndexedDB management ├── browser-tabs-connector.js # Cross-tab communication ├── content-moderation.js # Content filtering ├── ai-image-client.js # AI image processing ├── photopea-integration.js # Image editing integration └── worker/ # Web Workers └── crypto-worker.js # Cryptographic operations ``` ### Stylesheets (`public/styles/`) ``` styles/ ├── styles.css # Main stylesheet ├── styles-deferred.css # Lazy-loaded styles └── fonts.css # Font definitions ``` ### Localization (`public/lang/`) ``` lang/ ├── en.json # English translations ├── de.json # German translations ├── fr.json # French translations ├── es.json # Spanish translations ├── it.json # Italian translations ├── pt.json # Portuguese translations ├── ru.json # Russian translations ├── zh-CN.json # Chinese (Simplified) translations └── ja.json # Japanese translations ``` ## Server-Side Structure (`server/`) ### Main Server Files ``` server/ ├── index.js # Main server application ├── server.js # HTTP server setup ├── ws-server.js # WebSocket server implementation ├── peer.js # Peer connection management ├── helper.js # Utility functions ├── proxy-server.js # Reverse proxy functionality └── services/ # Additional services ├── ai-image.js # AI image processing └── shardcloud.js # Cloud storage integration ``` ### Data Models (`server/model/`) ``` model/ └── room-secrets.js # Room secret management ``` ## Key Components ### Client-Side Architecture #### Main Application (`public/scripts/main.js`) ```javascript theme={null} class ErikrafTdrop { constructor() { this.$headerNotificationBtn = $('notification'); this.$headerEditPairedDevicesBtn = $('edit-paired-devices'); this.$footerPairedDevicesBadge = $$('.discovery-wrapper .badge-room-secret'); this.$chatFooterPairedDevicesBadge = $$('#chat-panel .badge-room-secret'); this.$headerInstallBtn = $('install'); this.deferredStyles = [ "styles/styles-deferred.css" ]; this.deferredScripts = [ "scripts/browser-tabs-connector.js", "scripts/util.js", "scripts/network.js", "scripts/ai-image-client.js", "scripts/ui.js", "scripts/libs/heic2any.min.js", "scripts/libs/no-sleep.min.js", "scripts/libs/qr-code.min.js", "scripts/libs/zip.min.js", "scripts/content-moderation.js" ]; } } ``` #### Network Layer (`public/scripts/network.js`) ```javascript theme={null} // Key classes for networking class ServerConnection // WebSocket connection management class RTCPeer // WebRTC peer implementation class WSPeer // WebSocket fallback peer class PeersManager // Peer connection management class FileChunker // File chunking for transfer class FileDigester // File reassembly ``` #### UI Components (`public/scripts/ui.js`) ```javascript theme={null} // UI component classes class PairDeviceDialog // Device pairing interface class EditPairedDevicesDialog // Paired devices management class ReceiveFileDialog // File reception interface class SendFileDialog // File sending interface class Dialog // Base dialog component ``` ### Server-Side Architecture #### WebSocket Server (`server/ws-server.js`) ```javascript theme={null} export default class ErikrafTdropWsServer { constructor(server, conf) { this._conf = conf; this._rooms = {}; // Room management this._roomSecrets = {}; // Pairing secrets this._keepAliveTimers = {}; // Connection monitoring this._wss = new WebSocketServer({ server }); } } ``` #### Peer Management (`server/peer.js`) ```javascript theme={null} export default class Peer { constructor(socket, request, conf) { this.socket = socket; this.ip = this._setIP(request); this.id = this._setPeerId(request); this.rtcSupported = this._setRtcSupported(request); this.name = this._setName(request); this.roomSecrets = []; this.pairKey = null; } } ``` ## Configuration Files ### Package Configuration (`package.json`) ```json theme={null} { "name": "erikraft-drop", "version": "1.12.4", "type": "module", "description": "A maneira mais fácil de transferir arquivos entre dispositivos", "main": "server/index.js", "scripts": { "start": "node server/index.js", "start:prod": "node server/index.js --rate-limit --auto-restart", "build": "npm install --omit=dev" }, "dependencies": { "body-parser": "^2.2.1", "dotenv": "^16.6.1", "express": "^5.2.1", "express-rate-limit": "^7.5.1", "http-proxy-middleware": "^3.0.5", "multer": "^2.0.1", "redis": "^4.6.11", "ua-parser-js": "^2.0.5", "undici": "^6.23.0", "unique-names-generator": "^4.7.1", "ws": "^8.18.2" }, "engines": { "node": ">=20.18.1" } } ``` ### Docker Configuration (`docker-compose.yml`) ```yaml theme={null} version: '3.8' services: erikraftdrop: build: . ports: - "3000:3000" environment: - NODE_ENV=production restart: unless-stopped ``` ### RTC Configuration (`rtc_config_example.json`) ```json theme={null} { "sdpSemantics": "unified-plan", "iceServers": [ { "urls": "stun:stun.l.google.com:19302" } ] } ``` ## Build and Deployment ### Development Setup ```bash theme={null} # Install dependencies npm install # Start development server npm run dev # Start with debugging DEBUG_MODE=true npm start ``` ### Production Deployment ```bash theme={null} # Build for production npm run build # Start production server npm run start:prod # Docker deployment docker-compose up -d ``` ### Environment Variables ```bash theme={null} # Server configuration PORT=3000 HOST=0.0.0.0 DEBUG_MODE=false # Rate limiting RATE_LIMIT=true # LAN mode ALLOW_LOCAL_ONLY=false # Redis (optional) REDIS_URL=redis://localhost:6379 ``` ## Extension and Integration Structure ### Browser Extensions (`Extensions/`) ``` Extensions/ ├── chrome/ # Chrome extension ├── firefox/ # Firefox extension ├── edge/ # Edge extension └── safari/ # Safari extension ``` ### Mobile Applications ``` Android/ # Android native app ├── app/ # Main application ├── gradle/ # Build configuration └── src/ # Source code Shortcut/ # iOS shortcut └── Send with ErikrafT Drop.shortcut ``` ### CLI Tool (`erikraftdrop-cli/`) ``` erikraftdrop-cli/ ├── erikraftdrop # Main bash script ├── erikraftdrop.sh # Windows shell script ├── send-with-erikraftdrop # Nautilus script ├── .erikraftdrop-cli-config.example # Configuration template └── README.md # CLI documentation ``` ## Testing and Quality Assurance ### Test Structure ``` tests/ ├── unit/ # Unit tests ├── integration/ # Integration tests ├── e2e/ # End-to-end tests └── performance/ # Performance tests ``` ### Code Quality Tools * **ESLint**: JavaScript linting * **Prettier**: Code formatting * **TypeScript**: Type checking (where applicable) * **Jest**: Unit testing framework * **Playwright**: E2E testing ## Documentation Structure ### Technical Documentation ``` docs/ ├── technical-documentation.md # Technical overview ├── how-to.md # Usage guides ├── host-your-own.md # Self-hosting guide ├── faq.md # Frequently asked questions ├── docker-swarm-usage.md # Docker deployment └── release-notes.md # Version changelog ``` ### API Documentation * **WebSocket API**: Real-time communication * **HTTP Endpoints**: Configuration and health checks * **WebRTC API**: Peer-to-peer communication * **IndexedDB API**: Client-side storage This project structure provides a solid foundation for development, deployment, and maintenance of the ErikrafT Drop file sharing system. # Technical Documentation Source: https://docsdrop.erikraft.com/reference/technical-documentation In-depth technical details about ErikrafT Drop's architecture and implementation # Technical Documentation ## Encryption, WebRTC, STUN and TURN Encryption is mandatory for WebRTC connections and completely done by the browser itself. When the peers are first connecting, \ a channel is created by exchanging their signaling info. \ This signaling information includes some sort of public key \ and is specific to the clients IP address. \ That is what the STUN Server is used for: \ it simply returns your public IP address \ as you only know your local ip address \ if behind a NAT (router). The transfer of the signaling info is done by the \ ErikrafT Drop / Snapdrop server using secure websockets. \ After that the channel itself is completely peer-to-peer \ and all info can only be decrypted by the receiver. \ When the two peers are on the same network \ or when they are not behind any NAT system \ (which they are always for classic \ Snapdrop and for not paired users on ErikrafT Drop) \ the files are send directly peer-to-peer. When a user is behind a NAT (behind a router) \ the contents are channeled through a TURN server. \ But again, the contents send via the channel \ can only be decrypted by the receiver. \ So a rogue TURN server could only \ see that there is a connection, but not what is sent. \ Obviously, connections which are channeled through a TURN server \ are not as fast as peer-to-peer. The selection whether a TURN server is needed \ or not is also done automatically by the web browser. \ It simply iterated through the configured \ RTC iceServers and checks what works. \ Only if the STUN server is not sufficient, \ the TURN server is used. img *Diagram created by wowza.com* Good thing: if your device has an IPv6 address \ it is uniquely reachable by that address. \ As I understand it, when both devices are using \ IPv6 addresses there is no need for a TURN server in any scenario. Learn more by reading [https://www.wowza.com/blog/webrtc-encryption-and-security](https://www.wowza.com/blog/webrtc-encryption-and-security) \ which gives a good insight into STUN, TURN and WebRTC. ## Device Pairing The pairing functionality uses the [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). It works by creating long secrets that are served \ by the server to the initiating and requesting pair peer, \ when the inserted key is correct. \ These long secrets are then saved to an \ indexedDB database in the web browser. \ IndexedDB is somewhat the successor of localStorage \ as saved data is shared between all tabs. \ It goes one step further by making the data persistent \ and available offline if implemented to a PWA. All secrets a client has saved to its database \ are sent to the ErikrafT Drop server. \ Peers with a common secret are discoverable \ to each other analog to peers with the same \ IP address are discoverable by each other. What I really like about this approach (and the reason I implemented it) \ is that devices on the same network are always \ visible regardless whether any devices are paired or not. \ The main user flow is never obstructed. \ Paired devices are simply shown additionally. \ This makes it in my idea better than the idea of \ using a room system as [discussed here](https://github.com/RobinLinus/snapdrop/pull/214). # Releases Source: https://docsdrop.erikraft.com/releases ### ✨ New * Chat agora suporta envio de imagens com preview e botão de download * Botão de upload de mídia (ícone de clipe) adicionado no chat * Indicadores de mensagens não lidas no título e favicon do navegador * Notificações do navegador para mensagens recebidas em background * Layout do rodapé do chat alinhado com o painel principal * Painel discovery do chat agora mais compacto ### 🛠 Improvements * Sistema de notificações do chat reorganizado e mais confiável * Lógica de notificações padronizada usando visibilityState * Melhor feedback visual para mensagens não lidas * UX consistente com o restante do app * Botão de download usa ícone em vez de texto * Ajustes de espaçamento e alinhamento do chat ### 🐛 Fixes * Corrigido problema onde notificações do chat não disparavam * Corrigido mensagens que não apareciam ao reabrir o chat * Upload de vídeo removido devido a falhas de envio ### 🐛 Fixes * Correções de bugs gerais ### 🛠 Improvements * Versão estável preparada para futuras melhorias ### 📱 Download * Google Play * F-Droid # SSL Architecture Source: https://docsdrop.erikraft.com/ssl-architecture # SSL and Secure Architecture ErikrafT Drop requires **secure connections** to operate correctly. All communication between clients and the signaling server is protected using **SSL/TLS**. Secure transport is mandatory for modern browsers when using **WebRTC** and **Secure WebSockets (WSS)**. Without HTTPS, device discovery and file transfer may fail or be blocked entirely. This page explains how SSL/TLS integrates into the ErikrafT Drop architecture. *** ## Why SSL is Required ErikrafT Drop depends on secure browser APIs that only work in **secure contexts**. SSL/TLS is required for: * Loading the application via HTTPS * Establishing Secure WebSocket connections (WSS) * WebRTC signaling * Device pairing * Secure file transfers Without SSL: * Browsers block WebRTC features * WebSocket connections may fail * Mixed-content errors occur * Device discovery becomes unreliable With SSL: * All connections are encrypted * WebRTC works correctly * WebSockets connect reliably * Signaling is protected * Transfers remain private *** ## Secure Communication Layers ErikrafT Drop uses multiple secure layers. ### HTTPS (TLS) HTTPS is used to: * Load the web application * Retrieve configuration * Access API endpoints Example: ``` https://drop.example.com ``` *** ### Secure WebSockets (WSS) Secure WebSockets are used for signaling between devices. Example: ``` wss://drop.example.com/server ``` WSS is responsible for: * Peer discovery * Device pairing * WebRTC signaling * Connection management The signaling server **does not store files**. *** ### WebRTC Encryption WebRTC connections are always encrypted by the browser. After signaling is complete: * Data flows directly between peers * Files do not pass through the server * Encryption is end-to-end Even when using TURN servers: * Data remains encrypted * Only metadata is visible to the relay *** ## Architecture Overview Below is a **controllable architecture diagram** showing how SSL/TLS is used in ErikrafT Drop. ```mermaid placement="top-left" actions={true} theme={null} flowchart LR A[Browser A] B[Browser B] HTTPS[HTTPS Server] WSS[WSS Signaling] RTC[WebRTC P2P] REL[WSS Relay] A -->|HTTPS TLS| HTTPS B -->|HTTPS TLS| HTTPS A -->|WSS TLS| WSS B -->|WSS TLS| WSS A <-->|P2P WebRTC| RTC B <-->|P2P WebRTC| RTC A <-->|Fallback WSS| REL B <-->|Fallback WSS| REL ``` ## Connection Flow ### Step 1 — Load Application The browser loads ErikrafT Drop over HTTPS. ``` Browser → HTTPS Server ``` TLS encrypts: * HTML * CSS * JavaScript * Configuration data *** ### Step 2 — WebSocket Connection The client connects to the signaling server using WSS. ``` Browser → WSS Server ``` TLS protects: * Peer discovery * Signaling messages * Pairing secrets *** ### Step 3 — WebRTC Signaling Devices exchange connection information through the signaling server. ``` Browser A → WSS → Browser B ``` TLS protects: * SDP offers * SDP answers * ICE candidates *** ### Step 4 — Peer Connection After signaling completes, a direct connection is established. ``` Browser A ↔ Browser B ``` Connection types: * Direct P2P WebRTC * TURN relay (if needed) Encryption is handled automatically by WebRTC. *** ### Step 5 — File Transfer Files are transferred directly between devices. ``` Browser A ↔ Browser B ``` Properties: * Peer-to-peer * Encrypted * No server storage *** ## SSL Configuration ErikrafT Drop supports standard TLS certificates. Recommended options: ### Let's Encrypt Automatic certificate generation: ``` certbot --nginx ``` Recommended for production deployments. *** ### Self-Signed Certificates For development environments: ``` mkcert localhost ``` Useful for local testing. *** ## Required Protocols ErikrafT Drop requires the following protocols: | Protocol | Purpose | Required | | :------- | :--------------- | :------- | | HTTPS | Load application | Yes | | WSS | Signaling | Yes | | WebRTC | P2P transfer | Yes | If HTTPS or WSS is disabled, ErikrafT Drop may not function correctly. *** ## Security Notes Important security characteristics: * Files are never stored on the server * Signaling data is encrypted with TLS * File transfers use WebRTC encryption * TURN servers cannot read file contents *** ## Best Practices Recommended settings: * Always enable HTTPS * Redirect HTTP → HTTPS * Enable HSTS * Use strong TLS ciphers * Keep certificates updated Example HSTS header: ``` Strict-Transport-Security: max-age=31536000 ``` # Connect Devices Source: https://docsdrop.erikraft.com/usage/connect-devices Step-by-step guide for connecting devices using local network discovery, device pairing, and QR codes. # Connecting Devices ErikrafT Drop provides multiple methods for connecting devices, each suited for different scenarios. This guide covers all available connection methods and best practices for successful device discovery. ## Connection Methods Overview ### 1. Local Network Discovery (Automatic) * **Best for**: Devices on the same WiFi/network * **Setup**: No configuration required * **Speed**: Instant discovery * **Security**: Local network only ### 2. Device Pairing (Persistent) * **Best for**: Frequently used devices across different networks * **Setup**: One-time pairing process * **Speed**: Quick reconnection * **Security**: Encrypted room secrets ### 3. QR Code Connection (Quick) * **Best for**: Fast, temporary connections * **Setup**: Scan QR code or enter 6-digit key * **Speed**: Immediate connection * **Security**: Temporary pairing keys ## Local Network Discovery ### Prerequisites * **Same Network**: All devices must be connected to the same network * **Modern Browser**: WebRTC-compatible browser required * **Internet Access**: Initial server connection needed ### Step-by-Step Process #### 1. Open ErikrafT Drop Navigate to [https://drop.erikraft.com/](https://drop.erikraft.com/) on all devices #### 2. Wait for Discovery * Devices automatically appear after 10-30 seconds * Look for device names in the main interface * Each device shows a unique display name (e.g., "Blue Fox", "Red Eagle") #### 3. Verify Connection * Connected devices show as active peers * Hover over devices to see connection details * Test with a small file transfer ### Troubleshooting Local Discovery #### Devices Not Appearing **Check Network Configuration:** * Verify all devices are on the same WiFi network * Check router settings for client isolation * Disable VPN or proxy services **Browser Issues:** * Update to the latest browser version * Clear browser cache and cookies * Try a different browser **Network Problems:** * Restart router if necessary * Check firewall settings * Test with a simple ping between devices #### Slow Discovery * **Network Congestion**: Reduce network traffic * **Router Performance**: Restart if discovery is very slow * **Browser Performance**: Close unnecessary tabs ## Device Pairing ### When to Use Pairing * **Cross-Network**: Devices on different networks * **Frequent Use**: Regularly connected devices * **Mobile Devices**: Phones and tablets that move between networks * **Family Setup**: Multiple family devices ### Pairing Process #### 1. Initiate Pairing On the first device: 1. Click the **Pair Device** button 2. Wait for the pairing dialog to appear 3. Note the 6-digit key and QR code #### 2. Connect Second Device On the second device: 1. Click **Pair Device** button 2. Choose one of two methods: * **Scan QR Code**: Use camera to scan the QR code * **Enter Key**: Type the 6-digit key manually #### 3. Confirm Pairing * Both devices show pairing success * Devices are saved to persistent storage * Paired devices appear automatically in future sessions ### QR Code Scanning #### Camera Access 1. **Grant Permission**: Allow camera access when prompted 2. **Position Camera**: Hold device 6-12 inches from screen 3. **Lighting**: Ensure good lighting for clear scanning 4. **Stability**: Keep device steady during scanning #### Manual Key Entry If camera access is unavailable: 1. **Note the Key**: Write down the 6-digit key 2. **Enter Carefully**: Type the key in the input field 3. **Validate**: Ensure all 6 digits are correct 4. **Submit**: Click submit or press Enter ### Managing Paired Devices #### View Paired Devices 1. Click **Edit Paired Devices** button 2. View all previously paired devices 3. See device names and pairing dates #### Device Options * **Auto-Accept**: Toggle automatic file acceptance * **Rename**: Change device display names * **Unpair**: Remove device from paired list #### Unpairing Devices 1. Open **Edit Paired Devices** dialog 2. Find the device to remove 3. Click the **Unpair** button 4. Confirm removal ## QR Code Quick Connections ### Temporary Sharing Scenarios * **Presentations**: Audience members connect quickly * **Classrooms**: Students connect to teacher's device * **Meetings**: Rapid file sharing during sessions * **Public Spaces**: Quick connections in cafes or offices ### QR Code Generation #### Create QR Code 1. Click **Pair Device** button 2. QR code appears automatically 3. 6-digit key displays below QR code 4. QR code is valid for one connection #### Share QR Code * **Display**: Show QR code on screen * **Copy URL**: Click QR code to copy pairing URL * **Share Link**: Use browser's share functionality ### QR Code Scanning #### Mobile Scanning 1. Open ErikrafT Drop on mobile device 2. Click **Pair Device** 3. Grant camera permission 4. Point camera at QR code 5. Wait for automatic detection #### Desktop Scanning 1. Use phone camera to scan desktop QR code 2. Or use desktop QR code scanner app 3. Manual entry always available as fallback ## Connection Best Practices ### Network Optimization #### WiFi Configuration * **5GHz Preferred**: Faster speeds and less interference * **Strong Signal**: Ensure good signal strength * **Channel Selection**: Use less congested channels * **Security**: WPA2/WPA3 encryption recommended #### Router Settings * **Disable Client Isolation**: Allow device communication * **UPnP Enabled**: Facilitate peer discovery * **DMZ Configuration**: For advanced users only * **Port Forwarding**: Not typically required ### Browser Optimization #### Recommended Browsers * **Chrome**: Best WebRTC support and performance * **Firefox**: Good alternative with full support * **Edge**: Chromium-based, excellent compatibility * **Safari**: Good support, some limitations #### Browser Settings * **JavaScript Enabled**: Required for functionality * **Cookies Allowed**: For session persistence * **Camera Permission**: For QR code scanning * **Notifications**: Optional but recommended ### Security Considerations #### Network Security * **Trusted Networks**: Only pair on trusted networks * **Public WiFi**: Use with caution * **VPN Considerations**: May affect local discovery * **Firewall Rules**: Ensure WebRTC traffic allowed #### Device Security * **Screen Lock**: Protect devices when unattended * **Auto-Accept**: Use only with trusted devices * **Regular Cleanup**: Remove unused paired devices * **Software Updates**: Keep browsers updated ## Advanced Connection Scenarios ### Cross-Platform Connections #### Mobile to Desktop 1. **Local Network**: Automatic discovery works best 2. **Different Networks**: Use device pairing 3. **Quick Transfer**: QR code for temporary sharing #### Mixed Device Types * **iOS to Android**: Full compatibility * **Windows to macOS**: No compatibility issues * **Linux Support**: Full functionality on modern distributions ### Multiple Device Networks #### Home Network Setup 1. **Main Computer**: Primary file source 2. **Mobile Devices**: Quick access to files 3. **Tablets**: Media consumption devices 4. **Smart TV**: Limited but possible support #### Office Environment 1. **Work Computer**: Primary work device 2. **Personal Phone**: Quick file transfers 3. **Conference Room**: Presentation sharing 4. **Guest Devices**: Temporary access ## Connection Troubleshooting ### Common Connection Issues #### Discovery Failures **Symptoms:** * Devices don't appear in list * Long wait times for discovery * Intermittent device visibility **Solutions:** * Restart all devices * Check network connectivity * Disable VPN/proxy services * Try different browsers #### Pairing Failures **Symptoms:** * QR code won't scan * Invalid key error * Pairing timeout **Solutions:** * Check lighting conditions * Verify 6-digit key accuracy * Regenerate QR code * Use manual key entry #### Connection Drops **Symptoms:** * Devices disconnect randomly * Transfer interruptions * Connection instability **Solutions:** * Check network stability * Move closer to router * Reduce network congestion * Restart network equipment ### Performance Issues #### Slow Transfers * **Network Speed**: Test internet speed * **WiFi Signal**: Improve signal strength * **Browser Performance**: Close other applications * **File Size**: Large files take longer naturally #### High Latency * **Network Congestion**: Reduce network load * **Router Quality**: Consider upgrade if old * **Interference**: Check for wireless interference * **Distance**: Move closer to access point This comprehensive connection guide ensures successful device pairing and optimal performance across all supported scenarios and device types. # Receive Files Source: https://docsdrop.erikraft.com/usage/receive-files Complete guide to receiving files, managing transfers, and handling incoming file requests in ErikrafT Drop. # Receiving Files ErikrafT Drop provides a streamlined experience for receiving files from connected devices. This guide covers the complete receiving process, from transfer requests to file management and security considerations. ## Transfer Request Process ### 1. Incoming Transfer Notification When someone sends you files, you'll receive a transfer request: #### Request Dialog The transfer request dialog displays: * **Sender Information**: Device name and identification * **File List**: All files being sent with details * **Total Size**: Combined size of all files * **File Types**: Icons indicating file categories * **Accept/Decline Options**: Choice to accept or reject #### Request Information Structure ```javascript theme={null} { type: 'request', header: [ { name: 'vacation-photo.jpg', size: 2048576, mime: 'image/jpeg' }, { name: 'document.pdf', size: 1048576, mime: 'application/pdf' } ], totalSize: 3096562, imagesOnly: false } ``` ### 2. File Preview and Inspection Before accepting, you can inspect the incoming files: #### File Details * **File Names**: Exact names of files being sent * **File Sizes**: Individual and total file sizes * **File Types**: MIME types and file extensions * **File Count**: Number of files in transfer #### Security Indicators * **File Type Warnings**: Potentially dangerous file types * **Size Warnings**: Unusually large files * **Sender Verification**: Known vs unknown senders * **Auto-Accept Status**: For paired devices ### 3. Acceptance Decision Choose how to handle the transfer request: #### Accept Transfer * **Click Accept**: Begin receiving files immediately * **Choose Location**: Select download destination (browser-dependent) * **Monitor Progress**: Watch transfer progress in real-time * **Completion Notification**: Receive success notification #### Decline Transfer * **Click Decline**: Reject the transfer request * **Optional Reason**: Send decline reason to sender * **Notification**: Sender receives decline notification * **Privacy**: No files are downloaded #### Auto-Accept (Paired Devices) For trusted paired devices: * **Automatic Accept**: Files download automatically * **Configurable**: Toggle per device in settings * **Trust Management**: Control which devices auto-accept * **Security**: Only enable for trusted devices ## File Reception Process ### 1. Header Reception ```javascript theme={null} // From network.js lines 841-867 _respondToFileTransferRequest(accepted) { this.sendJSON({type: 'files-transfer-response', accepted: accepted}); if (accepted) { this._requestAccepted = this._requestPending; this._totalBytesReceived = 0; this._filesReceived = []; } this._requestPending = null; } ``` ### 2. File Assembly Files are received in chunks and reassembled: #### FileDigester Process ```javascript theme={null} // From network.js lines 1718-1746 class FileDigester { constructor(meta, totalSize, totalBytesReceived, callback) { this._buffer = []; this._bytesReceived = 0; this._size = meta.size; this._name = meta.name; this._mime = meta.mime; this._totalSize = totalSize; this._totalBytesReceived = totalBytesReceived; this._callback = callback; } unchunk(chunk) { this._buffer.push(chunk); this._bytesReceived += chunk.byteLength || chunk.size; this.progress = (this._totalBytesReceived + this._bytesReceived) / this._totalSize; if (isNaN(this.progress)) this.progress = 1; if (this._bytesReceived < this._size) return; const blob = new Blob(this._buffer); this._buffer = null; this._callback(new File([blob], this._name, { type: this._mime || "application/octet-stream", lastModified: new Date().getTime() })); } } ``` ### 3. Progress Monitoring Track transfer progress in real-time: #### Progress Information * **Percentage**: 0-100% completion * **Transfer Speed**: Current download rate * **Time Remaining**: Estimated completion time * **File Progress**: Individual file progress for multiple files #### Progress Events ```javascript theme={null} // Progress tracking during reception _onProgress(progress) { Events.fire('file-progress', { progress: progress, peerId: this._peerId }); } ``` ## File Management ### 1. Download Location Files are saved based on browser settings: #### Default Behavior * **Downloads Folder**: Most browsers use default Downloads folder * **Browser-Specific**: Each browser has its own download location * **User Configurable**: Can be changed in browser settings * **Prompt Option**: Some browsers prompt for location #### File Naming * **Original Names**: Preserves original file names * **Conflict Resolution**: Adds suffix for duplicate names * **Special Characters**: Handles special characters appropriately * **Extension Preservation**: Maintains file extensions ### 2. File Organization Organize received files effectively: #### Automatic Organization * **Date Stamping**: Some browsers add timestamps * **Sender Identification**: Files may include sender info * **Type Grouping**: Consider organizing by file type * **Project Folders**: Create folders for different projects #### Manual Organization * **Review Files**: Check all received files * **Move to Folders**: Organize into appropriate directories * **Delete Duplicates**: Remove unnecessary copies * **Backup Important**: Backup critical files ## Advanced Receiving Features ### Multiple Simultaneous Transfers Receive files from multiple senders simultaneously: #### Concurrent Transfers * **Multiple Senders**: Accept transfers from different devices * **Independent Progress**: Each transfer tracked separately * **Bandwidth Sharing**: Transfer speed shared among transfers * **Queue Management**: Transfers queue automatically #### Transfer Management * **Pause/Resume**: Pause individual transfers if supported * **Priority Setting**: Prioritize important transfers * **Cancel Options**: Cancel unwanted transfers * **Retry Failed**: Automatic retry for failed transfers ### Preview and Quick Actions Some files support preview before complete download: #### Image Previews * **Thumbnails**: Small preview images * **Basic Info**: Resolution and file size * **Format Support**: JPEG, PNG, GIF, WebP * **Quick Actions**: Save, share, or delete #### Document Previews * **Text Files**: Basic text preview * **PDF Info**: Document metadata * **File Properties**: Size, creation date, type * **Security Scan**: Basic security information ## Security and Privacy ### Transfer Security Ensure safe file reception: #### File Validation ```javascript theme={null} // File integrity verification _onFileTransferCompleted() { const fileBlob = this._filesReceived[0]; this._totalBytesReceived += fileBlob.size; this._completeTransfer('receive', true); this.sendJSON({type: 'file-transfer-complete'}); const sameSize = fileBlob.size === acceptedHeader.size; const sameName = fileBlob.name === acceptedHeader.name; Events.fire('file-received', { file: fileBlob, peerId: this._peerId, imagesOnly: request.imagesOnly, sameSize, sameName }); } ``` #### Security Checks * **Size Verification**: Confirm actual size matches declared size * **Name Verification**: Ensure file name matches expected * **Type Verification**: Validate MIME type consistency * **Integrity Check**: Verify file integrity ### Privacy Protection Protect your privacy during file reception: #### Anonymous Reception * **No Registration**: No account required * **No Tracking**: Transfer not logged permanently * **Local Processing**: All processing on your device * **Temporary Data**: Minimal data stored temporarily #### Safe Practices * **Trusted Senders**: Only accept from known sources * **Scan Files**: Use antivirus software on received files * **Sandbox Opening**: Open suspicious files in sandbox * **Regular Cleanup**: Remove unnecessary downloaded files ## Browser-Specific Behavior ### Desktop Browsers #### Chrome/Edge * **Downloads Folder**: Files go to Downloads folder * **Download Bar**: Shows download progress at bottom * **Right-Click Options**: Context menu for file actions * **History**: Download history available #### Firefox * **Downloads Panel**: Separate downloads panel * **Custom Location**: Can set custom download folder * **Privacy Mode**: Enhanced privacy in private browsing * **Add-ons**: Extended functionality with add-ons #### Safari * **Downloads Folder**: Uses default Downloads folder * **Smart Download**: Organizes by file type sometimes * **Privacy Features**: Enhanced tracking protection * **iCloud Integration**: May sync with iCloud ### Mobile Browsers #### Mobile Chrome * **Download Notification**: Shows download in notifications * **Download Folder**: Files go to device Downloads * **File Manager**: Access through file manager app * **Share Options**: Can share received files immediately #### Mobile Safari * **Files App**: Downloads go to Files app * **iCloud Drive**: May sync with iCloud Drive * **Privacy**: Enhanced privacy features * **Storage Management**: Storage space management ## Troubleshooting Receiving Issues ### Common Problems #### Transfer Not Starting **Causes:** * Transfer request not received * Network connectivity issues * Browser blocking downloads * Insufficient storage space **Solutions:** * Check network connection * Verify browser download settings * Clear browser cache * Check available storage #### Slow Transfer Speeds **Causes:** * Poor network quality * Network congestion * Browser performance issues * Large file sizes **Solutions:** * Improve network connection * Close other applications * Try different browser * Transfer during off-peak hours #### File Corruption **Causes:** * Network interruptions * Browser crashes during transfer * Storage issues * Transfer conflicts **Solutions:** * Re-request transfer * Check storage health * Use stable network * Verify file integrity #### Download Location Issues **Causes:** * Browser download settings * Permission issues * Storage full * Folder access problems **Solutions:** * Check browser settings * Verify folder permissions * Free up storage space * Choose different location ### Performance Optimization #### Improve Reception Speed * **Wired Connection**: Use Ethernet when possible * **5GHz WiFi**: Faster and less interference * **Close Applications**: Free system resources * **Update Browser**: Latest versions perform better #### Storage Management * **Regular Cleanup**: Remove unnecessary files * **External Storage**: Use external drives for large files * **Cloud Backup**: Backup important received files * **Monitoring**: Monitor storage space usage ## Best Practices ### Security Best Practices * **Verify Senders**: Only accept from trusted sources * **Scan Files**: Use antivirus software * **Preview First**: Preview files before opening * **Backup Important**: Backup critical received files ### Organization Best Practices * **Immediate Organization**: Organize files as received * **Consistent Naming**: Use consistent file naming * **Folder Structure**: Maintain logical folder structure * **Regular Cleanup**: Remove unnecessary files ### Transfer Best Practices * **Stable Connection**: Ensure reliable network * **Sufficient Storage**: Check available space * **Browser Updates**: Keep browser current * **Patience**: Allow time for large transfers This comprehensive receiving guide ensures successful file reception while maintaining security and organization across all supported devices and browsers. # Send Files Source: https://docsdrop.erikraft.com/usage/send-files Complete guide to sending files, folders, and text messages using ErikrafT Drop's peer-to-peer system. # Sending Files ErikrafT Drop provides multiple methods for sending files, from simple drag-and-drop to advanced command-line integration. This guide covers all sending methods and best practices for successful file transfers. ## File Selection Methods ### 1. Drag and Drop (Recommended) The most intuitive method for sending files: #### Supported Content * **Files**: Any file type and size * **Folders**: Complete directory structures * **Multiple Items**: Select multiple files/folders simultaneously * **Mixed Content**: Files and folders together #### Step-by-Step Process 1. **Open ErikrafT Drop** on both devices 2. **Select Recipient**: Click on the target device 3. **Drag Files**: Drag files/folders onto the browser window 4. **Drop Content**: Release to initiate transfer 5. **Wait for Acceptance**: Recipient must accept the transfer #### Best Practices * **Organize Files**: Group related files before transfer * **Check Sizes**: Large files take longer to transfer * **Network Quality**: Ensure stable connection for large transfers * **Recipient Ready**: Confirm recipient is available ### 2. Click to Select Traditional file selection method: #### Process 1. **Click Main Area**: Click anywhere in the main interface 2. **File Dialog**: Browser file selection dialog opens 3. **Select Files**: Choose one or more files 4. **Confirm Selection**: Click Open to start transfer #### Limitations * **Folder Selection**: Not supported in all browsers * **Multiple Selection**: Use Ctrl/Cmd+Click for multiple files * **File Types**: All file types supported ### 3. Share Menu Integration Native operating system integration: #### Mobile Devices 1. **Select Files**: Use file manager or gallery app 2. **Share Button**: Tap the share icon 3. **Choose ErikrafT Drop**: Select from share menu 4. **Select Recipient**: Choose target device #### Desktop Integration * **Windows**: Right-click → Send to → ErikrafT Drop * **macOS**: Right-click → Share → ErikrafT Drop * **Linux**: Context menu integration (if configured) ## Transfer Process ### 1. Recipient Selection Before sending files, select the target recipient: #### Device List * **Available Devices**: Shows all connected devices * **Device Names**: Display names for easy identification * **Connection Status**: Shows connection quality * **Paired Devices**: Marked with special indicators #### Multiple Recipients * **Simultaneous Sending**: Send to multiple devices at once * **Individual Transfers**: Each recipient gets separate transfer * **Progress Tracking**: Monitor each transfer separately ### 2. Transfer Request When files are selected, a transfer request is sent: #### Request Information ```javascript theme={null} { type: 'request', header: [ { name: 'document.pdf', size: 1048576, mime: 'application/pdf' } ], totalSize: 1048576, imagesOnly: false } ``` #### Recipient Experience * **Notification**: Transfer request notification appears * **File Preview**: Shows file names, sizes, and types * **Accept/Decline**: User chooses to accept or decline * **Auto-Accept**: For paired devices with auto-accept enabled ### 3. Transfer Execution Once accepted, the transfer begins: #### File Preparation ```javascript theme={null} // From network.js lines 729-748 async _sendFile(file) { this.sendJSON({ type: 'header', size: file.size, name: file.name, mime: file.type || mime.defaultMime }); this._chunker = new FileChunker( file, chunk => this._send(chunk), offset => this._onPartitionEnd(offset) ); this._chunker.nextPartition(); } ``` #### Chunking System * **Chunk Size**: 64KB chunks for memory efficiency * **Partition Size**: 1MB partitions for progress tracking * **Streaming**: Files processed in real-time * **Memory Management**: Prevents browser overload ## Advanced Sending Methods ### Command Line Interface For power users and automation: #### Basic Usage ```bash theme={null} # Send single file erikraftdrop document.pdf # Send multiple files erikraftdrop file1.txt file2.jpg file3.pdf # Send directory erikraftdrop /path/to/directory/ # Send text message erikraftdrop -t "Hello world" ``` #### Configuration ```bash theme={null} # Specify custom server erikraftdrop -d "https://drop.erikraft.com/" file.txt # Show help erikraftdrop -h ``` ### URL Sharing Share links and web content: #### Process 1. **Copy URL**: Copy link from browser 2. **Paste**: Paste into ErikrafT Drop 3. **Send**: Transfer as text message 4. **Recipient**: Opens link in browser #### Supported Content * **Web Pages**: Complete URLs * **Search Queries**: Search terms as text * **Short Links**: Expanded to full URLs * **Local Files**: File:// URLs (limited support) ## File Types and Handling ### Supported File Types ErikrafT Drop supports all file types: #### Documents * **PDF**: .pdf files * **Office**: .doc, .docx, .xls, .xlsx, .ppt, .pptx * **Text**: .txt, .md, .rtf * **Code**: .js, .py, .html, .css, etc. #### Media * **Images**: .jpg, .png, .gif, .svg, .webp * **Audio**: .mp3, .wav, .ogg, .m4a * **Video**: .mp4, .avi, .mov, .mkv * **Archives**: .zip, .rar, .7z, .tar #### Special Files * **Executables**: .exe, .dmg, .deb, .rpm * **System Files**: Configuration and system files * **Large Files**: Limited only by browser memory * **Encrypted Files**: Encrypted containers and archives ### MIME Type Detection ```javascript theme={null} // Automatic MIME type detection mime.addMissingMimeTypesToFiles(files); ``` #### File Recognition * **Extension-Based**: Uses file extensions for type detection * **Default Types**: Assigns default MIME for unknown types * **Preview Support**: Determines preview capabilities * **Security**: Identifies potentially dangerous file types ## Transfer Optimization ### Large File Handling #### iOS Memory Limits ```javascript theme={null} // From network.js lines 819-822 if (window.iOS && request.totalSize >= 200*1024*1024) { this.sendJSON({ type: 'files-transfer-response', accepted: false, reason: 'ios-memory-limit' }); return; } ``` #### Strategies for Large Files * **Break Down**: Split large archives into smaller parts * **Compress**: Use compression to reduce file size * **Stable Network**: Use reliable network connection * **Patience**: Allow sufficient time for transfer ### Network Optimization #### Connection Quality * **WiFi Preferred**: More stable than cellular * **5GHz Band**: Less interference, faster speeds * **Signal Strength**: Strong signal improves reliability * **Network Congestion**: Avoid peak usage times #### Transfer Speed * **Local Network**: 50-200+ MB/s possible * **WiFi Networks**: 10-50 MB/s typical * **Mobile Data**: 1-10 MB/s depending on connection * **Cross-Network**: Limited by internet connection ## Progress Monitoring ### Real-time Feedback During transfer, both sender and receiver see progress: #### Progress Information * **Percentage**: 0-100% completion * **Transfer Speed**: Current transfer rate * **Time Remaining**: Estimated completion time * **File Count**: Progress for multiple files #### Progress Events ```javascript theme={null} // Progress tracking implementation _sendProgress(progress) { this.sendJSON({ type: 'progress', progress: progress }); } ``` ### Transfer States #### Sending States 1. **Preparing**: File preparation and chunking 2. **Request Sent**: Waiting for recipient acceptance 3. **Accepted**: Recipient approved transfer 4. **Transferring**: Active file transfer 5. **Completed**: Successful transfer 6. **Failed**: Transfer error or cancellation #### Error Handling * **Network Issues**: Automatic retry mechanisms * **Recipient Offline**: Transfer queue and retry * **File Errors**: Corrupted file handling * **Browser Crashes**: Resume capability ## Security Considerations ### File Security * **No Server Storage**: Files never stored on servers * **Direct Transfer**: Peer-to-peer encryption * **Malware Scanning**: Recipient's responsibility * **File Integrity**: Automatic integrity verification ### Privacy Protection * **End-to-End Encryption**: WebRTC provides encryption * **No Metadata Tracking**: Minimal data collection * **Temporary Connections**: No persistent data stored * **Local Processing**: All processing on device ## Troubleshooting Sending Issues ### Common Problems #### Transfer Fails to Start **Causes:** * Recipient not connected * Network connectivity issues * Browser compatibility problems * File access permissions **Solutions:** * Verify recipient connection * Check network connectivity * Try different browser * Check file permissions #### Transfer Interrupts **Causes:** * Network instability * Browser memory limits * Device going to sleep * Connection timeout **Solutions:** * Improve network stability * Close other applications * Adjust power settings * Reduce file sizes #### Slow Transfer Speeds **Causes:** * Poor network quality * Network congestion * Distance from router * Browser performance issues **Solutions:** * Improve network connection * Reduce network load * Move closer to router * Optimize browser performance ### Performance Tips #### Optimize Transfer Speed * **Use Ethernet**: Wired connection is most stable * **Close Applications**: Free up system resources * **Update Browser**: Latest browser versions perform better * **Restart Network**: Refresh network connection #### Reduce Transfer Time * **Compress Files**: Use compression for large files * **Organize Transfers**: Group related files * **Batch Small Files**: Combine many small files * **Choose Optimal Time**: Transfer during off-peak hours This comprehensive sending guide ensures successful file transfers across all supported methods and device types while maintaining security and performance.