diff --git a/.windsurf/rules.md b/.windsurf/rules.md index 71353030..de819b82 100644 --- a/.windsurf/rules.md +++ b/.windsurf/rules.md @@ -3,7 +3,7 @@ ## Project context - This is a documentation project on the Mintlify platform -- We use MDX files with YAML frontmatter +- We use MDX files with YAML frontmatter - Navigation is configured in `docs.json` - We follow technical writing best practices @@ -33,7 +33,7 @@ description: "Concise description for SEO and navigation" - `` for helpful supplementary information - `` for important cautions and breaking changes -- `` for best practices and expert advice +- `` for best practices and expert advice - `` for neutral contextual information - `` for success confirmations @@ -60,7 +60,7 @@ description: "Concise description for SEO and navigation" ## API documentation requirements -- Document all parameters with `` +- Document all parameters with `` - Show response structure with `` - Include both success and error examples - Use `` for nested object properties diff --git a/docs/architecture/file-transfer-flow.mdx b/docs/architecture/file-transfer-flow.mdx index 9c890ebe..660c5a14 100644 --- a/docs/architecture/file-transfer-flow.mdx +++ b/docs/architecture/file-transfer-flow.mdx @@ -43,10 +43,10 @@ async requestFileTransfer(files) { size: file.size, mime: file.type || mime.defaultMime }; - + header.push(fileHeader); totalSize += file.size; - + if (!mime.isImage(file)) { imagesOnly = false; } @@ -96,11 +96,11 @@ _onFilesTransferRequest(request) { 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, + type: 'files-transfer-response', + accepted: false, reason: 'ios-memory-limit' }); return; @@ -169,7 +169,7 @@ async _sendFile(file) { name: file.name, mime: file.type || mime.defaultMime }); - + this._chunker = new FileChunker( file, chunk => this._send(chunk), @@ -225,7 +225,7 @@ class FileDigester { 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, { @@ -341,12 +341,12 @@ _onFileTransferCompleted() { const sameSize = fileBlob.size === acceptedHeader.size; const sameName = fileBlob.name === acceptedHeader.name; - Events.fire('file-received', { - file: fileBlob, + Events.fire('file-received', { + file: fileBlob, peerId: this._peerId, imagesOnly: request.imagesOnly, - sameSize, - sameName + sameSize, + sameName }); } ``` diff --git a/docs/architecture/signaling-server.mdx b/docs/architecture/signaling-server.mdx index 7724728b..059dd761 100644 --- a/docs/architecture/signaling-server.mdx +++ b/docs/architecture/signaling-server.mdx @@ -53,7 +53,7 @@ export default class ErikrafTdropWsServer { 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))); } @@ -76,7 +76,7 @@ _onConnection(peer) { } return; } - + peer.socket.on('message', message => this._onMessage(peer, message)); peer.socket.onerror = e => console.error(e); this._keepAlive(peer); @@ -94,7 +94,7 @@ function isLocalIp(ip) { 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; @@ -102,7 +102,7 @@ function isLocalIp(ip) { if (/^fd[0-9a-f]{2}$/.test(firstWord)) return true; if (firstWord === "fe80") return true; if (firstWord === "100") return true; - + return false; } ``` @@ -278,7 +278,7 @@ _onPairDeviceJoin(sender, message) { 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, diff --git a/docs/architecture/webrtc-connection.mdx b/docs/architecture/webrtc-connection.mdx index e2040ffc..5388528e 100644 --- a/docs/architecture/webrtc-connection.mdx +++ b/docs/architecture/webrtc-connection.mdx @@ -17,10 +17,10 @@ The core WebRTC functionality is implemented in the `RTCPeer` class in `network. 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(); } @@ -215,7 +215,7 @@ 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 WS PWA --> WS Android --> WS @@ -151,7 +151,7 @@ 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: WebRTC offer @@ -167,7 +167,7 @@ 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 diff --git a/docs/ecosystem/shortcut.mdx b/docs/ecosystem/shortcut.mdx index 6a084c2d..74dd21a3 100644 --- a/docs/ecosystem/shortcut.mdx +++ b/docs/ecosystem/shortcut.mdx @@ -63,12 +63,12 @@ graph TD 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] ``` diff --git a/docs/features/device-pairing.mdx b/docs/features/device-pairing.mdx index cfd6f512..bf9c5ac5 100644 --- a/docs/features/device-pairing.mdx +++ b/docs/features/device-pairing.mdx @@ -172,7 +172,7 @@ _onPairDeviceJoin(sender, message) { 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, @@ -240,12 +240,12 @@ async _initDOM() { 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'; @@ -255,7 +255,7 @@ async _initDOM() { autoAccept: e.target.checked }); }); - + $pairedDevice.appendChild(displayDiv); $pairedDevice.appendChild(input); this.$pairedDevicesWrapper.appendChild($pairedDevice); @@ -334,7 +334,7 @@ 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)); } diff --git a/docs/features/p2p-transfer.mdx b/docs/features/p2p-transfer.mdx index 625a1e75..5aca2049 100644 --- a/docs/features/p2p-transfer.mdx +++ b/docs/features/p2p-transfer.mdx @@ -71,7 +71,7 @@ Devices discover each other through: ```javascript // From network.js lines 1104-1113 _connect() { - if (!this._conn || this._conn.signalingState === "closed") + if (!this._conn || this._conn.signalingState === "closed") this._openConnection(); if (this._isCaller) { diff --git a/docs/features/qr-connection.mdx b/docs/features/qr-connection.mdx index 9ee0d676..9ec89afb 100644 --- a/docs/features/qr-connection.mdx +++ b/docs/features/qr-connection.mdx @@ -119,8 +119,8 @@ The system requests camera access for QR code scanning: ```javascript // Camera access is handled by the browser's getUserMedia API -navigator.mediaDevices.getUserMedia({ - video: { facingMode: 'environment' } +navigator.mediaDevices.getUserMedia({ + video: { facingMode: 'environment' } }) .then(stream => { // Initialize QR code scanner @@ -238,17 +238,17 @@ When camera access is unavailable: 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; } ``` diff --git a/docs/reference/configuration.mdx b/docs/reference/configuration.mdx index ba371cb1..635079d0 100644 --- a/docs/reference/configuration.mdx +++ b/docs/reference/configuration.mdx @@ -360,8 +360,8 @@ if (cluster.isMaster) { // From network.js lines 819-822 if (window.iOS && request.totalSize >= 200*1024*1024) { this.sendJSON({ - type: 'files-transfer-response', - accepted: false, + type: 'files-transfer-response', + accepted: false, reason: 'ios-memory-limit' }); return; diff --git a/docs/reference/host-your-own.mdx b/docs/reference/host-your-own.mdx index bb024cbf..ab532d73 100644 --- a/docs/reference/host-your-own.mdx +++ b/docs/reference/host-your-own.mdx @@ -41,10 +41,10 @@ The easiest way to get ErikrafT Drop up and running is by using Docker. ```bash 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 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 -> +> > **For official ErikrafT Drop images, build from source using the Dockerfile below.** diff --git a/docs/usage/receive-files.mdx b/docs/usage/receive-files.mdx index 38f1935c..72b914c6 100644 --- a/docs/usage/receive-files.mdx +++ b/docs/usage/receive-files.mdx @@ -119,7 +119,7 @@ class FileDigester { 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, { @@ -231,12 +231,12 @@ _onFileTransferCompleted() { const sameSize = fileBlob.size === acceptedHeader.size; const sameName = fileBlob.name === acceptedHeader.name; - Events.fire('file-received', { - file: fileBlob, + Events.fire('file-received', { + file: fileBlob, peerId: this._peerId, imagesOnly: request.imagesOnly, - sameSize, - sameName + sameSize, + sameName }); } ``` diff --git a/docs/usage/send-files.mdx b/docs/usage/send-files.mdx index afea498d..253c4f05 100644 --- a/docs/usage/send-files.mdx +++ b/docs/usage/send-files.mdx @@ -113,7 +113,7 @@ async _sendFile(file) { name: file.name, mime: file.type || mime.defaultMime }); - + this._chunker = new FileChunker( file, chunk => this._send(chunk), @@ -217,8 +217,8 @@ mime.addMissingMimeTypesToFiles(files); // From network.js lines 819-822 if (window.iOS && request.totalSize >= 200*1024*1024) { this.sendJSON({ - type: 'files-transfer-response', - accepted: false, + type: 'files-transfer-response', + accepted: false, reason: 'ios-memory-limit' }); return;