diff --git a/android-templates/MainActivity.java b/android-templates/MainActivity.java deleted file mode 100644 index 215f0d9..0000000 --- a/android-templates/MainActivity.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.skatespots.app; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import com.getcapacitor.BridgeActivity; - -/** - * Custom MainActivity that lets the WebView hand OFF `intent:` / `nostrsigner:` - * URLs to the Android OS so Amber's approval screen actually opens. - * - * WHY THIS EXISTS - * ─────────────── - * When the JS signer navigates to an `intent:...;scheme=nostrsigner;...;end` - * URL, Capacitor's default WebView treats it as a page navigation and silently - * DROPS it — so Amber never launches and every signing action (delete, accept - * crew invite, zap, profile edit) hangs forever. Login works only because it - * goes through the native plugin's startActivityForResult; JS-initiated intents - * were never reaching the OS. On GrapheneOS this is enforced strictly. - * - * The fix: override shouldOverrideUrlLoading. Whenever the WebView tries to load - * an `intent:` or `nostrsigner:` URL, we parse it and call startActivity() - * ourselves — a REAL native launch that opens Amber, exactly like login. The - * result comes back via the app's custom-scheme deep link - * (org.skatespots.app://amber-callback...), handled by DeepLinkHandler / - * resolveAmberIntent in the web layer. - * - * This file is injected into the generated android/ project at build time by - * scripts/inject-main-activity.mjs (android/ is not committed). - */ -public class MainActivity extends BridgeActivity { - - private static final String TAG = "SkateSpotsAmber"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final WebView webView = getBridge().getWebView(); - if (webView == null) { - return; - } - - final WebViewClient existing = new WebViewClient(); - - webView.setWebViewClient(new WebViewClient() { - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (handleExternalScheme(url)) { - return true; - } - return super.shouldOverrideUrlLoading(view, url); - } - - @Override - public boolean shouldOverrideUrlLoading(WebView view, android.webkit.WebResourceRequest request) { - final String url = request.getUrl() != null ? request.getUrl().toString() : null; - if (url != null && handleExternalScheme(url)) { - return true; - } - return super.shouldOverrideUrlLoading(view, request); - } - }); - } - - /** - * If the URL is an Amber/signer intent, launch it natively and return true. - * Returns false for normal in-app URLs so Capacitor handles them as usual. - */ - private boolean handleExternalScheme(String url) { - if (url == null) { - return false; - } - - try { - if (url.startsWith("intent:")) { - // Parse the full Android intent: URI (carries scheme, extras, end). - Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - return true; - } - - if (url.startsWith("nostrsigner:")) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - return true; - } - } catch (Exception e) { - Log.e(TAG, "Failed to launch external signer intent: " + e.getMessage(), e); - // Fall through — let the WebView try to handle it (will no-op safely). - } - - return false; - } -} diff --git a/package.json b/package.json index 3480127..98accff 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "skate-spots", "private": true, - "version": "1.2.9", + "version": "1.2.10", "type": "module", "homepage": "https://skate-spots.com", "scripts": { @@ -9,11 +9,11 @@ "build": "npm i --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'Project built successfully!'", "test": "npm i --silent && tsc --noEmit && eslint && vitest run --reporter=dot --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'All tests passed!'", "deploy": "npm i --silent && npm run build && npx -y nostr-deploy-cli deploy --skip-setup", - "android:init": "npm run android:build:apk && npx cap add android && npx cap sync android && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs", - "android:sync": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs", + "android:init": "npm run android:build:apk && npx cap add android && npx cap sync android && node scripts/inject-amber-queries.mjs", + "android:sync": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs", "android:open": "npx cap open android", "android:version": "node scripts/sync-android-version.mjs", - "android:build": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && cd android && ./gradlew assembleRelease", + "android:build": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && cd android && ./gradlew assembleRelease", "android:build:apk": "CAPACITOR_BUILD=1 vite build && sed -i 's|||g' dist/index.html && sed -i 's|