temp. branching of transaction model type for dogecoin wallets

This commit is contained in:
julian 2023-01-10 17:53:09 -06:00
parent 9d6e2d0a0d
commit e7877358da
3 changed files with 678 additions and 97 deletions

View file

@ -2,14 +2,19 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart' as old;
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart';
import 'package:stackwallet/providers/blockchain/dogecoin/current_height_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
@ -37,11 +42,12 @@ class TransactionsList extends ConsumerStatefulWidget {
class _TransactionsListState extends ConsumerState<TransactionsList> {
//
bool _hasLoaded = false;
Map<String, Transaction> _transactions = {};
Map<String, old.Transaction> _transactions = {};
List<Transaction> _transactions2 = [];
late final ChangeNotifierProvider<Manager> managerProvider;
void updateTransactions(TransactionData newData) {
void updateTransactions(old.TransactionData newData) {
_transactions = {};
final newTransactions =
newData.txChunks.expand((element) => element.transactions);
@ -73,7 +79,10 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
}
Widget itemBuilder(
BuildContext context, Transaction tx, BorderRadius? radius) {
BuildContext context,
old.Transaction tx,
BorderRadius? radius,
) {
final matchingTrades = ref
.read(tradesServiceProvider)
.trades
@ -190,6 +199,134 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
}
}
Widget itemBuilder2(
BuildContext context,
Transaction tx,
BorderRadius? radius,
) {
final matchingTrades = ref
.read(tradesServiceProvider)
.trades
.where((e) => e.payInTxid == tx.txid || e.payOutTxid == tx.txid);
if (tx.type == TransactionType.outgoing && matchingTrades.isNotEmpty) {
final trade = matchingTrades.first;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: radius,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TransactionCard2(
// this may mess with combined firo transactions
key: Key(tx.toString()), //
transaction: tx,
walletId: widget.walletId,
),
TradeCard(
// this may mess with combined firo transactions
key: Key(tx.toString() + trade.uuid), //
trade: trade,
onTap: () async {
if (Util.isDesktop) {
// await showDialog<void>(
// context: context,
// builder: (context) => Navigator(
// initialRoute: TradeDetailsView.routeName,
// onGenerateRoute: RouteGenerator.generateRoute,
// onGenerateInitialRoutes: (_, __) {
// return [
// FadePageRoute(
// DesktopDialog(
// maxHeight: null,
// maxWidth: 580,
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Padding(
// padding: const EdgeInsets.only(
// left: 32,
// bottom: 16,
// ),
// child: Row(
// mainAxisAlignment:
// MainAxisAlignment.spaceBetween,
// children: [
// Text(
// "Trade details",
// style: STextStyles.desktopH3(context),
// ),
// DesktopDialogCloseButton(
// onPressedOverride: Navigator.of(
// context,
// rootNavigator: true,
// ).pop,
// ),
// ],
// ),
// ),
// Flexible(
// child: TradeDetailsView(
// tradeId: trade.tradeId,
// transactionIfSentFromStack: tx,
// walletName:
// ref.read(managerProvider).walletName,
// walletId: widget.walletId,
// ),
// ),
// ],
// ),
// ),
// const RouteSettings(
// name: TradeDetailsView.routeName,
// ),
// ),
// ];
// },
// ),
// );
} else {
unawaited(
Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(
trade.tradeId,
tx,
widget.walletId,
ref.read(managerProvider).walletName,
),
),
);
}
},
)
],
),
);
} else {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: radius,
),
child: TransactionCard2(
// this may mess with combined firo transactions
key: Key(tx.toString()), //
transaction: tx,
walletId: widget.walletId,
),
);
}
}
void updateHeightProvider(Manager manager) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
ref.read(currentHeightProvider(manager.coin).state).state =
manager.currentHeight;
});
}
@override
void initState() {
managerProvider = widget.managerProvider;
@ -202,10 +339,104 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
// .watch(walletsChangeNotifierProvider)
// .getManagerProvider(widget.walletId);
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId)));
if (manager.coin == Coin.dogecoinTestNet) {
updateHeightProvider(manager);
final wallet = manager.wallet as DogecoinWallet;
return FutureBuilder(
future: wallet.isar.transactions.where().findAll(),
builder: (fbContext, AsyncSnapshot<List<Transaction>> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
_transactions2 = snapshot.data!;
_hasLoaded = true;
}
if (!_hasLoaded) {
return Column(
children: const [
Spacer(),
Center(
child: LoadingIndicator(
height: 50,
width: 50,
),
),
Spacer(
flex: 4,
),
],
);
}
if (_transactions2.isEmpty) {
return const NoTransActionsFound();
} else {
_transactions2.sort((a, b) => b.timestamp - a.timestamp);
return RefreshIndicator(
onRefresh: () async {
//todo: check if print needed
// debugPrint("pulled down to refresh on transaction list");
final managerProvider = ref
.read(walletsChangeNotifierProvider)
.getManagerProvider(widget.walletId);
if (!ref.read(managerProvider).isRefreshing) {
unawaited(ref.read(managerProvider).refresh());
}
},
child: Util.isDesktop
? ListView.separated(
itemBuilder: (context, index) {
BorderRadius? radius;
if (_transactions2.length == 1) {
radius = BorderRadius.circular(
Constants.size.circularBorderRadius,
);
} else if (index == _transactions2.length - 1) {
radius = _borderRadiusLast;
} else if (index == 0) {
radius = _borderRadiusFirst;
}
final tx = _transactions2[index];
return itemBuilder2(context, tx, radius);
},
separatorBuilder: (context, index) {
return Container(
width: double.infinity,
height: 2,
color: Theme.of(context)
.extension<StackColors>()!
.background,
);
},
itemCount: _transactions2.length,
)
: ListView.builder(
itemCount: _transactions2.length,
itemBuilder: (context, index) {
BorderRadius? radius;
if (_transactions2.length == 1) {
radius = BorderRadius.circular(
Constants.size.circularBorderRadius,
);
} else if (index == _transactions2.length - 1) {
radius = _borderRadiusLast;
} else if (index == 0) {
radius = _borderRadiusFirst;
}
final tx = _transactions2[index];
return itemBuilder2(context, tx, radius);
},
),
);
}
},
);
} else {
return FutureBuilder(
future:
ref.watch(managerProvider.select((value) => value.transactionData)),
builder: (fbContext, AsyncSnapshot<TransactionData> snapshot) {
builder: (fbContext, AsyncSnapshot<old.TransactionData> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
updateTransactions(snapshot.data!);
@ -293,3 +524,4 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
);
}
}
}

View file

@ -1,11 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/transactions_model.dart' as old;
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
class TxIcon extends StatelessWidget {
const TxIcon({Key? key, required this.transaction}) : super(key: key);
final Transaction transaction;
final old.Transaction transaction;
static const Size size = Size(32, 32);
@ -62,3 +64,76 @@ class TxIcon extends StatelessWidget {
);
}
}
class TxIcon2 extends StatelessWidget {
const TxIcon2({
Key? key,
required this.transaction,
required this.currentHeight,
required this.coin,
}) : super(key: key);
final isar_models.Transaction transaction;
final int currentHeight;
final Coin coin;
static const Size size = Size(32, 32);
String _getAssetName(
bool isCancelled, bool isReceived, bool isPending, BuildContext context) {
if (!isReceived &&
transaction.subType == isar_models.TransactionSubType.mint) {
if (isCancelled) {
return Assets.svg.anonymizeFailed;
}
if (isPending) {
return Assets.svg.anonymizePending;
}
return Assets.svg.anonymize;
}
if (isReceived) {
if (isCancelled) {
return Assets.svg.receiveCancelled(context);
}
if (isPending) {
return Assets.svg.receivePending(context);
}
return Assets.svg.receive(context);
} else {
if (isCancelled) {
return Assets.svg.sendCancelled(context);
}
if (isPending) {
return Assets.svg.sendPending(context);
}
return Assets.svg.send(context);
}
}
@override
Widget build(BuildContext context) {
final txIsReceived =
transaction.type == isar_models.TransactionType.incoming;
return SizedBox(
width: size.width,
height: size.height,
child: Center(
child: SvgPicture.asset(
_getAssetName(
transaction.cancelled,
txIsReceived,
!transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
),
context,
),
width: size.width,
height: size.height,
),
),
);
}
}

View file

@ -2,7 +2,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/transactions_model.dart' as old;
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart';
@ -16,6 +17,8 @@ import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:tuple/tuple.dart';
import '../providers/blockchain/dogecoin/current_height_provider.dart';
class TransactionCard extends ConsumerStatefulWidget {
const TransactionCard({
Key? key,
@ -23,7 +26,7 @@ class TransactionCard extends ConsumerStatefulWidget {
required this.walletId,
}) : super(key: key);
final Transaction transaction;
final old.Transaction transaction;
final String walletId;
@override
@ -31,7 +34,7 @@ class TransactionCard extends ConsumerStatefulWidget {
}
class _TransactionCardState extends ConsumerState<TransactionCard> {
late final Transaction _transaction;
late final old.Transaction _transaction;
late final String walletId;
String whatIsIt(String type, Coin coin) {
@ -266,3 +269,274 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
);
}
}
class TransactionCard2 extends ConsumerStatefulWidget {
const TransactionCard2({
Key? key,
required this.transaction,
required this.walletId,
}) : super(key: key);
final isar_models.Transaction transaction;
final String walletId;
@override
ConsumerState<TransactionCard2> createState() => _TransactionCardState2();
}
class _TransactionCardState2 extends ConsumerState<TransactionCard2> {
late final isar_models.Transaction _transaction;
late final String walletId;
String whatIsIt(
isar_models.TransactionType type,
Coin coin,
int currentHeight,
) {
if (coin == Coin.epicCash && _transaction.slateId == null) {
return "Restored Funds";
}
final confirmedStatus = _transaction.isConfirmed(
currentHeight,
coin.requiredConfirmations,
);
if (_transaction.subType == isar_models.TransactionSubType.mint) {
// if (type == "Received") {
if (confirmedStatus) {
return "Anonymized";
} else {
return "Anonymizing";
}
// } else if (type == "Sent") {
// if (_transaction.confirmedStatus) {
// return "Sent MINT";
// } else {
// return "Sending MINT";
// }
// } else {
// return type;
// }
}
if (type == isar_models.TransactionType.incoming) {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (confirmedStatus) {
return "Received";
} else {
return "Receiving";
}
} else if (type == isar_models.TransactionType.outgoing) {
if (confirmedStatus) {
return "Sent";
} else {
return "Sending";
}
} else {
return type.name;
}
}
@override
void initState() {
walletId = widget.walletId;
_transaction = widget.transaction;
super.initState();
}
@override
Widget build(BuildContext context) {
final locale = ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale));
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
final baseCurrency = ref
.watch(prefsChangeNotifierProvider.select((value) => value.currency));
final coin = manager.coin;
final price = ref
.watch(priceAnd24hChangeNotifierProvider
.select((value) => value.getPrice(coin)))
.item1;
String prefix = "";
if (Util.isDesktop) {
if (_transaction.type == isar_models.TransactionType.outgoing) {
prefix = "-";
} else if (_transaction.type == isar_models.TransactionType.incoming) {
prefix = "+";
}
}
final currentHeight = ref.watch(currentHeightProvider(coin).state).state;
return Material(
color: Theme.of(context).extension<StackColors>()!.popupBG,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(Constants.size.circularBorderRadius),
),
child: Padding(
padding: const EdgeInsets.all(6),
child: RawMaterialButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: () async {
if (coin == Coin.epicCash && _transaction.slateId == null) {
unawaited(showFloatingFlushBar(
context: context,
message:
"Restored Epic funds from your Seed have no Data.\nUse Stack Backup to keep your transaction history.",
type: FlushBarType.warning,
duration: const Duration(seconds: 5),
));
return;
}
if (Util.isDesktop) {
// await showDialog<void>(
// context: context,
// builder: (context) => DesktopDialog(
// maxHeight: MediaQuery.of(context).size.height - 64,
// maxWidth: 580,
// child: TransactionDetailsView(
// transaction: _transaction,
// coin: coin,
// walletId: walletId,
// ),
// ),
// );
} else {
unawaited(
Navigator.of(context).pushNamed(
TransactionDetailsView.routeName,
arguments: Tuple3(
_transaction,
coin,
walletId,
),
),
);
}
},
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
children: [
TxIcon2(
transaction: _transaction,
coin: ref.watch(walletsChangeNotifierProvider.select(
(value) => value.getManager(widget.walletId).coin)),
currentHeight: currentHeight,
),
const SizedBox(
width: 14,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
_transaction.cancelled
? "Cancelled"
: whatIsIt(
_transaction.type,
coin,
currentHeight,
),
style: STextStyles.itemSubtitle12(context),
),
),
),
const SizedBox(
width: 10,
),
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Builder(
builder: (_) {
final amount = _transaction.amount;
return Text(
"$prefix${Format.satoshiAmountToPrettyString(amount, locale, coin)} ${coin.ticker}",
style:
STextStyles.itemSubtitle12_600(context),
);
},
),
),
),
],
),
const SizedBox(
height: 4,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
Format.extractDateFrom(_transaction.timestamp),
style: STextStyles.label(context),
),
),
),
if (ref.watch(prefsChangeNotifierProvider
.select((value) => value.externalCalls)))
const SizedBox(
width: 10,
),
if (ref.watch(prefsChangeNotifierProvider
.select((value) => value.externalCalls)))
Flexible(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Builder(
builder: (_) {
int value = _transaction.amount;
return Text(
"$prefix${Format.localizedStringAsFixed(
value: Format.satoshisToAmount(value,
coin: coin) *
price,
locale: locale,
decimalPlaces: 2,
)} $baseCurrency",
style: STextStyles.label(context),
);
},
),
),
),
],
),
],
),
),
],
),
),
),
),
);
}
}