import 'package:blind_master/BlindMasterResources/secure_transmissions.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; /// Bridge to the native iOS APNs registration in `ios/Runner/AppDelegate.swift`. /// The Swift side captures the device token in /// `didRegisterForRemoteNotificationsWithDeviceToken`, hex-encodes it, and /// pushes it back here over the `blindmaster/apns` MethodChannel. We then POST /// it to `/register_apns_token` so the server can target this device. /// /// Mirrors the LockInBroMobile NotificationService flow — Android has no APNs /// equivalent and the backend only supports APNs, so this is a no-op there. class ApnsService { static const _channel = MethodChannel('blindmaster/apns'); static bool _handlerInstalled = false; /// Wire the channel handler once at startup so a token delivered before the /// first `register()` call (or after, asynchronously) is still uploaded. static void install() { if (_handlerInstalled) return; if (defaultTargetPlatform != TargetPlatform.iOS && defaultTargetPlatform != TargetPlatform.macOS) { return; } _handlerInstalled = true; _channel.setMethodCallHandler((call) async { if (call.method == 'onToken') { final token = call.arguments as String?; if (token == null || token.isEmpty) return; debugPrint('APNS: token received'); try { await securePost({'token': token}, 'register_apns_token'); } catch (e) { debugPrint('APNS: token upload failed: $e'); } } }); } /// Request notification permission and upload the cached token if APNs has /// already produced one. Safe to call repeatedly (login + session-restore) — /// the server upserts. static Future register() async { if (defaultTargetPlatform != TargetPlatform.iOS && defaultTargetPlatform != TargetPlatform.macOS) { return; } install(); try { final granted = await _channel.invokeMethod('requestPermission') ?? false; if (!granted) { debugPrint('APNS: notifications denied — enable in Settings'); return; } final token = await _channel.invokeMethod('getToken'); if (token == null || token.isEmpty) { debugPrint('APNS: token not ready yet — onToken handler will catch it'); return; } await securePost({'token': token}, 'register_apns_token'); } catch (e) { debugPrint('APNS registration failed: $e'); } } }