import 'dart:async'; import 'package:hash_wallet/generated/i18n.dart'; import 'package:hash_wallet/reactions/wallet_connect.dart'; import 'package:hash_wallet/routes.dart'; import 'package:hash_wallet/store/app_store.dart'; import 'package:hash_wallet/store/authentication_store.dart'; import 'package:hash_wallet/store/settings_store.dart'; import 'package:hash_wallet/utils/payment_request.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; class LinkViewModel { LinkViewModel({ required this.settingsStore, required this.appStore, required this.authenticationStore, required this.navigatorKey, }); final SettingsStore settingsStore; final AppStore appStore; final AuthenticationStore authenticationStore; final GlobalKey navigatorKey; Uri? currentLink; bool readyToOpenPage = false; bool get _isValidPaymentUri => currentLink?.path.isNotEmpty ?? false; bool get isWalletConnectLink => currentLink?.authority == 'wc'; bool get isNanoGptLink => currentLink?.scheme == 'nano-gpt'; bool get isQuickActionLink => currentLink?.scheme == 'hashwallet' && currentLink?.host == 'quickaction'; String? getRouteToGo() { if (isWalletConnectLink) { if (!isWalletConnectCompatibleChain(appStore.wallet!.type)) { _errorToast(S.current.switchToEVMCompatibleWallet); return null; } return Routes.walletConnectConnectionsListing; } // Check for a quick action first. if (isQuickActionLink) { final action = currentLink!.pathSegments.isNotEmpty ? currentLink!.pathSegments.first : null; switch (action) { case 'send': return Routes.send; case 'receive': return Routes.addressPage; default: return null; } } if (authenticationStore.state == AuthenticationState.uninitialized) { return null; } if (isNanoGptLink) { switch (currentLink?.authority ?? '') { case "exchange": return Routes.exchange; case "send": return Routes.send; case "buy": return Routes.buySellPage; } } if (_isValidPaymentUri) { return Routes.send; } return null; } dynamic getRouteArgs() { if (isWalletConnectLink) { return currentLink; } if (isQuickActionLink) { return null; } if (isNanoGptLink) { switch (currentLink?.authority ?? '') { case "exchange": return PaymentRequest.fromUri(currentLink); case "send": return {"paymentRequest": PaymentRequest.fromUri(currentLink)}; case "buy": return true; } } if (_isValidPaymentUri) { return {"paymentRequest": PaymentRequest.fromUri(currentLink)}; } return null; } Future _errorToast(String message, {double fontSize = 16}) async { try { await Fluttertoast.showToast( msg: message, toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.SNACKBAR, backgroundColor: Colors.black, textColor: Colors.white, fontSize: fontSize, ); } catch (_) {} } Future markReadyToOpenPage() async { readyToOpenPage = true; await handleLink(); } Future handleLink() async { if (!readyToOpenPage) { return; } String? route = getRouteToGo(); dynamic args = getRouteArgs(); if (route != null) { if (appStore.wallet == null) { return; } // Prevent navigating to the same route again. if (appStore.currentRouteName == route) { return; } if (isNanoGptLink) { if (route == Routes.buySellPage || route == Routes.exchange) { await _errorToast(S.current.nano_gpt_thanks_message, fontSize: 14); } } // Quick actions must reset navigation to Dashboard → TargetPage if (isQuickActionLink) { currentLink = null; navigatorKey.currentState?.pushNamedAndRemoveUntil( route, ModalRoute.withName(Routes.dashboard), arguments: args, ); return; } // Normal navigation flow currentLink = null; navigatorKey.currentState?.pushNamed(route, arguments: args); } } }