From 6850273b3f011727c6613323c965468da5aec141 Mon Sep 17 00:00:00 2001 From: Sivert <316918682+grytchat@users.noreply.github.com> Date: Tue, 3 Nov 2026 23:32:15 +0100 Subject: [PATCH] Only the phone that asked reacts to a no (GRYT-2023) server#364 sends dm:key:handover:denied to every device on the account, with the binding that was asked for. The phone listened with once(), so a no for another device's ask would use up its listener and show the alert for nothing. It now checks the binding, and a no without one, from an older server, still counts. Co-Authored-By: Claude Opus 5.5 --- src/mls/useServerMls.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mls/useServerMls.ts b/src/mls/useServerMls.ts index 62a1ccc..74f533d 100644 --- a/src/mls/useServerMls.ts +++ b/src/mls/useServerMls.ts @@ -167,12 +167,16 @@ async function askOtherDevice(socket: Socket, host: string, dmScope: string, acc const binding = await dmKeyBindingFor(dmScope); const code = await handoverCode(dmScope, accountBinding, binding).catch(() => null); socket.emit("dm:key:handover:ask", { binding, deviceName: Platform.OS === "ios" ? "iPhone" : "Android phone" }); - socket.once("dm:key:handover:denied", () => + // Every device on the account hears a no since GRYT-2023; only one naming this key is for us. + const denied = (no?: { binding?: string }) => { + if (no?.binding && no.binding !== binding) return; + socket.off("dm:key:handover:denied", denied); Alert.alert("Your other device said no", "Nothing changed. If that was a mistake, approve this phone from another device.", [ { text: "OK", style: "cancel" }, { text: "Approve from another device", onPress: () => router.push("/link-from-device") }, - ]), - ); + ]); + }; + socket.on("dm:key:handover:denied", denied); Alert.alert( "Approve on your other device", `Your other device has a request from this phone. Open Gryt there and check it shows ${code ?? "the same code"}, then approve. ${host} then uses the same key as your other servers.`,