diff --git a/src/lib/capacitorAmberSigner.ts b/src/lib/capacitorAmberSigner.ts index c654d3e..8533870 100644 --- a/src/lib/capacitorAmberSigner.ts +++ b/src/lib/capacitorAmberSigner.ts @@ -147,10 +147,24 @@ async function getPlugin(): Promise { * handle both hex and real npub just in case. */ export async function getAmberPublicKeyViaPlugin(): Promise { - const plugin = await getPlugin(); + // Get the raw native bridge directly. CRITICALLY we do NOT call + // setPackageName here and we do NOT pass packageName to getPublicKey. + // + // WHY: the native getPublicKey first tries Amber's ContentProvider (a + // background, no-UI query) whenever a packageName is known. On GrapheneOS that + // cross-app ContentResolver query is blocked/stalls and never returns cleanly, + // so the code never falls through to the intent that actually opens Amber's + // approval screen → eternal "Waiting for Amber". By omitting packageName, the + // plugin skips the content-resolver branch and goes STRAIGHT to + // startActivityForResult(nostrsigner:) which launches Amber's UI. Amber returns + // both the pubkey AND its package, so subsequent signing still works. + const plugin = getNativeSigner(); + if (!plugin) { + throw new Error('Amber signing is only available in the SkateSpots Android app.'); + } const result = await withTimeout( - plugin.getPublicKey({ packageName: AMBER_PACKAGE }), + plugin.getPublicKey({ permissions: JSON.stringify([{ type: 'get_public_key' }]) }), 'login', );