7.2 KiB
7.2 KiB
Clipboard Sync Implementation Plan
1. Goal and Scope
Build clipboard synchronization between the Android input method in Xime/ and the Windows input method in winxime/, using a Docker-deployable HTTPS relay server.
MVP scope:
- Sync text clipboard content only.
- Devices join the same sync chain by entering a sync code.
- Remote content is written to the local system clipboard, equivalent to a user copy action.
- Android additionally exposes received synced text in the IME candidate bar so users can commit it directly.
- Users can enable/disable sync in settings and must configure an HTTPS relay server URL.
Out of MVP scope:
- Image/file/rich-text clipboard sync.
- Automatic paste into the currently focused field.
- Multi-user administration UI.
- Cloud-hosted default relay.
2. Repository Layout Proposal
Add a new backend service at workspace root:
sync-server/
Dockerfile
docker-compose.yml
src/
README.md
Client integrations:
- Android:
Xime/app/src/main/java/com/kingzcheung/xime/settings,service,clipboard, andui. - Windows:
winxime/crates/winxime-serverfor clipboard watching, WebSocket sync, and local clipboard writes. - Shared protocol docs:
CLIPBOARD_SYNC_PROTOCOL.mdorsync-server/docs/protocol.md.
3. Core Product Rules
- A sync chain is a group of devices allowed to exchange clipboard events.
- A sync code authorizes a device to join a chain. It must be random, revocable, and regeneratable.
- The server must reject non-HTTPS client relay URLs. For local development, allow explicit debug-only overrides such as
http://localhost. - Every synced item must be inserted into the local clipboard and local clipboard history where the platform/app supports it.
- Android must show the latest remote synced text in the candidate bar. Tapping it should commit the text through the IME.
- Sync must be opt-in and pauseable per device.
4. Architecture
Use HTTPS REST for setup and WSS for live sync:
Android Xime <--- HTTPS/WSS ---> Sync Relay Server <--- HTTPS/WSS ---> WinXime
The server is a relay, not an editor. It authenticates devices, tracks sync chains, forwards clipboard events, and keeps short-lived replay data for reconnects.
Recommended backend stack:
- Rust with
tokio,axum,tower,serde, andsqlx/SQLite for a small self-hosted binary. - Docker image exposing one port, with TLS handled either by the service or by a reverse proxy such as Caddy/Nginx.
- WebSocket heartbeat, reconnect support, and event replay by last acknowledged sequence.
5. Protocol and Data Model
REST endpoints:
GET /healthz
POST /v1/chains
POST /v1/chains/join
POST /v1/chains/{chainId}/sync-code/rotate
GET /v1/ws
Minimum tables/entities:
chains(id, code_hash, code_expires_at, created_at)
devices(id, chain_id, name, platform, token_hash, last_seen_at)
clipboard_events(id, chain_id, source_device_id, seq, content_type, content_hash, encrypted_payload, created_at, expires_at)
WebSocket event shape:
{
"type": "clipboard.publish",
"eventId": "uuid",
"chainId": "uuid",
"sourceDeviceId": "uuid",
"sequence": 42,
"contentType": "text/plain",
"contentHash": "sha256:...",
"payload": "base64 encrypted or encoded text",
"createdAt": "2026-06-09T00:00:00Z",
"ttlSeconds": 86400
}
Client requirements:
- Ignore events from the same
deviceId. - Cache recent
eventIdandcontentHashvalues to prevent duplicate imports. - Suppress the next local clipboard-change callback after writing a remote event to avoid echo loops.
- Limit payload size, for example 64 KiB for MVP.
6. Security Requirements
- Relay URL validation must require
https://; WebSocket connections must usewss://. - Store only token hashes and sync code hashes on the server.
- Use TLS in all production deployments.
- Prefer end-to-end encryption for clipboard payloads. At minimum, server-side event storage must be short-lived with a configurable TTL.
- Sync codes should expire by default, for example after 10 minutes or after first successful join. Provide a manual rotate/revoke action.
- Never log raw clipboard content on clients or server.
7. Android Implementation Plan
- Add settings fields: enable sync, relay server URL, sync code, device name, connection status, pause/resume, and disconnect.
- Persist config in
SettingsPreferences.ktor a dedicated sync preferences class. - Add a
ClipboardSyncClientresponsible for HTTPS join, WSS connection, heartbeats, reconnects, and event acknowledgements. - Add a clipboard bridge that publishes local text copies and writes remote text via Android
ClipboardManager. - Add a local synced-item state source consumed by
CandidateBar.ktor the relevant keyboard UI layer. - When remote text arrives, update system clipboard and display it as a candidate. Tapping the candidate commits the text.
- Add unit tests for URL validation, dedupe, echo-loop suppression, and event parsing.
8. Windows Implementation Plan
- Add sync configuration to the existing Windows settings/config layer.
- Implement a WebSocket sync client inside
winxime-server. - Watch local clipboard changes from the server process and publish text changes.
- Write remote text into the Windows clipboard using the existing server/background process.
- Prevent loops by tagging remote writes and suppressing the resulting local notification.
- Surface connection status in tray/setup UI if practical.
- Validate with
cargo build --quiet; do not useunwrap()orexpect().
9. Backend Implementation Plan
- Scaffold
sync-serverwith health check, config loading, structured logging, and Dockerfile. - Implement chain creation, sync-code join, device token issuance, and code rotation.
- Implement authenticated WebSocket sessions with heartbeat and reconnect.
- Implement event fan-out to online devices in the same chain.
- Persist recent events for replay after reconnect, bounded by TTL and size limits.
- Add Docker Compose example with a reverse proxy HTTPS configuration.
- Add integration tests for join, auth failure, event fan-out, replay, TTL expiry, and duplicate suppression expectations.
10. Acceptance Criteria
- A user can deploy the relay with Docker and access it over HTTPS.
- Android and Windows settings reject plain
http://relay URLs outside debug/local mode. - Device A can create or rotate a sync code; Device B can join using that code.
- Copying text on Windows updates Android clipboard and shows the text in the Android candidate bar.
- Copying text on Android updates the Windows clipboard.
- The same event is not re-broadcast indefinitely.
- Reconnect after network loss resumes sync without requiring a new sync code.
- Raw clipboard content does not appear in logs.
11. Implementation Order for Agents
- Protocol agent: finalize event schema, sync-code lifecycle, error codes, and protocol doc.
- Backend agent: implement relay, Docker image, tests, and deployment README.
- Windows agent: implement local clipboard watcher/writer and WSS client.
- Android agent: implement settings, WSS client, clipboard bridge, and candidate bar display.
- Integration agent: run end-to-end tests across one Android device/emulator, one Windows client, and the Docker relay.