Registered devices card on Account — list, date, and remove

Same contract as iOS: the relay's roster for this account, oldest
first, the current install marked and not removable from itself (that
is Sign out), removal behind an in-place "Really remove" confirmation
per this screen's house style. RelayClient grows revokeDevice
(DELETE /e2e/devices/{id}); Session surfaces ownDevices()/revokeDevice
and parses the directory's new created_at.

The relay caps accounts at three devices, so this card is the only way
off the cap when registration refuses a fourth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-08-28 17:05:12 -04:00
co-authored by Claude Fable 5
parent 8ca63c4fa1
commit 7885f55849
4 changed files with 160 additions and 0 deletions
@@ -108,6 +108,14 @@ class RelayClient(
fun listDevices(userId: Long): JSONArray =
getJson("/e2e/devices/$userId").optJSONArray("devices") ?: JSONArray()
/**
* `DELETE /e2e/devices/{id}` — remove one of the ACCOUNT'S OWN devices.
* The relay refuses anyone else's, and drops the device's prekeys and
* queued mail with it (§8.3a).
*/
fun revokeDevice(deviceId: String): JSONObject =
requestJson("DELETE", url("/e2e/devices/$deviceId"), "/e2e/devices/$deviceId", null)
// -- Messages ------------------------------------------------------------
/** One envelope for one of the recipient's devices. */