import 'dart:async'; import 'dart:developer'; import 'package:app_links/app_links.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:provider/provider.dart'; /// Handles opening the ad detail screen directly when the app is launched or /// resumed via a shared ad link, for Android App Links / iOS Universal Links /// (https://ms.hmg.com/ad/1541) AND the custom-scheme fallback used by that /// same web page when App Links verification isn't active /// (mowatercustomer://ad/1541, mowaterprovider://ad/1541). class AdDeepLinkService { static final AppLinks _appLinks = AppLinks(); static StreamSubscription? _subscription; /// Call once, after the app's first frame (so [navigatorKey] is attached to a Navigator). static Future init() async { try { final Uri? initialUri = await _appLinks.getInitialLink(); if (initialUri != null) { _handleUri(initialUri); } } catch (e) { log("AdDeepLinkService: failed to read initial link - $e"); } _subscription?.cancel(); _subscription = _appLinks.uriLinkStream.listen( _handleUri, onError: (Object e) => log("AdDeepLinkService: stream error - $e"), ); } static void _handleUri(Uri uri) { log("AdDeepLinkService: received $uri"); // https://ms.hmg.com/ad/1541 -> host="ms.hmg.com", pathSegments=["ad", "1541"] // mowatercustomer://ad/1541 -> host="ad" (Dart treats it as the authority), pathSegments=["1541"] int? adId; if (uri.scheme == 'https') { final segments = uri.pathSegments; if (segments.length >= 2 && segments[0] == 'ad') { adId = int.tryParse(segments[1]); } } else if (uri.host == 'ad' && uri.pathSegments.isNotEmpty) { adId = int.tryParse(uri.pathSegments.first); } if (adId == null) return; _openAd(adId); } static Future _openAd(int adId) async { final context = navigatorKey.currentContext; if (context == null) return; Utils.showLoading(context); final adDetails = await context.read().getAdDetailsById(adId); Utils.hideLoading(context); if (adDetails == null) { Utils.showToast(LocaleKeys.somethingWrong.tr()); return; } navigateWithName(context, AppRoutes.adsDetailView, arguments: adDetails); } }