| 1 | import 'dart:async'; |
| 2 | |
| 3 | import 'package:cake_wallet/buy/buy_provider_description.dart'; |
| 4 | import 'package:cake_wallet/cake_pay/src/models/cake_pay_order.dart'; |
| 5 | import 'package:cake_wallet/cake_pay/src/services/cake_pay_service.dart'; |
| 6 | import 'package:cake_wallet/core/utilities.dart'; |
| 7 | import 'package:cake_wallet/generated/i18n.dart'; |
| 8 | import 'package:cake_wallet/order/order.dart'; |
| 9 | import 'package:cake_wallet/order/order_provider.dart'; |
| 10 | import 'package:cake_wallet/order/order_provider_adapter/cake_pay_order_provider_adapter.dart'; |
| 11 | import 'package:cake_wallet/order/order_provider_adapter/wyre_order_provider_adapter.dart'; |
| 12 | import 'package:cake_wallet/order/order_provider_description.dart'; |
| 13 | import 'package:cake_wallet/order/order_source_description.dart'; |
| 14 | import 'package:cake_wallet/src/screens/order_details/cake_pay_detail_list_card_item.dart'; |
| 15 | import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; |
| 16 | import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; |
| 17 | import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; |
| 18 | import 'package:cake_wallet/utils/date_formatter.dart'; |
| 19 | import 'package:cake_wallet/utils/show_bar.dart'; |
| 20 | import 'package:cw_core/utils/print_verbose.dart'; |
| 21 | import 'package:cw_core/wallet_base.dart'; |
| 22 | import 'package:flutter/material.dart'; |
| 23 | import 'package:flutter/services.dart'; |
| 24 | import 'package:hive/hive.dart'; |
| 25 | import 'package:mobx/mobx.dart'; |
| 26 | import 'package:url_launcher/url_launcher.dart'; |
| 27 | |
| 28 | part 'order_details_view_model.g.dart'; |
| 29 | |
| 30 | class OrderDetailsViewModel = OrderDetailsViewModelBase with _$OrderDetailsViewModel; |
| 31 | |
| 32 | abstract class OrderDetailsViewModelBase with Store { |
| 33 | OrderDetailsViewModelBase({ |
| 34 | required WalletBase wallet, |
| 35 | required Order orderForDetails, |
| 36 | required this.cakePayService, |
| 37 | required this.orders, |
| 38 | }) : items = ObservableList<StandartListItem>(), |
| 39 | order = orderForDetails { |
| 40 | switch (order.source) { |
| 41 | case OrderSourceDescription.buy: |
| 42 | if (order.buyProvider == BuyProviderDescription.wyre) { |
| 43 | _provider = WyreOrderProviderAdapter(wallet: wallet); |
| 44 | } else if (order.buyProvider == BuyProviderDescription.moonPay) { |
| 45 | //_provider = MoonPayOrderProviderAdapter(appStore: null /* provide if needed */, wallet: wallet); |
| 46 | } |
| 47 | break; |
| 48 | |
| 49 | case OrderSourceDescription.order: |
| 50 | if (order.orderProvider == OrderProviderDescription.cakePay) { |
| 51 | _provider = CakePayOrderProviderAdapter(wallet: wallet, cakePayService: cakePayService); |
| 52 | } |
| 53 | break; |
| 54 | } |
| 55 | |
| 56 | _updateItems(); |
| 57 | _updateOrder(); |
| 58 | timer = Timer.periodic(const Duration(seconds: 20), (_) async => _updateOrder()); |
| 59 | } |
| 60 | |
| 61 | @observable |
| 62 | Order order; |
| 63 | |
| 64 | @observable |
| 65 | ObservableList<StandartListItem> items; |
| 66 | |
| 67 | final CakePayService cakePayService; |
| 68 | final Box<Order> orders; |
| 69 | OrderProvider? _provider; |
| 70 | List<OrderCard> cards = []; |
| 71 | |
| 72 | Timer? timer; |
| 73 | |
| 74 | @action |
| 75 | Future<void> _updateOrder() async { |
| 76 | try { |
| 77 | if (_provider == null) return; |
| 78 | |
| 79 | final updatedOrderObj = await _provider!.findOrderById(order.id); |
| 80 | final updatedOrder = updatedOrderObj.$1; |
| 81 | |
| 82 | if (_provider is CakePayOrderProviderAdapter) { |
| 83 | cards = updatedOrderObj.$2 as List<OrderCard>? ?? []; |
| 84 | } |
| 85 | |
| 86 | final existing = orders.values.firstWhereOrNull((e) => e.id == updatedOrder.id); |
| 87 | if (existing != null) { |
| 88 | existing.stateRaw = updatedOrder.stateRaw; |
| 89 | await existing.save(); |
| 90 | |
| 91 | order = existing; |
| 92 | } else { |
| 93 | await orders.add(updatedOrder); |
| 94 | order = updatedOrder; |
| 95 | } |
| 96 | |
| 97 | _updateItems(); |
| 98 | } catch (e) { |
| 99 | printV(e.toString()); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | void _updateItems() { |
| 104 | final dateFormat = DateFormatter.withCurrentLocal(); |
| 105 | items.clear(); |
| 106 | |
| 107 | items.add( |
| 108 | DetailsListStatusItem(title: S.current.trade_details_state, value: order.state.toString())); |
| 109 | |
| 110 | if (_provider is CakePayOrderProviderAdapter) { |
| 111 | items.add(CakePayDetailsListCardItem( |
| 112 | title: '', |
| 113 | value: '', |
| 114 | id: order.id, |
| 115 | createdAt: dateFormat.format(order.createdAt), |
| 116 | price: order.receiveAmount, |
| 117 | quantity: order.quantity, |
| 118 | from: order.from ?? '', |
| 119 | to: order.to ?? '', |
| 120 | cards: cards, |
| 121 | onTap: (BuildContext context) { |
| 122 | Clipboard.setData(ClipboardData(text: '${order.id}')); |
| 123 | showBar<void>(context, S.of(context).copied_to_clipboard); |
| 124 | }, |
| 125 | )); |
| 126 | } |
| 127 | |
| 128 | items.add(StandartListItem(title: 'Order provider', value: _provider?.title ?? '')); |
| 129 | |
| 130 | final trackUrl = _provider?.trackUrl ?? ''; |
| 131 | if (trackUrl.isNotEmpty) { |
| 132 | final buildURL = trackUrl + '${order.transferId}'; |
| 133 | items.add(TrackTradeListItem( |
| 134 | title: S.current.track, |
| 135 | value: buildURL, |
| 136 | onTap: () async { |
| 137 | try { |
| 138 | final uri = Uri.parse(buildURL); |
| 139 | if (await canLaunchUrl(uri)) |
| 140 | await launchUrl(uri, mode: LaunchMode.externalApplication); |
| 141 | } catch (e) {} |
| 142 | })); |
| 143 | } |
| 144 | } |
| 145 | } |