Fix Amber native login in APK: reliable Capacitor detection (v1.1.7)
Root cause: LoginDialog and useCurrentUser detected the native app via
window.Capacitor, which is unreliable inside the WebView (false at mount / not
attached in some builds). So the ZapStore APK fell into the web intent:// redirect
flow and never opened Amber ("Waiting for Amber…" hang).
Fix: add isNativeAmberAvailable() in capacitorAmberSigner.ts using the imported
@capacitor/core Capacitor + native plugin presence, and use it (evaluated at
click time) in LoginDialog.handleAmberLogin and in useCurrentUser's signer
selection. The APK now calls getAmberPublicKeyViaPlugin() → native intent → Amber
opens directly, no redirects.
Bump version to 1.1.7.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
3dea1e42dc
commit
c6372742a9
4 changed files with 25 additions and 9 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "skate-spots",
|
||||
"private": true,
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"type": "module",
|
||||
"homepage": "https://skate-spots.com",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { useLoginActions } from '@/hooks/useLoginActions';
|
|||
import { useToast } from '@/hooks/useToast';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { openAmberForLogin, subscribeToAmberReturn } from '@/lib/amber';
|
||||
import { getAmberPublicKeyViaPlugin } from '@/lib/capacitorAmberSigner';
|
||||
import { getAmberPublicKeyViaPlugin, isNativeAmberAvailable } from '@/lib/capacitorAmberSigner';
|
||||
|
||||
|
||||
interface LoginDialogProps {
|
||||
|
|
@ -45,9 +45,6 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
|
||||
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||
|
||||
// Detect if running inside a Capacitor native app
|
||||
const isCapacitor = !!(window as unknown as { Capacitor?: { isNativePlatform?: () => boolean } }).Capacitor?.isNativePlatform?.();
|
||||
|
||||
// Step 1: open Amber
|
||||
// - On Capacitor (ZapStore APK): use the native plugin — direct Promise, no redirects needed
|
||||
// - On web/PWA: use intent:// URL with callbackUrl so Amber redirects back
|
||||
|
|
@ -55,7 +52,11 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
setAmberStep('loading');
|
||||
setAmberError('');
|
||||
|
||||
if (isCapacitor) {
|
||||
// Decide native-vs-web at CLICK TIME using the reliable Capacitor check from
|
||||
// the signer module (imported @capacitor/core), NOT window.Capacitor which
|
||||
// can be false at mount inside the WebView — that mismatch was causing the
|
||||
// APK to fall into the web redirect flow and never actually open Amber.
|
||||
if (isNativeAmberAvailable()) {
|
||||
// ── Native path (ZapStore/Capacitor APK) ────────────────────────────────
|
||||
// Attempt login directly — skip isExternalSignerInstalled() check because
|
||||
// Android 11+ package visibility rules can make it return false even when
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useCallback, useMemo } from 'react';
|
|||
|
||||
import { useAuthor } from './useAuthor.ts';
|
||||
import { AmberSigner } from '@/lib/amber';
|
||||
import { CapacitorAmberSigner } from '@/lib/capacitorAmberSigner';
|
||||
import { CapacitorAmberSigner, isNativeAmberAvailable } from '@/lib/capacitorAmberSigner';
|
||||
import type { AmberLoginType } from './useLoginActions';
|
||||
|
||||
/** Extended login type that includes Amber */
|
||||
|
|
@ -27,8 +27,8 @@ export function useCurrentUser() {
|
|||
// On Capacitor (ZapStore APK) use the native plugin signer so all
|
||||
// signing operations go through Amber via native intents.
|
||||
// On web/PWA fall back to the URL-redirect based AmberSigner.
|
||||
const isCapacitor = !!(window as unknown as { Capacitor?: { isNativePlatform?: () => boolean } }).Capacitor?.isNativePlatform?.();
|
||||
const signer = isCapacitor
|
||||
// Use the reliable module-level Capacitor check (not window.Capacitor).
|
||||
const signer = isNativeAmberAvailable()
|
||||
? new CapacitorAmberSigner(amberLogin.pubkey)
|
||||
: new AmberSigner(amberLogin.pubkey);
|
||||
return new NUser('x-amber', amberLogin.pubkey, signer);
|
||||
|
|
|
|||
|
|
@ -257,6 +257,21 @@ export class CapacitorAmberSigner implements NostrSigner {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* True when we're running inside the native Capacitor app AND the native
|
||||
* NostrSigner bridge is usable. This is the ONLY reliable native check —
|
||||
* reading `window.Capacitor` from a component can be false at mount time or in
|
||||
* builds where Capacitor doesn't attach itself to `window`. Always call this at
|
||||
* the moment of the action (e.g. inside the login click handler), not at render.
|
||||
*/
|
||||
export function isNativeAmberAvailable(): boolean {
|
||||
try {
|
||||
return !!Capacitor?.isNativePlatform?.() && !!getNativeSigner();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is an external signer (Amber) installed on this device?
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue