SkateSpots/scripts/inject-amber-queries.mjs
shakespeare.diy 677ccb8a82 v1.2.0: Spedn label, multi-relay community stats, GrapheneOS Near-Me fix
1. Map filter: renamed the "Bitcoin" toggle to "Spedn" (matches the toolbar
   button); tooltip now says "Spedn your sats".

2. Community stats (/stats): useGrowthStats now queries the same relay set as the
   rest of the app (community relay + user relays) via useSkateRelays instead of
   only the single hardcoded SKATE_RELAY. Lab profiles / spots / etc. that live on
   a user's own relay are now counted, so the numbers match what /lab shows.

3. Near Me on GrapheneOS: even after granting the OS location permission, the
   WebView's navigator.geolocation stays blocked → "permission denied". Fixed by
   fetching the position from the native Capacitor Geolocation plugin first
   (LocationManager, honours the granted permission), falling back to
   navigator.geolocation only if that fails. Also auto-inject
   ACCESS_FINE/COARSE_LOCATION into AndroidManifest via the manifest script.

Bump version to 1.2.0 (versionCode 10200).

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-08-27 14:54:00 +07:00

80 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Inject the Amber (NIP-55) <queries> block into the Android manifest.
*
* WHY THIS EXISTS
* ───────────────
* On Android 11+ (and GrapheneOS enforces this strictly), an app can only see
* or launch another app if it declares a matching <queries> entry. Without it,
* the nostrsigner intent that opens Amber is SILENTLY blocked by the OS and the
* native signer call hangs forever — the classic "Waiting for Amber…" bug.
*
* Capacitor regenerates android/app/src/main/AndroidManifest.xml on `cap add`
* and can touch it on sync, so hand-editing is fragile. This script is
* idempotent and runs automatically as part of the android build, guaranteeing
* the block is always present in the APK we ship.
*
* If android/ hasn't been generated yet (fresh checkout), it exits quietly.
*/
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
const manifestPath = join(root, 'android', 'app', 'src', 'main', 'AndroidManifest.xml');
if (!existsSync(manifestPath)) {
console.log('[inject-amber-queries] android/ not generated yet — skipping.');
process.exit(0);
}
let manifest = readFileSync(manifestPath, 'utf8');
let changed = false;
// Insert right before the closing </manifest> tag.
if (!manifest.includes('</manifest>')) {
console.error('[inject-amber-queries] No closing </manifest> tag found — aborting.');
process.exit(1);
}
// ── 1. Amber <queries> block ────────────────────────────────────────────────
if (!manifest.includes('android:scheme="nostrsigner"')) {
const queriesBlock = ` <!-- REQUIRED for Amber (NIP-55) on Android 11+ / GrapheneOS.
Without this the OS blocks the nostrsigner intent and the signer call
hangs forever ("Waiting for Amber"). Injected by scripts/inject-amber-queries.mjs -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="nostrsigner" />
</intent>
<package android:name="com.greenart7c3.nostrsigner" />
</queries>
`;
manifest = manifest.replace('</manifest>', `${queriesBlock}</manifest>`);
changed = true;
console.log('[inject-amber-queries] ✓ Injected Amber <queries> block.');
} else {
console.log('[inject-amber-queries] <queries> already present.');
}
// ── 2. Location permissions ───────────────────────────────────────────────────
// The native Geolocation plugin can't prompt for / obtain a fix without these.
// Missing permissions is why "Near Me" reports denied even after the user
// thinks they granted it.
const locationPerms = ` <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
`;
if (!manifest.includes('ACCESS_FINE_LOCATION')) {
manifest = manifest.replace('</manifest>', `${locationPerms}</manifest>`);
changed = true;
console.log('[inject-amber-queries] ✓ Injected location permissions.');
} else {
console.log('[inject-amber-queries] location permissions already present.');
}
if (changed) {
writeFileSync(manifestPath, manifest);
console.log('[inject-amber-queries] AndroidManifest.xml updated.');
} else {
console.log('[inject-amber-queries] nothing to do.');
}