import 'dart:async'; import 'dart:convert'; import 'package:app_links/app_links.dart'; import 'package:get/get.dart'; import 'package:onufitness/controller/notification_controller.dart'; import 'package:onufitness/environment/environment_config.dart'; import 'package:onufitness/routes/route_constant.dart'; import 'package:onufitness/screens/accounts/Controllers/coach_rating_controller.dart'; import 'package:onufitness/screens/chat/controllers/chat_controller.dart'; import 'package:onufitness/screens/echoboard/controllers/connection_and_tribe_controller.dart'; import 'package:onufitness/screens/echoboard/controllers/profile_controller.dart'; import 'package:onufitness/screens/echoboard/views/single_post_screen.dart'; import 'package:onufitness/screens/navbar/bottom_nav_bar.dart'; import 'package:onufitness/screens/echoboard/controllers/echoboard_controller.dart'; import 'package:onufitness/services/local_storage_services/shared_services.dart'; import 'package:onufitness/utils/custom_sneakbar.dart'; class DeepLinkService extends GetxService { late AppLinks appLinks; StreamSubscription? linkSubscription; static DeepLinkService get instance => Get.find(); final RxBool isDeepLinkNavigating = false.obs; @override void onInit() { super.onInit(); appLinks = AppLinks(); // initDeepLinks(); } //....................................................................................................... @override void onClose() { linkSubscription?.cancel(); super.onClose(); } void initDeepLinks() { // Handle incoming links when app is already running linkSubscription = appLinks.uriLinkStream.listen((Uri uri) { handleDeepLink(uri); }, onError: (err) {}); } void handleDeepLink(Uri uri) async { isDeepLinkNavigating(true); final webUrl = EnvironmentConfigFactory.getConfig().webUrl; if (uri.host == webUrl && uri.pathSegments.isNotEmpty) { // Handle regular post link: /post-link?postId=encodedPostId if (uri.pathSegments[0] == 'post-link') { final String? encodedPostId = uri.queryParameters['postId']; if (encodedPostId != null) { final decodedPostId = utf8.decode(base64Url.decode(encodedPostId)); await navigateToPost(postId: decodedPostId); } } // Handle tribe post link: /tribe-post-link?tribeId=encodedTribeId&postId=encodedPostId if (uri.pathSegments[0] == 'tribe-post-link') { final String? encodedTribeId = uri.queryParameters['tribeId']; final String? encodedPostId = uri.queryParameters['postId']; if (encodedTribeId != null && encodedPostId != null) { final decodedPostId = utf8.decode(base64Url.decode(encodedPostId)); final decodedTribeId = utf8.decode(base64Url.decode(encodedTribeId)); await navigateToTribeEchoboardPost( postId: decodedPostId, tribeId: int.parse(decodedTribeId), ); } } } } Future navigateToTribeEchoboardPost({ required String postId, int? tribeId, }) async { // Give 1 second wait for GetMaterialApp Initialize Prooperly..................... await Future.delayed(Duration(seconds: 1)); //................................................................................. if (SharedServices.isLoggedIn() == true) { if (!Get.isRegistered()) { Get.put(SocialConnectionController()); } final socialConnectionController = Get.find(); // Check if user is a member of the tribe final isMember = await socialConnectionController.checkUserInTribe( tribeId: tribeId!, ); if (isMember) { // User is a member, load tribe details final tribeDetailsLoaded = await socialConnectionController .getSingleTribeDetails(tribeId: tribeId); if (tribeDetailsLoaded) { // Navigate to SinglePostPage with tribe context Get.offAll( () => SinglePostPage( postId: postId, tribeId: tribeId, isComingFromShare: true, ), ); controllerInitialization(); } else { customSnackbar( title: "Error", message: "Failed to load tribe details", duration: 2, ); Get.offAll(() => const DashboardScreen()); controllerInitialization(); } } else { // User is NOT a member customSnackbar( title: "Access Denied", message: "You are not a member of this tribe", duration: 2, ); Get.offAll(() => const DashboardScreen()); controllerInitialization(); } } else { Future.delayed(const Duration(milliseconds: 100), () { Get.offNamedUntil(RouteConstant.loginFirstScreen, (route) => false); }); } } Future navigateToPost({required String postId}) async { // Give 1 second wait for GetMaterialApp Initialize Prooperly..................... await Future.delayed(Duration(seconds: 1)); //................................................................................. if (SharedServices.isLoggedIn() == true) { Get.offAll( () => SinglePostPage(postId: postId, tribeId: 0, isComingFromShare: true), ); controllerInitialization(); } else { Future.delayed(const Duration(milliseconds: 100), () { Get.offNamedUntil(RouteConstant.loginFirstScreen, (route) => false); }); } } controllerInitialization() { if (!Get.isRegistered()) { Get.put(NavigationController()); } if (!Get.isRegistered()) { Get.put(RatingsReviewsController()); } if (!Get.isRegistered()) { Get.put(EchoBoardController()); } if (!Get.isRegistered()) { Get.put(ChatController()); } if (!Get.isRegistered()) { Get.put(ProfileController()); } if (!Get.isRegistered()) { Get.put(NotificationController()); } } }