You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
car_common_app/lib/services/ad_deep_link_service.dart

75 lines
2.5 KiB
Dart

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<Uri>? _subscription;
/// Call once, after the app's first frame (so [navigatorKey] is attached to a Navigator).
static Future<void> 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<void> _openAd(int adId) async {
final context = navigatorKey.currentContext;
if (context == null) return;
Utils.showLoading(context);
final adDetails = await context.read<AdVM>().getAdDetailsById(adId);
Utils.hideLoading(context);
if (adDetails == null) {
Utils.showToast(LocaleKeys.somethingWrong.tr());
return;
}
navigateWithName(context, AppRoutes.adsDetailView, arguments: adDetails);
}
}