From b6a37f8bbb9f7086933ecd632f92d57f3a0de234 Mon Sep 17 00:00:00 2001 From: "shakespeare.diy" Date: Thu, 3 Sep 2026 23:49:03 +0700 Subject: [PATCH] Request all Amber permissions at login (fixes silent no-prompt signing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The likely real cause of "Amber never pops up, delete hangs" on GrapheneOS: login only requested the get_public_key permission, so later sign_event / encrypt / decrypt calls hit a per-action permission check that routes through Amber's ContentProvider and stalls WITHOUT showing a prompt. Now login pre-grants get_public_key, sign_event, nip04/nip44 encrypt+decrypt up front, so subsequent signing is a fast background round-trip with no surprise permission stall. IMPORTANT: existing sessions only granted get_public_key — users must log out and back in once for Amber to grant the new permission set. Co-authored-by: shakespeare.diy --- src/lib/capacitorAmberSigner.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/lib/capacitorAmberSigner.ts b/src/lib/capacitorAmberSigner.ts index 22be76c..1f4e458 100644 --- a/src/lib/capacitorAmberSigner.ts +++ b/src/lib/capacitorAmberSigner.ts @@ -133,8 +133,23 @@ export async function getAmberPublicKeyViaPlugin(): Promise { throw new Error('Amber signing is only available in the SkateSpots Android app.'); } + // Request ALL permissions the app will need UP FRONT, so Amber pre-authorizes + // signing + encryption at login time. Without this, later signEvent/encrypt + // calls trigger a per-action permission check that, on GrapheneOS, routes + // through Amber's ContentProvider and stalls WITHOUT ever showing a prompt — + // the "Amber never pops up, delete hangs" bug. Pre-granting means signing + // afterwards is a fast background round-trip with no surprise stall. + const permissions = JSON.stringify([ + { type: 'get_public_key' }, + { type: 'sign_event' }, + { type: 'nip04_encrypt' }, + { type: 'nip04_decrypt' }, + { type: 'nip44_encrypt' }, + { type: 'nip44_decrypt' }, + ]); + const result = await withTimeout( - plugin.getPublicKey({ permissions: JSON.stringify([{ type: 'get_public_key' }]) }), + plugin.getPublicKey({ permissions }), 'login', );