diff --git a/images/2.0x/logo_b_40.png b/images/2.0x/logo_b_40.png new file mode 100644 index 0000000..27dfb21 Binary files /dev/null and b/images/2.0x/logo_b_40.png differ diff --git a/images/2.0x/qr.png b/images/2.0x/qr.png new file mode 100644 index 0000000..6392496 Binary files /dev/null and b/images/2.0x/qr.png differ diff --git a/images/3.0x/logo_b_40.png b/images/3.0x/logo_b_40.png new file mode 100644 index 0000000..53e8338 Binary files /dev/null and b/images/3.0x/logo_b_40.png differ diff --git a/images/3.0x/qr.png b/images/3.0x/qr.png new file mode 100644 index 0000000..31c0ce2 Binary files /dev/null and b/images/3.0x/qr.png differ diff --git a/images/logo_b_40.png b/images/logo_b_40.png new file mode 100644 index 0000000..9e90624 Binary files /dev/null and b/images/logo_b_40.png differ diff --git a/images/qr.png b/images/qr.png new file mode 100644 index 0000000..6f4d550 Binary files /dev/null and b/images/qr.png differ diff --git a/lib/common/color.dart b/lib/common/color.dart index bf057e6..6e44bbf 100644 --- a/lib/common/color.dart +++ b/lib/common/color.dart @@ -12,6 +12,9 @@ class DarkColors { static const bottomNavColor = Color(0xCCA0A3BD); static const transactionColor = Color(0x4DA0A3BD); static const greenColor = Color(0xFF168A3C); + // 20% opacity + static const greenColorMask = Color(0x66168A3C); + static const redColor = Color(0xFFDD4556); // gold static const yellowColor = Color(0xFFE8B000); diff --git a/lib/common/global.dart b/lib/common/global.dart index 10b7303..e83ae59 100644 --- a/lib/common/global.dart +++ b/lib/common/global.dart @@ -43,10 +43,10 @@ class Global { static String buildNumber = ''; static const String rpcURL = 'https://testnet-rpc.xdagj.org'; - static const String explorURL = 'https://testexplorer.xdag.io/api'; + static const String explorURL = 'https://testexplorer.xdag.io'; static const String mainRpcURL = 'https://mainnet-rpc.xdagj.org'; - static const String mainExplorURL = 'https://mainnet-explorer.xdagj.org/api'; + static const String mainExplorURL = 'https://mainnet-explorer.xdagj.org'; static const bool isTest = false; diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index ff10bd5..091fb38 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -120,8 +120,14 @@ "contact_tips":"Bitte beachten Sie, dass Kontakte nur lokal auf diesem Gerät gespeichert werden. Wenn Sie die App löschen, gehen Ihre Kontakte dauerhaft verloren und können nicht wiederhergestellt werden.", "no_contacts":"Keine Kontakte", "tips":"Tipps", - "wallet_tips":"Wischen Sie den Eintrag nach rechts, um das Wallet zu löschen。", + "wallet_tips":"Wischen Sie das Element nach links, um die Brieftasche zu löschen.", "hide_balance":"Guthaben ausblenden", "contact_address_repeat": "Kontaktadresse existiert bereits", - "no_wallets":"Keine Wallet" + "no_wallets":"Keine Wallet", + "view_in_explorer":"Im Explorer anzeigen", + "details":"Details", + "sent":"Gesendet", + "received":"Empfangen", + "qr_code":"QR-code", + "save_to_album":"In Album speichern" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 88d7e27..3b0f892 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -120,8 +120,14 @@ "contact_tips":"Please note that contacts are only stored locally on this device. If you delete the app, your contacts will be permanently lost and cannot be recovered.", "no_contacts":"Any contact", "tips":"Tips", - "wallet_tips":"Swipe the item to the right to delete the wallet.", + "wallet_tips":"Swipe the item to the left to delete the wallet.", "hide_balance":"Hide Balance", "contact_address_repeat":"Contact address already exists", - "no_wallets":"Any wallet" + "no_wallets":"Any wallet", + "view_in_explorer":"View in explorer", + "details":"Details", + "sent":"Sent", + "received":"Received", + "qr_code":"QR Code", + "save_to_album":"Save to album" } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 4ccc523..e363b25 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -120,8 +120,14 @@ "contact_tips": "Ten en cuenta que los contactos se almacenan solo localmente en este dispositivo. Si eliminas la aplicación, tus contactos se perderán permanentemente y no se podrán recuperar.", "no_contacts": "Cualquier contacto", "tips": "Consejos", - "wallet_tips": "Desliza el elemento hacia la derecha para eliminar la billetera.", + "wallet_tips":"Desliza el elemento hacia la izquierda para eliminar la billetera.", "hide_balance": "Ocultar saldo", "contact_address_repeat": "La dirección del contacto ya existe", - "no_wallets": "Cualquier cartera" + "no_wallets": "Cualquier cartera", + "view_in_explorer": "Ver en el explorador", + "details": "Detalles", + "sent": "Enviado", + "received": "Recibido", + "qr_code": "Código QR", + "save_to_album": "Guardar en el álbum" } \ No newline at end of file diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 5c7fbc6..d517a33 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -48,11 +48,11 @@ "enter_password": "Entrez le code secret", "use_biometrics_tips_1": "Appuyez pour utiliser Face ID", "use_biometrics_tips_2": "Appuyez pour utiliser Touch ID", - "use_biometrics_tips_3": "Appuyez pour utiliser les biométriques", + "use_biometrics_tips_3": "Appuyez pour utiliser contrôle biométrique", "use_password": "Utiliser le code secret", "use_biometrics_1": "Utiliser Face ID", "use_biometrics_2": "Utiliser Touch ID", - "use_biometrics_3": "Utiliser les biométriques", + "use_biometrics_3": "Utiliser contrôle biométrique", "delete_tip": "Si vous supprimez votre portefeuille sans le sauvegarder, vous perdrez tous vos actifs numériques de manière permanente et ils ne pourront pas être récupérés.", "write_Down_Mnemonics": "Noter les mnémoniques", "write_Down_PrivateKey": "Noter la clé privée", @@ -63,10 +63,10 @@ "change_password_success": "Code secret changé avec succès", "enable_biometrics_1": "Activer Face ID", "enable_biometrics_2": "Activer Touch ID", - "enable_biometrics_3": "Activer les biométriques", + "enable_biometrics_3": "Activer contrôle biométrique", "disenable_biometrics_1": "Désactiver Face ID", "disenable_biometrics_2": "Désactiver Touch ID", - "disenable_biometrics_3": "Désactiver les biométriques", + "disenable_biometrics_3": "Désactiver contrôle biométrique", "no_transactions": "Aucune transaction", "send_on": "Envoyé le", "receive_on": "Reçu le", @@ -120,8 +120,14 @@ "contact_tips":"Veuillez noter que les contacts sont uniquement stockés localement sur cet appareil. Si vous supprimez l'application, vos contacts seront définitivement perdus et ne pourront pas être récupérés.", "no_contacts":"Aucun contact", "tips":"Conseils", - "wallet_tips":"Balayez l'élément vers la droite pour supprimer le portefeuille.", + "wallet_tips":"Balayez l'élément vers la gauche pour supprimer le portefeuille.", "hide_balance":"Masquer le solde", "contact_address_repeat": "L'adresse de contact existe déjà", - "no_wallets": "Aucun portefeuille" + "no_wallets": "Aucun portefeuille", + "view_in_explorer": "Voir dans l'explorateur", + "details": "Détails", + "sent": "Envoyé", + "received": "Reçu", + "qr_code": "Code QR", + "save_to_album": "Enregistrer dans l'album" } \ No newline at end of file diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 5e98bc5..8707f5a 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -120,8 +120,14 @@ "contact_tips": "Si prega di notare che i contatti sono conservati solo localmente su questo dispositivo. Se si elimina l'app, i contatti verranno persi in modo permanente e non saranno recuperabili.", "no_contacts": "Nessun contatto", "tips": "Suggerimenti", - "wallet_tips": "Scorri l'elemento verso destra per eliminare il portafoglio", + "wallet_tips": "Scorri l'elemento a sinistra per eliminare il portafoglio.", "hide_balance": "Nascondi saldo", "contact_address_repeat": "L'indirizzo del contatto è già stato aggiunto", - "no_wallets": "Nessun portafoglio" + "no_wallets": "Nessun portafoglio", + "view_in_explorer": "Visualizza in Explorer", + "details":"dettagli", + "sent":"Inviato", + "received":"Ricevuto", + "qr_code":"Codice QR", + "save_to_album":"Salva in album" } \ No newline at end of file diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 49c9c0d..f67f8c2 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -120,8 +120,14 @@ "contact_tips":"連絡先はこのデバイスにのみ保存されます。アプリを削除すると、連絡先は永久に失われ、回復できません。", "no_contacts":"連絡先がありません", "tips":"ヒント", - "wallet_tips":"ウォレットを削除するには、アイテムを右にスワイプしてください。", + "wallet_tips":"財布を削除するには、アイテムを左にスワイプしてください。", "hide_balance":"残高を非表示", "contact_address_repeat": "連絡先がすでに存在しています", - "no_wallets":"ウォレットがありません" + "no_wallets":"ウォレットがありません", + "view_in_explorer":"エクスプローラーで表示", + "details":"詳細", + "sent":"送信", + "received":"受け取る", + "qr_code":"QRコード", + "save_to_album":"アルバムに保存" } \ No newline at end of file diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index fa8d18e..1390443 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -120,8 +120,14 @@ "contact_tips":"Обратите внимание, что контакты хранятся только локально на этом устройстве. Если вы удалите приложение, ваши контакты будут навсегда потеряны и не могут быть восстановлены.", "no_contacts":"Нет контактов", "tips":"Советы", - "wallet_tips":"Чтобы удалить кошелек, проведите элемент вправо.", + "wallet_tips":"Чтобы удалить кошелек, проведите элемент влево.", "hide_balance":"Скрыть баланс", "contact_address_repeat": "Контактный адрес уже существует", - "no_wallets":"Нет кошельков" + "no_wallets":"Нет кошельков", + "view_in_explorer":"Посмотреть в исследователе", + "details":"Детали", + "sent":"Отправлено", + "received":"Получено", + "qr_code":"QR-код", + "save_to_album":"Сохранить в альбом" } \ No newline at end of file diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 01d1f2e..46109e2 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -120,8 +120,14 @@ "contact_tips":"请注意,联系人仅存储在本地设备上。如果您删除应用程序,您的联系人将永久丢失,无法找回。", "no_contacts":"没有联系人", "tips":"提示", - "wallet_tips":"向右滑动该项以删除钱包。", + "wallet_tips":"向左滑动该项以删除钱包。", "hide_balance":"隐藏余额", "contact_address_repeat": "联系地址已存在", - "no_wallets":"没有钱包" + "no_wallets":"没有钱包", + "view_in_explorer":"在浏览器中查看", + "details":"详情", + "sent":"发送", + "received":"接收", + "qr_code":"二维码", + "save_to_album":"保存到相册" } \ No newline at end of file diff --git a/lib/model/config_modal.dart b/lib/model/config_modal.dart index 5d79459..b6db261 100644 --- a/lib/model/config_modal.dart +++ b/lib/model/config_modal.dart @@ -21,8 +21,8 @@ class ConfigModal extends ChangeNotifier { LangItem('Français', const Locale('fr', 'FR')), LangItem('Русский', const Locale('ru', 'RU')), LangItem('Deutsch', const Locale('de', 'DE')), - LangItem('Spanish', const Locale('es', 'ES')), - LangItem('Italy', const Locale('it', 'IT')), + LangItem('Español', const Locale('es', 'ES')), + LangItem('Italiano', const Locale('it', 'IT')), ]; static final List netWorks = ["MainNet", "TestNet"]; @@ -37,8 +37,9 @@ class ConfigModal extends ChangeNotifier { return walletConfig.network == 0 ? Global.mainRpcURL : Global.rpcURL; } - String getCurrentExplorer() { - return walletConfig.network == 0 ? Global.mainExplorURL : Global.explorURL; + String getCurrentExplorer({isApi = true}) { + var url = walletConfig.network == 0 ? Global.mainExplorURL : Global.explorURL; + return isApi ? '$url/api' : url; } changeNetwork(int pos) async { diff --git a/lib/page/common/check_page.dart b/lib/page/common/check_page.dart index cdc6973..6a7099c 100644 --- a/lib/page/common/check_page.dart +++ b/lib/page/common/check_page.dart @@ -47,9 +47,13 @@ class _CheckPageState extends State { Widget build(BuildContext context) { ConfigModal config = Provider.of(context); String tipsText = type == 0 ? AppLocalizations.of(context).use_biometrics_tips_1 : AppLocalizations.of(context).use_biometrics_tips_2; + String btnTex = type == 0 ? AppLocalizations.of(context).use_biometrics_1 : AppLocalizations.of(context).use_biometrics_2; if (type > 0 && Platform.isAndroid) { tipsText = AppLocalizations.of(context).use_biometrics_tips_3; } + if (Platform.isAndroid) { + btnTex = AppLocalizations.of(context).use_biometrics_3; + } var padding = Helper.isDesktop ? 10.0 : ScreenHelper.topPadding; return Scaffold( backgroundColor: DarkColors.bgColor, @@ -95,12 +99,15 @@ class _CheckPageState extends State { setState(() { type = type == -1 ? Global.devBiometricsType : -1; }); + if (type != -1) { + check(); + } }, child: Container( height: 40, padding: const EdgeInsets.symmetric(horizontal: 20), child: Center( - child: Text(AppLocalizations.of(context).use_password, style: Helper.fitChineseFont(context, const TextStyle(fontSize: 16, fontWeight: FontWeight.w700, color: Colors.white))), + child: Text(type == -1 ? btnTex : AppLocalizations.of(context).use_password, style: Helper.fitChineseFont(context, const TextStyle(fontSize: 16, fontWeight: FontWeight.w700, color: Colors.white))), ), ), ) diff --git a/lib/page/common/langs_select.dart b/lib/page/common/langs_select.dart index 34760a2..1230345 100644 --- a/lib/page/common/langs_select.dart +++ b/lib/page/common/langs_select.dart @@ -73,7 +73,7 @@ class NetWorkSelectPage extends StatelessWidget { ConfigModal config = Provider.of(context); double bottomPadding = ScreenHelper.bottomPadding; List netWorks = ConfigModal.netWorks; - double height = 60 + (bottomPadding > 0 ? bottomPadding : 20) + 70 * netWorks.length + 10; + double height = 60 + (bottomPadding > 0 ? bottomPadding : 20) + 70 * netWorks.length + 10 + 30; return ModalFrame( height: height, title: AppLocalizations.of(context).select_network, diff --git a/lib/page/common/webview.dart b/lib/page/common/webview.dart index 9d50c03..7cd1aa2 100644 --- a/lib/page/common/webview.dart +++ b/lib/page/common/webview.dart @@ -32,6 +32,9 @@ class _WebViewPageState extends State { onPageStarted: (String url) {}, onPageFinished: (String url) {}, onWebResourceError: (WebResourceError error) {}, + onNavigationRequest: (NavigationRequest request) { + return NavigationDecision.navigate; + }, ), ); diff --git a/lib/page/detail/receive_page.dart b/lib/page/detail/receive_page.dart index 6dc769a..b9c7a0b 100644 --- a/lib/page/detail/receive_page.dart +++ b/lib/page/detail/receive_page.dart @@ -21,81 +21,70 @@ class ReceivePage extends StatelessWidget { double marginH = 20; double paddingH = 15; TextStyle titleStyle = Helper.fitChineseFont(context, const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w400)); - TextStyle addressStyle = Helper.fitChineseFont(context, const TextStyle(color: Colors.white54, fontSize: 16, fontWeight: FontWeight.w700)); + // TextStyle addressStyle = Helper.fitChineseFont(context, const TextStyle(color: Colors.white54, fontSize: 16, fontWeight: FontWeight.w700)); return ModalFrame( - title: '${AppLocalizations.of(context).receive} XDAG', + title: AppLocalizations.of(context).qr_code, + child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - ContentBox( - marginH: marginH, - child: Padding( - padding: const EdgeInsets.all(15.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(AppLocalizations.of(context).show_QR, style: titleStyle), - const SizedBox(height: 15), - Center( - child: Container( - width: 250, - height: 250, - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10)), - child: Center( - child: QrImage(data: wallet.address, version: QrVersions.auto), - ), - ), - ), - ], - ), - ), - ), ContentBox( marginH: marginH, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: EdgeInsets.fromLTRB(paddingH, 15, paddingH, 15), + padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(AppLocalizations.of(context).share_wallet_address, style: titleStyle), - const SizedBox(height: 8), - Text(wallet.address, style: addressStyle), + Text(AppLocalizations.of(context).show_QR, style: titleStyle), + const SizedBox(height: 15), + Center( + child: Container( + width: 250, + height: 250, + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10)), + child: Center( + child: QrImage( + data: wallet.address, + version: QrVersions.auto, + embeddedImage: const AssetImage('images/logo_b_40.png'), + embeddedImageStyle: QrEmbeddedImageStyle( + size: const Size(40, 40), + ), + ), + ), + ), + ), ], ), ), Container(height: 1, color: DarkColors.bgColor), - SizedBox( - height: 50, - child: Row( - children: [ - Expanded( - child: Button( - icon: Icons.copy_rounded, - onPressed: () { - Clipboard.setData(ClipboardData(text: wallet.address)); - Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); - }, - title: AppLocalizations.of(context).copy, - )), - // Container(width: 1, color: DarkColors.bgColor), - // Expanded( - // child: Button( - // icon: Icons.share_rounded, - // onPressed: () {}, - // title: AppLocalizations.of(context).share, - // )), - ], - ), - ), + // SizedBox( + // height: 50, + // child: Row( + // children: [ + // Expanded( + // child: Button( + // icon: Icons.download, + // onPressed: () { + // Clipboard.setData(ClipboardData(text: wallet.address)); + // Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); + // }, + // title: AppLocalizations.of(context).save_to_album, + // )), + // ], + // ), + // ), ], ), ), ], - )); + ), + ), + ); } } @@ -126,14 +115,6 @@ class Button extends StatelessWidget { @override Widget build(BuildContext context) { TextStyle btnStyle = Helper.fitChineseFont(context, const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w400)); - return MyCupertinoButton( - padding: EdgeInsets.zero, - onPressed: onPressed, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [Icon(icon, color: Colors.white, size: 20), const SizedBox(width: 10), Text(title, style: btnStyle)], - ), - ); + return MyCupertinoButton(padding: EdgeInsets.zero, onPressed: onPressed, child: Text(title, style: btnStyle)); } } diff --git a/lib/page/detail/transaction_page.dart b/lib/page/detail/transaction_page.dart index a6c40d3..8b76bf6 100644 --- a/lib/page/detail/transaction_page.dart +++ b/lib/page/detail/transaction_page.dart @@ -1,13 +1,16 @@ +import 'dart:io'; + import 'package:dio/dio.dart'; -import 'package:extended_text/extended_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher_string.dart'; import 'package:xdag/common/color.dart'; import 'package:xdag/common/helper.dart'; import 'package:xdag/model/config_modal.dart'; import 'package:xdag/model/contacts_modal.dart'; import 'package:xdag/model/wallet_modal.dart'; +import 'package:xdag/page/common/webview.dart'; import 'package:xdag/widget/button.dart'; import 'package:xdag/widget/desktop.dart'; import 'package:xdag/widget/modal_frame.dart'; @@ -28,7 +31,7 @@ class _TransactionPageState extends State { String fee = ""; String hash = ""; String transactionState = 'Pending'; - double height = 430; + // double height = 430; final dio = Dio(); CancelToken cancelToken = CancelToken(); @@ -98,10 +101,23 @@ class _TransactionPageState extends State { // 查询 otherAddress 是否在 contacts.contactsList 中 ContactsItem otherContact = contacts.contactsList.firstWhere((element) => element.address == otherAddress, orElse: () => ContactsItem("", otherAddress)); - // if(transaction.amount) + ConfigModal config = Provider.of(context); return ModalFrame( - height: height, - title: isSend ? AppLocalizations.of(context).send : AppLocalizations.of(context).receive, + // height: height, + title: '', + titleWidget: Center( + child: Container( + padding: const EdgeInsets.fromLTRB(10, 5, 10, 5), + decoration: BoxDecoration( + color: config.walletConfig.network == 1 ? DarkColors.redColorMask2 : DarkColors.greenColorMask, + borderRadius: BorderRadius.circular(5), + ), + child: Text( + config.walletConfig.network == 1 ? "TestNet" : "MainNet", + style: Helper.fitChineseFont(context, const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Colors.white70)), + ), + ), + ), rightBtn: CircleButton( icon: Icons.refresh, onPressed: () { @@ -114,82 +130,112 @@ class _TransactionPageState extends State { isShowRightCloseButton: true, child: Column( children: [ - Text(isSend ? '-${transaction.amount} XDAG' : '+${transaction.amount} XDAG', style: Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 22, fontWeight: FontWeight.w700, color: isSend ? DarkColors.bottomNavColor : DarkColors.greenColor))), - const SizedBox(height: 5), - if (transaction.status == 'pending') - Text( - "${AppLocalizations.of(context).state}: $transactionState", - style: Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w400, color: transactionState == 'Accepted' ? DarkColors.greenColor : DarkColors.redColor)), - ) - else - const SizedBox(), - if (transaction.time.isEmpty) - const SizedBox() - else - Text( - "${isSend ? AppLocalizations.of(context).send_on : AppLocalizations.of(context).receive_on} ${Helper.formatFullTime(transaction.time)} UTC", - style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w400, color: Colors.white54)), - ), - const SizedBox(height: 25), - if (isLoading) - const SizedBox( - height: 152, - child: Center( - child: SizedBox( - width: 50, - height: 50, - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(DarkColors.mainColor), - ), - ), - ), - ) - else - Column( + Expanded( + child: SingleChildScrollView( + child: Column( children: [ - MyCupertinoButton( - padding: EdgeInsets.zero, - child: TransactionButton( - showCopy: true, - borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8)), - title: isSend ? AppLocalizations.of(context).receiver : AppLocalizations.of(context).sender, - value: otherContact.name.isEmpty ? otherContact.address : otherContact.name, - leftIcon: otherContact.name.isEmpty ? const Icon(Icons.add, color: Colors.white, size: 10) : const Icon(Icons.person, color: Colors.white, size: 10), + const SizedBox(height: 10), + Text(isSend ? '-${transaction.amount} XDAG' : '+${transaction.amount} XDAG', style: Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 24, fontWeight: FontWeight.w700, color: isSend ? DarkColors.bottomNavColor : DarkColors.greenColor))), + const SizedBox(height: 5), + if (transaction.status == 'pending') + Text( + "${AppLocalizations.of(context).state}: $transactionState", + style: Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w400, color: transactionState == 'Accepted' ? DarkColors.greenColor : DarkColors.redColor)), + ) + else + const SizedBox(), + if (transaction.time.isEmpty) + const SizedBox() + else + Text( + "${isSend ? AppLocalizations.of(context).send_on : AppLocalizations.of(context).receive_on} ${Helper.formatFullTime(transaction.time)} UTC", + style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w400, color: Colors.white54)), + ), + const SizedBox(height: 25), + if (isLoading) + const SizedBox( + height: 152, + child: Center( + child: SizedBox( + width: 50, + height: 50, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(DarkColors.mainColor), + ), + ), ), - onPressed: () { - Navigator.of(context).pop(otherContact); - }), - const SizedBox(height: 1), - MyCupertinoButton( - padding: EdgeInsets.zero, - child: TransactionButton(showCopy: true, title: "Hash", value: hash), - onPressed: () { - Clipboard.setData(ClipboardData(text: hash)); - Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); - }), - const SizedBox(height: 1), - MyCupertinoButton( - padding: EdgeInsets.zero, - child: TransactionButton(showCopy: true, title: AppLocalizations.of(context).block_address, value: transaction.blockAddress), - onPressed: () { - Clipboard.setData(ClipboardData(text: transaction.blockAddress)); - Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); - }), - const SizedBox(height: 1), - TransactionButton( - showCopy: false, - title: AppLocalizations.of(context).fee, - value: '$fee XDAG', - ), - const SizedBox(height: 1), - TransactionButton( - showCopy: false, - title: AppLocalizations.of(context).remark, - value: transaction.remark, - borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)), + ) + else + Column( + children: [ + MyCupertinoButton( + padding: EdgeInsets.zero, + child: TransactionButton( + showCopy: true, + borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8)), + title: isSend ? AppLocalizations.of(context).receiver : AppLocalizations.of(context).sender, + value: otherContact.name.isEmpty ? otherContact.address : otherContact.name, + leftIcon: otherContact.name.isEmpty ? const Icon(Icons.person_add, color: Colors.white, size: 10) : const Icon(Icons.person, color: Colors.white, size: 10), + ), + onPressed: () { + Navigator.of(context).pop(otherContact); + }), + const SizedBox(height: 1), + MyCupertinoButton( + padding: EdgeInsets.zero, + child: TransactionButton(showCopy: true, title: "Hash", value: hash), + onPressed: () { + Clipboard.setData(ClipboardData(text: hash)); + Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); + }), + const SizedBox(height: 1), + MyCupertinoButton( + padding: EdgeInsets.zero, + child: TransactionButton(showCopy: true, title: AppLocalizations.of(context).block_address, value: transaction.blockAddress), + onPressed: () { + Clipboard.setData(ClipboardData(text: transaction.blockAddress)); + Helper.showToast(context, AppLocalizations.of(context).copied_to_clipboard); + }), + const SizedBox(height: 1), + TransactionButton(showCopy: false, title: AppLocalizations.of(context).fee, value: '$fee XDAG', borderRadius: transaction.remark.isNotEmpty ? BorderRadius.zero : const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8))), + const SizedBox(height: 1), + if (transaction.remark.isNotEmpty) + TransactionButton( + showCopy: false, + title: AppLocalizations.of(context).remark, + value: transaction.remark, + borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)), + ), + ], + ), + ], + ), + )), + Container( + margin: EdgeInsets.fromLTRB(15, 20, 15, ScreenHelper.bottomPadding > 0 ? ScreenHelper.bottomPadding : 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Button( + text: AppLocalizations.of(context).view_in_explorer, + width: ScreenHelper.screenWidth - 30, + bgColor: DarkColors.blockColor, + textColor: Colors.white, + onPressed: () async { + // Navigator.of(context).pop(true); + ConfigModal config = Provider.of(context, listen: false); + var url = '${config.getCurrentExplorer(isApi: false)}/block/${transaction.blockAddress}'; + if (Platform.isAndroid || Platform.isIOS) { + Navigator.pushNamed(context, '/webview', arguments: WebViewPageRouteParams(url: url, title: "")); + } else { + launchUrlString(url, mode: LaunchMode.externalApplication); + } + // print(transaction.blockAddress); + }, ), ], - ) + ), + ), ], ), ); @@ -203,47 +249,61 @@ class TransactionShowDetail extends StatelessWidget { @override Widget build(BuildContext context) { bool isSameAddress = transaction.from == transaction.to; + ConfigModal config = Provider.of(context); return ModalFrame( - height: 430, + height: transaction.remark.isEmpty ? 400 : 450, title: '', + titleWidget: Center( + child: Container( + padding: const EdgeInsets.fromLTRB(10, 5, 10, 5), + decoration: BoxDecoration( + color: config.walletConfig.network == 1 ? DarkColors.redColorMask2 : DarkColors.greenColorMask, + borderRadius: BorderRadius.circular(5), + ), + child: Text( + config.walletConfig.network == 1 ? "TestNet" : "MainNet", + style: Helper.fitChineseFont(context, const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Colors.white70)), + ), + ), + ), isHideLeftDownButton: true, isShowRightCloseButton: true, child: Column( children: [ Expanded( - child: Column( - children: [ - Text('${transaction.amount} XDAG', textAlign: TextAlign.center, style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 22, fontWeight: FontWeight.w700, color: DarkColors.greenColor))), - const SizedBox(height: 20), - TransactionButton( - showCopy: false, - readFont: isSameAddress, - borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8)), - title: AppLocalizations.of(context).receiver, - value: transaction.to, - ), - const SizedBox(height: 1), - TransactionButton( - showCopy: false, - readFont: isSameAddress, - borderRadius: BorderRadius.zero, - title: AppLocalizations.of(context).sender, - value: transaction.from, - ), - const SizedBox(height: 1), - TransactionButton( - showCopy: false, - title: AppLocalizations.of(context).fee, - value: '0.00 XDAG', - ), - const SizedBox(height: 1), - TransactionButton( - showCopy: false, - title: AppLocalizations.of(context).remark, - value: transaction.remark, - borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)), - ), - ], + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 10), + Text('${transaction.amount} XDAG', textAlign: TextAlign.center, style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 24, fontWeight: FontWeight.w700, color: DarkColors.greenColor))), + const SizedBox(height: 20), + TransactionButton( + showCopy: false, + readFont: isSameAddress, + borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8)), + title: AppLocalizations.of(context).receiver, + value: transaction.to, + ), + const SizedBox(height: 1), + TransactionButton( + showCopy: false, + readFont: isSameAddress, + borderRadius: BorderRadius.zero, + title: AppLocalizations.of(context).sender, + value: transaction.from, + ), + const SizedBox(height: 1), + TransactionButton(showCopy: false, title: AppLocalizations.of(context).fee, value: '0.00 XDAG', borderRadius: transaction.remark.isNotEmpty ? BorderRadius.zero : const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8))), + const SizedBox(height: 1), + if (transaction.remark.isNotEmpty) + TransactionButton( + showCopy: false, + title: AppLocalizations.of(context).remark, + value: transaction.remark, + borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)), + ), + ], + ), )), Container( margin: EdgeInsets.fromLTRB(15, 20, 15, ScreenHelper.bottomPadding > 0 ? ScreenHelper.bottomPadding : 20), @@ -279,49 +339,35 @@ class TransactionButton extends StatelessWidget { @override Widget build(BuildContext context) { - TextStyle titleStyle = Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 16, fontWeight: FontWeight.w400, color: Colors.white54)); - TextStyle valueStyle = Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 12, fontWeight: FontWeight.w700, color: readFont ? DarkColors.redColor : Colors.white)); - Widget icon = showCopy == true - ? Container( - margin: const EdgeInsets.only(left: 5), - width: 20, - height: 20, - decoration: const BoxDecoration( - color: DarkColors.bgColor, - borderRadius: BorderRadius.all(Radius.circular(14)), - ), - child: leftIcon ?? const Icon(Icons.copy_rounded, size: 10, color: Colors.white)) - : const SizedBox(width: 0); + TextStyle titleStyle = Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 16, fontWeight: FontWeight.w700, color: Colors.white54)); + TextStyle valueStyle = Helper.fitChineseFont(context, TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w400, color: readFont ? DarkColors.redColor : Colors.white)); return Container( - height: 50, + constraints: const BoxConstraints(minHeight: 50.0), margin: const EdgeInsets.fromLTRB(15, 0, 15, 0), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: DarkColors.blockColor, borderRadius: borderRadius, ), child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const SizedBox(width: 10), Text(title, style: titleStyle), - // const Spacer(), - const SizedBox(width: 10), - // Text(value, style: valueStyle, maxLines: 2), - Expanded( - child: ExtendedText( - value, - textAlign: TextAlign.right, - maxLines: 1, - style: valueStyle, - overflowWidget: TextOverflowWidget( - position: TextOverflowPosition.middle, - align: TextOverflowAlign.center, - child: Text('...', style: valueStyle), - ), - ), + const SizedBox(width: 20), + Flexible( + fit: FlexFit.tight, + child: Text(value, textAlign: TextAlign.right, maxLines: 5, style: valueStyle), ), - - icon, - const SizedBox(width: 10), + if (showCopy == true) + Container( + margin: const EdgeInsets.only(left: 5), + width: 24, + height: 24, + decoration: const BoxDecoration( + color: DarkColors.bgColor, + borderRadius: BorderRadius.all(Radius.circular(15)), + ), + child: leftIcon ?? const Icon(Icons.copy_rounded, size: 12, color: Colors.white)) ], ), ); diff --git a/lib/page/wallet/wallet_page.dart b/lib/page/wallet/wallet_page.dart index 38dfbdf..76107c3 100644 --- a/lib/page/wallet/wallet_page.dart +++ b/lib/page/wallet/wallet_page.dart @@ -21,7 +21,6 @@ class WalletPageState extends State { final _refreshIndicatorKey = GlobalKey(); String _crurrentAddress = ""; int _network = 0; - // String lastTime = ""; List list = []; final dio = Dio(); CancelToken cancelToken = CancelToken(); @@ -56,8 +55,10 @@ class WalletPageState extends State { _onConfigModalChange() { WalletModal walletModal = Provider.of(context, listen: false); - if (_network != Provider.of(context, listen: false).walletConfig.network) { + var newNetwork = Provider.of(context, listen: false).walletConfig.network; + if (_network != newNetwork) { _refreshIndicatorKey.currentState?.deactivate(); + _network = newNetwork; setState(() { list = []; }); diff --git a/lib/widget/home_button.dart b/lib/widget/home_button.dart index 8d3e18f..ef5754c 100644 --- a/lib/widget/home_button.dart +++ b/lib/widget/home_button.dart @@ -7,7 +7,8 @@ class HomeHeaderButton extends StatelessWidget { final VoidCallback? onPressed; final String title; final String icon; - const HomeHeaderButton({super.key, required this.title, required this.icon, this.onPressed}); + final Widget? iconWidget; + const HomeHeaderButton({super.key, this.iconWidget, required this.title, required this.icon, this.onPressed}); @override Widget build(BuildContext context) { @@ -27,7 +28,7 @@ class HomeHeaderButton extends StatelessWidget { children: [ Row( children: [ - Image.asset(icon, width: 20, height: 20), + iconWidget ?? Image.asset(icon, width: 20, height: 20), const Spacer(), ], ), diff --git a/lib/widget/home_transaction_item.dart b/lib/widget/home_transaction_item.dart index 0b155f3..ae75082 100644 --- a/lib/widget/home_transaction_item.dart +++ b/lib/widget/home_transaction_item.dart @@ -69,8 +69,8 @@ class WalletTransactionItem extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(isSnapshot ? AppLocalizations.of(context).snapshot : (isSend ? AppLocalizations.of(context).send : AppLocalizations.of(context).receive), style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white))), - const SizedBox(height: 3), + Text(isSnapshot ? AppLocalizations.of(context).snapshot : (isSend ? AppLocalizations.of(context).sent : AppLocalizations.of(context).received), style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white))), + const SizedBox(height: 5), Text('${Helper.formatTime(transaction.time)} UTC', style: Helper.fitChineseFont(context, const TextStyle(decoration: TextDecoration.none, fontSize: 12, fontWeight: FontWeight.w400, color: Colors.white54))), ], ), diff --git a/lib/widget/home_widget.dart b/lib/widget/home_widget.dart index 231a547..0825104 100644 --- a/lib/widget/home_widget.dart +++ b/lib/widget/home_widget.dart @@ -86,7 +86,6 @@ class _HomeMainState extends State { double screenHeight = MediaQuery.of(context).size.height; double contentHeight = ScreenHelper.topPadding + 55 + 20 + (ScreenHelper.bottomPadding > 0 ? ScreenHelper.bottomPadding : 20) + 50 + 20 + 50; double h = (screenHeight - contentHeight) / 2; - print(screenHeight); return Stack( fit: StackFit.expand, children: [ diff --git a/lib/widget/modal_frame.dart b/lib/widget/modal_frame.dart index 92d4a83..26a730e 100644 --- a/lib/widget/modal_frame.dart +++ b/lib/widget/modal_frame.dart @@ -27,11 +27,12 @@ class CircleButton extends StatelessWidget { class ModalFrame extends StatelessWidget { final Widget child; final String title; + final Widget? titleWidget; final double? height; final bool? isHideLeftDownButton; final bool? isShowRightCloseButton; final Widget? rightBtn; - const ModalFrame({super.key, required this.child, required this.title, this.height, this.isHideLeftDownButton, this.isShowRightCloseButton, this.rightBtn}); + const ModalFrame({super.key, this.titleWidget, required this.child, required this.title, this.height, this.isHideLeftDownButton, this.isShowRightCloseButton, this.rightBtn}); @override Widget build(BuildContext context) { @@ -62,7 +63,7 @@ class ModalFrame extends StatelessWidget { children: [ leftButton, const SizedBox(width: 10), - Expanded(child: Text(title, textAlign: TextAlign.center, style: Helper.fitChineseFont(context, const TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.w700)))), + Expanded(child: titleWidget ?? Text(title, textAlign: TextAlign.center, style: Helper.fitChineseFont(context, const TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.w700)))), const SizedBox(width: 10), rightButton, ], diff --git a/lib/widget/wallet_header.dart b/lib/widget/wallet_header.dart index dc92c70..eb29788 100644 --- a/lib/widget/wallet_header.dart +++ b/lib/widget/wallet_header.dart @@ -71,25 +71,23 @@ class WalletHeader extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - if (config.walletConfig.network == 1) - Column( - children: [ - Container( - padding: const EdgeInsets.fromLTRB(10, 3, 10, 3), - decoration: BoxDecoration( - color: DarkColors.redColorMask, - borderRadius: BorderRadius.circular(5), - ), - child: Text( - "TEST", - style: Helper.fitChineseFont(context, const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: Colors.white70)), - ), + // if (config.walletConfig.network == 1) + Column( + children: [ + Container( + padding: const EdgeInsets.fromLTRB(10, 3, 10, 3), + decoration: BoxDecoration( + color: config.walletConfig.network == 1 ? DarkColors.redColorMask2 : DarkColors.greenColorMask, + borderRadius: BorderRadius.circular(5), ), - const SizedBox(height: 8), - ], - ) - else - const SizedBox(), + child: Text( + config.walletConfig.network == 1 ? "TestNet" : "MainNet", + style: Helper.fitChineseFont(context, const TextStyle(fontSize: 10, fontWeight: FontWeight.w400, color: Colors.white70)), + ), + ), + const SizedBox(height: 8), + ], + ), Text( wallet.hideBalance == true ? "****" : "${wallet.amount} XDAG", style: Helper.fitChineseFont(context, const TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white)), @@ -156,8 +154,8 @@ class WalletHeader extends StatelessWidget { const SizedBox(width: 15), Expanded( child: HomeHeaderButton( - title: AppLocalizations.of(context).receive, - icon: 'images/receive.png', + title: AppLocalizations.of(context).qr_code, + icon: 'images/qr.png', onPressed: () async { Helper.changeAndroidStatusBar(true); await Helper.showBottomSheet(context, const ReceivePage()); diff --git a/pubspec.lock b/pubspec.lock index 3b58e20..28f7e7c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1096,10 +1096,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "47663d51a9061451aa3880a214ee9a65dcbb933b77bc44388e194279ab3ccaf6" + sha256: "1a37bdbaaf5fbe09ad8579ab09ecfd473284ce482f900b5aea27cf834386a567" url: "https://pub.dev" source: hosted - version: "4.0.7" + version: "4.2.0" webview_flutter_android: dependency: transitive description: @@ -1112,10 +1112,10 @@ packages: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "1939c39e2150fb4d30fd3cc59a891a49fed9935db53007df633ed83581b6117b" + sha256: "78715dc442b7849dbde74e92bb67de1cecf5addf95531c5fb474e72f5fe9a507" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.3.0" webview_flutter_wkwebview: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 75b0a07..f017caf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.13+14 +version: 1.0.14+15 environment: sdk: '>=2.19.2 <3.0.0' @@ -51,7 +51,7 @@ dependencies: easy_refresh: ^3.3.1 bip39: ^1.0.6 bip32: ^2.0.0 - webview_flutter: ^4.0.7 + webview_flutter: ^4.2.0 crypto: ^3.0.2 fast_base58: ^0.2.1 secp256k1: ^0.3.0 @@ -218,6 +218,16 @@ flutter: - images/2.0x/contacts1.png - images/3.0x/contacts1.png + - images/logo_b_40.png + - images/2.0x/logo_b_40.png + - images/3.0x/logo_b_40.png + + - images/qr.png + - images/2.0x/qr.png + - images/3.0x/qr.png + + + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware