iOS only surfaces the Local Network permission prompt the first time an app touches the LAN (Bonjour/multicast/direct same-subnet connect). PearCal's transport is Hyperswarm/hyperdht in the Bare worklet, which reaches peers via the DHT + UDP holepunch and on first launch may never make a direct same-subnet connection - so the prompt never fired and same-WiFi peers fell back to the slow relayed path (the #37/#12 "iOS joins are slow / incomplete" bugs). Ports the proven module from PearList/PearPetal: a tiny Expo module (modules/local-network/) that, on boot, advertises + browses a throwaway Bonjour service (`_pearcallan._tcp`) to make iOS evaluate LAN access and present the prompt. Fire-and-forget from app/index.tsx before worklet bring-up; no-op off iOS. Expo autolinking (use_expo_modules!) picks it up at pod install - no manual Podfile/pbxproj edits. Added `_pearcallan._tcp` to NSBonjourServices. Client-side only, no wire change. Validated on iPhone: app launches, the Local Network prompt now fires on first launch. Suite measured cold-start join 112-147s -> ~3.4s with LN pre-granted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Azfqdkyyt4MiGSwoQLhNvd
22 lines
915 B
TypeScript
22 lines
915 B
TypeScript
import { Platform } from 'react-native'
|
|
import { requireOptionalNativeModule } from 'expo-modules-core'
|
|
|
|
// iOS-only native module (see ios/LocalNetworkModule.swift). On Android and web
|
|
// requireOptionalNativeModule returns null, so the export below is a no-op there.
|
|
const LocalNetwork = requireOptionalNativeModule<{
|
|
requestPermission(): Promise<boolean>
|
|
}>('LocalNetwork')
|
|
|
|
// Trigger the iOS Local Network permission prompt so same-WiFi Hyperswarm peers
|
|
// can be reached directly instead of via a relay. Fire-and-forget: it starts a
|
|
// short-lived Bonjour probe on the native side and resolves immediately. No-op
|
|
// off iOS or when the native module is unavailable. Never throws.
|
|
export async function requestLocalNetworkPermission (): Promise<boolean> {
|
|
if (Platform.OS !== 'ios' || !LocalNetwork) return false
|
|
try {
|
|
return await LocalNetwork.requestPermission()
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|