feat(engine): "Copy share link" Stats button — clipboards the replay URL
Quat: replay sharing as the next punch-list item. End-to-end: 1. Player wins a game on a server-backed sync backend. 2. `sync_plugin::push_replay_on_win` spawns the upload task on `AsyncComputeTaskPool` and stores the handle in the new `PendingReplayUpload` resource. The previous in-flight task (if any) is dropped — the most recent win is the one whose share link the player will care about. 3. `poll_replay_upload_result` harvests the task on the main thread each frame; on success writes `<server>/replays/<id>` to `LastSharedReplayUrl`. `UnsupportedPlatform` (LocalOnlyProvider) is silently absorbed; real network/auth errors warn-log. 4. The Stats overlay's action bar gains a "Copy share link" button. Click writes `LastSharedReplayUrl` to the OS clipboard via `arboard` and surfaces a "Copied: <url>" toast. Trait change: `SyncProvider::push_replay` now returns `Result<String, SyncError>` (the share URL) instead of `Result<(), SyncError>`. The default (`UnsupportedPlatform`) is unchanged for non-server backends; `SolitaireServerClient` parses the response body's `id` field and composes `<base_url>/replays/<id>`. Both call paths (initial + 401 retry) go through the new `share_url_from_response` helper so the parse logic isn't duplicated. New deps: - `arboard` (~10 KB, cross-platform clipboard) added to workspace + `solitaire_engine`. `default-features = false` keeps the X11/Wayland binary-feature deps off the dependency graph; arboard handles the fallback. Approved per the ASK BEFORE rule. Persistence: the URL is in-memory only — the player must share within the session of the win. A future revision can persist it alongside the replay history file if cross-session sharing is needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ dirs = "6"
|
||||
keyring = "4"
|
||||
keyring-core = "1"
|
||||
reqwest = { version = "0.13", features = ["json", "rustls", "rustls-native-certs"], default-features = false }
|
||||
arboard = { version = "3", default-features = false }
|
||||
|
||||
solitaire_core = { path = "solitaire_core" }
|
||||
solitaire_sync = { path = "solitaire_sync" }
|
||||
|
||||
Reference in New Issue
Block a user