Root cause of the CI "Cannot find module @anydrop/shared" error:
server/tsconfig.tsbuildinfo and shared/tsconfig.tsbuildinfo were checked in.
On the Gitea runner, tsc read those files, concluded the prior (local-machine)
build was still valid, and skipped emitting shared/dist — so there was nothing
to resolve by the time server's tsc ran.
- untrack the two .tsbuildinfo files
- gitignore *.tsbuildinfo
- dockerignore **/dist, **/*.tsbuildinfo (belt-and-suspenders)
- in both Dockerfiles, delete any stray tsbuildinfo + dist dirs before tsc
iOS PWA (home screen) has separate localStorage from Safari, so
QR-based pairing breaks. Now pairing uses a 6-character code:
- Device A taps "Appairer" → shows a code like "A7K9XB"
- Device B taps "Appairer" → "Rejoindre" tab → enters the code
- Server resolves the code to the groupId, devices are linked
Codes expire after 5 minutes. Pairing is permanent.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Transfers now survive page refreshes:
- beforeunload warning prevents accidental refresh during transfer
- Sender's files cached in IndexedDB before sending
- Receiver's chunks persisted in IndexedDB as they arrive
- On reconnect, receiver sends transfer-resume with bytes received
- Sender resumes from offset, skipping already-sent data
- Old transfer data auto-cleaned after 1 hour
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a groupId-based pairing system so devices can always see
each other regardless of network. Scan a QR code once from the
other device, and they're permanently linked via a shared group
stored in localStorage. No account, no email — just one-time QR
scan like Bluetooth pairing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
iCloud Private Relay hides iPhones' real public IP, breaking
IP-based LAN grouping. Devices now detect their local IP
(192.168.x.x) via WebRTC ICE candidates and send it to the
server. The server groups devices by local subnet as a fallback
when public IPs differ.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Offline push-subscribed devices appear dimmed in peer list
- Tap offline peer to send wake push notification
- Skip self-notification (own deviceId excluded)
- iOS/Android share sheet via Web Share Target API
- Online/offline indicator dot on peer avatars
- Web Push API for offline device notifications
- Custom service worker with push event handling
- Local notifications for background tab transfers
- VAPID keys in K8s config
- Persistent deviceId per device
- Users set their own device name and optional profile picture
- Profile persisted in localStorage (no account needed)
- Auto-detect device type from user agent (iPhone, Mac, Android...)
- Server uses client-provided profile instead of generating names
- PeerAvatar shows photo or device icon instead of animal emojis
- ProfileSetup modal on first visit + editable from header