SkateSpots/scripts/inject-main-activity.mjs
shakespeare.diy fea9ab3091 fix(android): native intent hand-off so Amber actually opens for signing (1.2.8)
Amber never appeared for delete/accept-invite/zap because Capacitor's default
WebView silently drops JS-initiated intent:/nostrsigner: navigations — the
request that opens Amber never reached the OS. Login worked only because it
uses the plugin's native startActivityForResult.

Add a custom MainActivity (android-templates/MainActivity.java) that overrides
shouldOverrideUrlLoading to launch intent:/nostrsigner: URLs via startActivity()
— a real native launch that opens Amber on GrapheneOS, matching login. Injected
into the generated android/ project at build time by inject-main-activity.mjs,
wired into android:build/sync/init. Simplify the JS launcher to navigate the
WebView (now intercepted natively). Bump to 1.2.8.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-09-04 21:23:38 +07:00

59 lines
2 KiB
JavaScript

#!/usr/bin/env node
/**
* Inject the custom MainActivity.java into the generated Android project.
*
* WHY THIS EXISTS
* ───────────────
* Capacitor's default MainActivity uses a WebView that silently DROPS
* `intent:` / `nostrsigner:` URL navigations, so Amber's approval screen never
* opens and every signing action (delete, accept crew invite, zap, profile
* edit) hangs forever. Our MainActivity overrides shouldOverrideUrlLoading to
* launch those intents natively via startActivity() — the real fix that opens
* Amber, matching how login already works.
*
* The android/ folder is generated per-machine (not committed), so we keep the
* source of truth in android-templates/MainActivity.java and copy it in on
* every build. Idempotent. Exits quietly if android/ hasn't been generated yet.
*/
import { readFileSync, writeFileSync, existsSync, copyFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
// Package path org.skatespots.app → org/skatespots/app
const target = join(
root,
'android',
'app',
'src',
'main',
'java',
'org',
'skatespots',
'app',
'MainActivity.java',
);
const template = join(root, 'android-templates', 'MainActivity.java');
if (!existsSync(target)) {
console.log('[inject-main-activity] android/ not generated yet — skipping.');
process.exit(0);
}
if (!existsSync(template)) {
console.error('[inject-main-activity] template android-templates/MainActivity.java missing — aborting.');
process.exit(1);
}
const current = readFileSync(target, 'utf8');
const desired = readFileSync(template, 'utf8');
if (current === desired) {
console.log('[inject-main-activity] MainActivity.java already up to date.');
process.exit(0);
}
copyFileSync(template, target);
console.log('[inject-main-activity] ✓ Installed custom MainActivity.java (intent hand-off for Amber).');