From be86ca2bca8ab9ef762fb0b53f567425cab4b7b6 Mon Sep 17 00:00:00 2001 From: maznnwell <181888996+maznnwell@users.noreply.github.com> Date: Wed, 11 Dec 2024 06:57:39 +0000 Subject: [PATCH] Rearchitecture of Dashboard features (#131) * feat: Create dev run configuration * refactor: dashboard blocs. * mods: delegation cubit. tests. * mods: delegation cubit - tests. * feat: Improve the DashboardCubit class * feat: Finish the delegation widgets * feat: Use a CardData object to hold the title and description of a card * feat: Fill up the balance widgets * fix: Assign the correct card data to the CardType.balance value * feat: Improve the DashboardCubit so that the cubits that implement it can specify the state * feat: Fill up the dual coin stats widgets * fix: Navigate after the current frame finished rendering * fix: Apply fixes with dart fix --apply * fix: Use the super parameters * refactor: Replace deprecated methods or classes * feat: Use very_good_analysis for linter rules and solve some issues with dart fix --apply * feat: Add localization * feat: Exemplify how to use AppLocalizations * feat: Enable l10n for the dev entry point also * fix: Regenerate the windows folder * refactor: Delete unused widgets * feat: Add documentation of public members inside the dual_coin_stats folder * feat: Replace Pillars with PillarsCard * feat: Replace RealtimeStatistics with RealtimeStatisticsCard * feat: Fill up the sentinels widgets * refactor: Change fields' order * fix: Documentation * feat: Fill the staking widgets * fix: Documentation * feat: Fill up the total hourly transactions widgets * feat: Delete unused blocs * feat: Tweak balance features * refactor: Delete unused bloc * feat: Create the node sync status feature * feat: Delete unused class * feat: Adapt Transfer widget to the new architecture * chore: Redo dashboard.dart exports * chore: Delete unused feature balance_dashboard * feat: Use localization version strings for generating CardData objects * chore: Improve documentation * chore: Rename CubitStatus class to DashboardStatus * chore: Improve documentation of the balance feature * chore: Improve documentation and solve linter issues * feat: Make the DashboardCubit a HydratedCubit * feat: Make custom exceptions serializable and move them to separated feature folders * feat: Structure the error handling mechanism * feat: Localize some strings * refactor: Make custom exceptions extend from DashboardCubitException * refactor: Restructure new code in a single folder * chore: Move node_sync_status inside features folder * chore: Improve documentation * feat: Add always_specify_types to the linter rules and run dart fix * chore: Solve linter hints in rearchitecture folder * chore: Improve documentation * chore: Create and use the state_copy_with documentation template * feat: transfer BLoC rearchitecture complete. added receive_transaction & transfer_widget_balance * feat: Add tests for delegation cubit * feat: Add asserts for the TimerState class * feat: Restructure exceptions * feat: Improve error logging * chore: Update Zenon SDK * chore: Delete flutter_lints dependency * chore: Update dependencies * feat: Change the interval at which the node sync status is fetched * chore: Rename and change location of a refresh interval constant * feat: Don't emit the loading state if the current one has a success status * feat: Add required named parameters to the TimerCubit constructor * feat: Run dart format in rearchitecture folder * feat: Delete the CubitException class * testing dashboard wip * chore: Improve documentation * testing dashboard wip * feat: Create constants for specific UI gaps * feat: dashboard unit testing added * removed unused import * node sync status tests added * feat: Create the new app themes and improve the UI of the back of the new card scaffold * feat: Create a cubit for hiding the front widget of the NewCardScaffold * feat: Log errors * feat: Make password field obscure text by default * feat: Create the newTheme and isDarkMode getters to the BuildContextExtension * feat: Rename local variable * feat: Delete the font specification from the new themes * fix: Getting setting and getting the new theme * chore: Rename 'newTheme' getter to 'theme' * feat: Adapt widgets to the new theme data * chore: Rename getter 'theme' to 'themeData' * refactor: Cubit initializations * chore: Use documentation templates for cubit state's fromJson and toJson * fix: Some tests * chore: Improve documentation * feat: Align the text field and the button on the center axis * chore: Repair dart analysis hints * feat: Remove styling from left side chart titles and use the default generated Y interval * feat: Revert some Windows changes * feat: Associated a custom URL deep linking scheme with the app - on Windows * feat: Restore bundling local libraries * feat: Restore updating Git metadata * fix: Fetching the dlls that will be installed in the Windows app folder and re-enable the generation of git metadata * shell script modified * build generated changes * fix: Fetching the dlls that will be installed in the Linux app folder * fix: Finding the correct path for .so files * feat: Update znn sdk and ledger * feat: Reset local git metadata * feat: Init kNumOfPillars --------- Co-authored-by: kossmmos <184493470+kossmmos@users.noreply.github.com> --- .metadata | 14 +- analysis_options.yaml | 53 +- l10n.yaml | 3 + lib/blocs/accelerator/accelerator.dart | 1 - .../accelerator/accelerator_balance_bloc.dart | 2 +- lib/blocs/accelerator/create_phase_bloc.dart | 8 +- .../accelerator/create_project_bloc.dart | 10 +- lib/blocs/accelerator/project_list_bloc.dart | 99 ++- .../project_vote_breakdown_bloc.dart | 4 +- .../accelerator/submit_donation_bloc.dart | 12 +- lib/blocs/accelerator/update_phase_bloc.dart | 10 +- lib/blocs/accelerator/vote_project_bloc.dart | 10 +- lib/blocs/auto_receive_tx_worker.dart | 22 +- lib/blocs/auto_unlock_htlc_worker.dart | 17 +- lib/blocs/base_bloc.dart | 2 +- .../base_bloc_for_reloading_indicator.dart | 2 +- lib/blocs/base_bloc_with_refresh_mixin.dart | 2 +- lib/blocs/blocs.dart | 10 +- lib/blocs/dashboard/balance_bloc.dart | 10 +- .../dashboard/balance_dashboard_bloc.dart | 20 - lib/blocs/dashboard/dashboard.dart | 10 - lib/blocs/dashboard/dashboard_base_bloc.dart | 48 -- lib/blocs/dashboard/delegation_bloc.dart | 25 - lib/blocs/dashboard/dual_coin_stats_bloc.dart | 20 - lib/blocs/dashboard/pillars_bloc.dart | 14 - .../dashboard/realtime_statistics_bloc.dart | 50 -- lib/blocs/dashboard/sentinels_bloc.dart | 11 - lib/blocs/dashboard/staking_bloc.dart | 37 - .../total_hourly_transactions_bloc.dart | 38 - lib/blocs/decrypt_wallet_file_bloc.dart | 2 +- lib/blocs/hide_widget_status_bloc.dart | 4 +- lib/blocs/infinite_scroll_bloc.dart | 21 +- lib/blocs/key_store_file_bloc.dart | 6 +- lib/blocs/ledger_wallet_file_bloc.dart | 10 +- lib/blocs/lock_bloc.dart | 2 +- lib/blocs/node_sync_status_bloc.dart | 37 - lib/blocs/notifications_bloc.dart | 6 +- .../htlc_swap/complete_htlc_swap_bloc.dart | 14 +- .../p2p_swap/htlc_swap/htlc_swap_bloc.dart | 4 +- .../htlc_swap/initial_htlc_for_swap_bloc.dart | 42 +- .../htlc_swap/join_htlc_swap_bloc.dart | 12 +- .../reclaim_htlc_swap_funds_bloc.dart | 10 +- .../recover_htlc_swap_funds_bloc.dart | 4 +- .../htlc_swap/start_htlc_swap_bloc.dart | 22 +- lib/blocs/p2p_swap/p2p_swaps_list_bloc.dart | 7 +- .../p2p_swap/periodic_p2p_swap_base_bloc.dart | 4 +- lib/blocs/pillars/delegate_button_bloc.dart | 8 +- .../pillars/disassemble_pillar_bloc.dart | 8 +- .../pillars/pillar_rewards_history_bloc.dart | 4 +- lib/blocs/pillars/pillars.dart | 1 - lib/blocs/pillars/pillars_deploy_bloc.dart | 10 +- .../pillars/pillars_deposit_qsr_bloc.dart | 8 +- lib/blocs/pillars/pillars_qsr_info_bloc.dart | 6 +- .../pillars/pillars_withdraw_qsr_bloc.dart | 8 +- lib/blocs/pillars/undelegate_button_bloc.dart | 8 +- lib/blocs/pillars/update_pillar_bloc.dart | 8 +- lib/blocs/plasma/cancel_plasma_bloc.dart | 10 +- lib/blocs/plasma/plasma.dart | 1 - lib/blocs/plasma/plasma_list_bloc.dart | 6 +- lib/blocs/plasma/plasma_options_bloc.dart | 8 +- lib/blocs/plasma/plasma_stats_bloc.dart | 6 +- lib/blocs/refresh_bloc_mixin.dart | 2 +- .../sentinels/disassemble_button_bloc.dart | 8 +- .../sentinels/sentinel_deposit_qsr_bloc.dart | 8 +- .../sentinels/sentinel_qsr_info_bloc.dart | 6 +- .../sentinels/sentinel_register_bloc.dart | 8 +- .../sentinel_rewards_history_bloc.dart | 4 +- .../sentinels/sentinel_withdraw_qsr_bloc.dart | 8 +- lib/blocs/sentinels/sentinels.dart | 1 - .../settings/account_chain_stats_bloc.dart | 23 +- lib/blocs/settings/general_stats_bloc.dart | 4 +- lib/blocs/settings/peers_bloc.dart | 2 +- lib/blocs/settings/settings.dart | 1 - lib/blocs/staking/cancel_stake_bloc.dart | 8 +- lib/blocs/staking/staking.dart | 1 - lib/blocs/staking/staking_options_bloc.dart | 10 +- .../staking/staking_rewards_history_bloc.dart | 4 +- lib/blocs/tokens/burn_token_bloc.dart | 10 +- lib/blocs/tokens/issue_token_bloc.dart | 10 +- lib/blocs/tokens/mint_token_bloc.dart | 10 +- lib/blocs/tokens/token_map_bloc.dart | 57 +- lib/blocs/tokens/tokens.dart | 1 - lib/blocs/tokens/tokens_bloc.dart | 2 +- lib/blocs/tokens/transfer_ownership_bloc.dart | 8 +- .../transfer/receive_transaction_bloc.dart | 4 +- lib/blocs/transfer/send_payment_bloc.dart | 10 +- lib/blocs/transfer/transfer.dart | 1 - .../transfer_widgets_balance_bloc.dart | 10 +- .../wallet_connect/chains/nom_service.dart | 93 +-- .../wallet_connect_sessions_bloc.dart | 6 +- lib/embedded_node/embedded_node.dart | 40 +- lib/handlers/htlc_swaps_handler.dart | 56 +- lib/l10n/app_en.arb | 29 + lib/main.dart | 106 +-- lib/main_dev.dart | 441 ++++++++++ lib/model/account_chain_stats.dart | 6 +- lib/model/basic_dropdown_item.dart | 4 +- lib/model/block_data.dart | 4 +- lib/model/database/wallet_notification.dart | 29 +- lib/model/general_stats.dart | 16 +- lib/model/model.dart | 4 +- lib/model/navigation_arguments.dart | 2 +- lib/model/p2p_swap/htlc_swap.dart | 78 +- lib/model/p2p_swap/p2p_swap.dart | 42 +- lib/model/pillars_qsr_info.dart | 4 +- lib/model/plasma_info_wrapper.dart | 4 +- lib/model/sentinels_qsr_info.dart | 4 +- .../features/balance/balance.dart | 4 + .../features/balance/cubit/balance_cubit.dart | 50 ++ .../balance/cubit/balance_cubit.g.dart | 32 + .../features/balance/cubit/balance_state.dart | 48 ++ .../balance/exceptions/exceptions.dart | 1 + .../exceptions/no_balance_exception.dart | 34 + .../exceptions/no_balance_exception.g.dart | 18 + .../features/balance/view/balance_card.dart | 47 ++ .../balance/widgets/balance_address.dart | 86 ++ .../balance/widgets/balance_chart.dart | 77 ++ .../balance/widgets/balance_chart_legend.dart | 58 ++ .../balance/widgets/balance_empty.dart | 19 + .../balance/widgets/balance_error.dart | 22 + .../balance/widgets/balance_loading.dart | 20 + .../balance/widgets/balance_populated.dart | 125 +++ .../features/balance/widgets/widgets.dart | 7 + .../delegation/cubit/delegation_cubit.dart | 57 ++ .../delegation/cubit/delegation_cubit.g.dart | 33 + .../delegation/cubit/delegation_state.dart | 41 + .../features/delegation/delegation.dart | 4 + .../delegation/exceptions/exceptions.dart | 1 + .../no_delegation_stats_exception.dart | 33 + .../no_delegation_stats_exception.g.dart | 19 + .../delegation/view/delegation_card.dart | 41 + .../delegation/widgets/delegation_empty.dart | 14 + .../delegation/widgets/delegation_error.dart | 17 + .../widgets/delegation_loading.dart | 13 + .../widgets/delegation_populated.dart | 59 ++ .../features/delegation/widgets/widgets.dart | 4 + .../cubit/dual_coin_stats_cubit.dart | 58 ++ .../cubit/dual_coin_stats_cubit.g.dart | 33 + .../cubit/dual_coin_stats_state.dart | 43 + .../dual_coin_stats/dual_coin_stats.dart | 3 + .../view/dual_coin_stats_card.dart | 39 + .../widgets/dual_coin_stats_chart.dart | 79 ++ .../widgets/dual_coin_stats_chart_legend.dart | 39 + .../dual_coin_stats_chart_legend_item.dart | 29 + .../widgets/dual_coin_stats_empty.dart | 17 + .../widgets/dual_coin_stats_error.dart | 21 + .../widgets/dual_coin_stats_loading.dart | 18 + .../widgets/dual_coin_stats_populated.dart | 50 ++ .../dual_coin_stats/widgets/widgets.dart | 7 + lib/rearchitecture/features/features.dart | 10 + .../cubit/node_sync_status_cubit.dart | 74 ++ .../cubit/node_sync_status_cubit.g.dart | 47 ++ .../cubit/node_sync_status_state.dart | 33 + .../node_sync_status/node_sync_status.dart | 3 + .../view/node_sync_status_icon.dart | 28 + .../widgets/node_sync_status_empty.dart | 22 + .../widgets/node_sync_status_error.dart | 26 + .../widgets/node_sync_status_loading.dart | 29 + .../widgets/node_sync_status_populated.dart | 146 ++++ .../node_sync_status/widgets/widgets.dart | 4 + .../features/pillars/cubit/pillars_cubit.dart | 40 + .../pillars/cubit/pillars_cubit.g.dart | 30 + .../features/pillars/cubit/pillars_state.dart | 40 + .../features/pillars/pillars.dart | 3 + .../features/pillars/view/pillars_card.dart | 39 + .../pillars/widgets/pillars_empty.dart | 17 + .../pillars/widgets/pillars_error.dart | 20 + .../pillars/widgets/pillars_loading.dart | 17 + .../pillars/widgets/pillars_populated.dart | 43 + .../features/pillars/widgets/widgets.dart | 4 + .../cubit/realtime_statistics_cubit.dart | 104 +++ .../cubit/realtime_statistics_cubit.g.dart | 35 + .../cubit/realtime_statistics_state.dart | 43 + .../exceptions/exceptions.dart | 1 + .../no_blocks_available_exception.dart | 35 + .../no_blocks_available_exception.g.dart | 19 + .../realtime_statistics.dart | 4 + .../view/realtime_statistics_card.dart | 42 + .../widgets/realtime_statistics_empty.dart | 14 + .../widgets/realtime_statistics_error.dart | 17 + .../widgets/realtime_statistics_loading.dart | 13 + .../realtime_statistics_populated.dart | 46 ++ .../widgets}/realtime_txs_chart.dart | 49 +- .../realtime_statistics/widgets/widgets.dart | 4 + .../sentinels/cubit/sentinels_cubit.dart | 39 + .../sentinels/cubit/sentinels_cubit.g.dart | 33 + .../sentinels/cubit/sentinels_state.dart | 42 + .../features/sentinels/sentinels.dart | 3 + .../sentinels/view/sentinels_card.dart | 39 + .../sentinels/widgets/sentinels_empty.dart | 17 + .../sentinels/widgets/sentinels_error.dart | 20 + .../sentinels/widgets/sentinels_loading.dart | 17 + .../widgets/sentinels_populated.dart | 47 ++ .../features/sentinels/widgets/widgets.dart | 4 + .../features/staking/cubit/staking_cubit.dart | 59 ++ .../staking/cubit/staking_cubit.g.dart | 32 + .../features/staking/cubit/staking_state.dart | 40 + .../staking/exceptions/exceptions.dart | 1 + .../no_active_skaking_entries_exception.dart | 35 + ...no_active_skaking_entries_exception.g.dart | 19 + .../features/staking/staking.dart | 4 + .../features/staking/view/staking_card.dart | 42 + .../staking/widgets/staking_empty.dart | 17 + .../staking/widgets/staking_error.dart | 20 + .../staking/widgets/staking_loading.dart | 17 + .../staking/widgets/staking_populated.dart | 64 ++ .../features/staking/widgets/widgets.dart | 4 + .../total_hourly_transactions_cubit.dart | 79 ++ .../total_hourly_transactions_cubit.g.dart | 33 + .../total_hourly_transactions_state.dart | 38 + .../exceptions/exceptions.dart | 1 + .../not_enough_momentums_exception.dart | 35 + .../not_enough_momentums_exception.g.dart | 19 + .../total_hourly_transactions.dart | 4 + .../view/total_hourly_transactions_card.dart | 40 + .../total_hourly_transactions_empty.dart | 17 + .../total_hourly_transactions_error.dart | 20 + .../total_hourly_transactions_loading.dart | 17 + .../total_hourly_transactions_populated.dart | 31 + .../widgets/widgets.dart | 4 + .../features/transfer/transfer.dart | 1 + .../features/transfer/view/transfer_card.dart | 70 ++ lib/rearchitecture/rearchitecture.dart | 1 + .../utils/constants/app_sizes.dart | 10 + .../utils/constants/constants.dart | 3 + .../utils/constants/durations.dart | 5 + .../utils/constants/strings.dart | 2 + lib/rearchitecture/utils/cubits/cubits.dart | 2 + .../utils/cubits/hide_widget/hide_widget.dart | 1 + .../cubits/hide_widget/hide_widget_cubit.dart | 83 ++ .../hide_widget/hide_widget_cubit.g.dart | 30 + .../cubits/hide_widget/hide_widget_state.dart | 61 ++ .../utils/cubits/timer_cubit.dart | 133 +++ .../utils/cubits/timer_state.dart | 79 ++ .../exceptions/cubit_failure_exception.dart | 34 + .../exceptions/cubit_failure_exception.g.dart | 19 + .../utils/exceptions/exceptions.dart | 2 + .../utils/exceptions/syrius_exception.dart | 49 ++ .../extensions/buildcontext_extension.dart | 17 + .../utils/extensions/extensions.dart | 2 + .../extensions/sync_state_extension.dart | 16 + .../utils/models/card/card.dart | 2 + .../utils/models/card/card_data.dart | 12 + .../utils/models/card/card_type.dart | 87 ++ lib/rearchitecture/utils/models/models.dart | 1 + .../utils/theming/new_app_themes.dart | 94 +++ .../utils/url_protocol/api.dart | 52 ++ .../utils/url_protocol/protocol.dart | 20 + .../utils/url_protocol/windows_protocol.dart | 70 ++ lib/rearchitecture/utils/utils.dart | 7 + .../utils/widgets/card_scaffold_header.dart | 62 ++ .../widgets/card_scaffold_password_field.dart | 49 ++ .../utils/widgets/new_card_scaffold.dart | 315 ++++++++ lib/rearchitecture/utils/widgets/widgets.dart | 1 + .../change_wallet_password_screen.dart | 37 +- .../development_intialization_screen.dart | 69 ++ lib/screens/dump_mnemonic_screen.dart | 17 +- lib/screens/export/export.dart | 1 - .../export/export_wallet_info_screen.dart | 48 +- .../export/export_wallet_password_screen.dart | 38 +- lib/screens/node_management_screen.dart | 59 +- .../onboarding/access_wallet_screen.dart | 12 +- .../onboarding/create_key_store_screen.dart | 16 +- .../onboarding/create_ledger_screen.dart | 16 +- .../hardware_wallet/hardware_wallet.dart | 3 +- .../hardware_wallet_device_choice_screen.dart | 86 +- .../hardware_wallet_password_screen.dart | 30 +- .../import_wallet/import_wallet.dart | 1 - .../import_wallet_decrypt_screen.dart | 34 +- .../import_wallet_password_screen.dart | 28 +- .../import_wallet_seed_choice_screen.dart | 26 +- .../onboarding/new_wallet/new_wallet.dart | 1 - .../new_wallet_confirm_seed_screen.dart | 118 ++- .../new_wallet_password_screen.dart | 30 +- .../new_wallet_seed_choice_screen.dart | 39 +- lib/screens/onboarding/onboarding.dart | 5 +- .../onboarding/wallet_success_screen.dart | 14 +- lib/screens/project_details_screen.dart | 32 +- lib/screens/reset_wallet_screen.dart | 26 +- lib/screens/screens.dart | 6 +- lib/screens/splash_screen.dart | 27 +- lib/screens/stepper_screen.dart | 24 +- lib/services/htlc_swaps_service.dart | 54 +- lib/services/shared_prefs_service.dart | 4 +- lib/services/web3wallet_service.dart | 73 +- lib/utils/account_block_utils.dart | 46 +- lib/utils/address_utils.dart | 44 +- lib/utils/app_colors.dart | 54 +- lib/utils/app_theme.dart | 134 +-- lib/utils/clipboard_utils.dart | 6 +- lib/utils/color_utils.dart | 2 +- lib/utils/constants.dart | 40 +- lib/utils/device_utils.dart | 16 +- lib/utils/extensions.dart | 16 +- lib/utils/file_utils.dart | 4 +- lib/utils/format_utils.dart | 24 +- lib/utils/functions.dart | 16 +- lib/utils/global.dart | 18 +- lib/utils/init_utils.dart | 14 +- lib/utils/input_validators.dart | 12 +- lib/utils/navigation_utils.dart | 6 +- lib/utils/network_utils.dart | 19 +- lib/utils/node_utils.dart | 56 +- lib/utils/notification_utils.dart | 3 +- lib/utils/notifiers/notifiers.dart | 1 - .../notifiers/text_scaling_notifier.dart | 12 +- lib/utils/pair.dart | 31 +- lib/utils/toast_utils.dart | 18 +- lib/utils/utils.dart | 4 +- lib/utils/wallet_file.dart | 86 +- lib/utils/wallet_utils.dart | 16 +- lib/utils/widget_utils.dart | 14 +- lib/utils/zts_utils.dart | 8 +- lib/widgets/charts/pillar_rewards_chart.dart | 16 +- .../charts/sentinel_rewards_chart.dart | 24 +- lib/widgets/charts/staking_rewards_chart.dart | 16 +- lib/widgets/main_app_container.dart | 764 +++++++----------- .../accelerator_donation_stepper.dart | 79 +- .../accelerator_donations.dart | 16 +- .../accelerator_project_list.dart | 62 +- .../accelerator_project_list_item.dart | 196 +++-- .../accelerator_stats.dart | 38 +- .../accelerator_widgets/create_phase.dart | 18 +- .../accelerator_widgets/create_project.dart | 16 +- .../phase_creation_stepper.dart | 87 +- .../accelerator_widgets/phase_list.dart | 12 +- .../project_creation_stepper.dart | 95 ++- .../accelerator_widgets/project_list.dart | 42 +- .../accelerator_widgets/projects_stats.dart | 60 +- .../update_phase_stepper.dart | 70 +- .../dashboard_widgets/balance.dart | 228 ------ .../dashboard_widgets/dashboard_widgets.dart | 9 - .../dashboard_widgets/delegation_stats.dart | 77 -- .../dashboard_widgets/dual_coin_stats.dart | 119 --- .../dashboard_widgets/pillars.dart | 63 -- .../dashboard_widgets/plasma_stats.dart | 33 +- .../realtime_statistics.dart | 66 -- .../dashboard_widgets/sentinels.dart | 65 -- .../dashboard_widgets/staking.dart | 76 -- .../total_hourly_transactions.dart | 52 -- .../dashboard_widgets/transfer.dart | 74 -- .../help_widgets/about_card.dart | 38 +- .../help_widgets/community_card.dart | 23 +- .../help_widgets/update_card.dart | 4 +- .../p2p_swap_widgets/detail_row.dart | 28 +- .../p2p_swap_widgets/htlc_card.dart | 98 +-- .../htlc_swap_details_widget.dart | 40 +- .../modals/join_native_swap_modal.dart | 130 ++- .../modals/native_p2p_swap_modal.dart | 180 ++--- .../modals/p2p_swap_warning_modal.dart | 14 +- .../modals/recover_deposit_modal.dart | 64 +- .../modals/start_native_swap_modal.dart | 68 +- .../p2p_swap_options_button.dart | 35 +- .../p2p_swap_options_card.dart | 46 +- .../p2p_swap_widgets/p2p_swaps_card.dart | 50 +- .../p2p_swap_widgets/p2p_swaps_list_item.dart | 75 +- .../pillar_widgets/create_pillar.dart | 26 +- .../pillar_widgets/pillar_collect.dart | 19 +- .../pillar_widgets/pillar_list_widget.dart | 138 ++-- .../pillar_widgets/pillar_rewards.dart | 9 +- .../pillar_stepper_container.dart | 237 +++--- .../pillar_widgets/pillar_update_stepper.dart | 81 +- .../plasma_list/plasma_list.dart | 54 +- .../plasma_options/plasma_options.dart | 91 ++- .../sentinel_widgets/create_sentinel.dart | 20 +- .../sentinel_widgets/sentinel_collect.dart | 22 +- .../sentinel_list_widget.dart | 67 +- .../sentinel_widgets/sentinel_rewards.dart | 10 +- .../sentinel_stepper_container.dart | 165 ++-- .../settings_widgets/account_chain_stats.dart | 58 +- .../settings_widgets/addresses.dart | 54 +- .../settings_widgets/backup.dart | 10 +- .../settings_widgets/display.dart | 40 +- .../settings_widgets/general.dart | 72 +- .../settings_widgets/node_management.dart | 69 +- .../settings_widgets/peers.dart | 26 +- .../settings_widgets/security.dart | 119 ++- .../settings_widgets/wallet_options.dart | 36 +- .../staking_widgets/stake_collect.dart | 19 +- .../staking_list/staking_list.dart | 75 +- .../staking_options/staking_options.dart | 58 +- .../staking_widgets/staking_rewards.dart | 10 +- .../token_widgets/create_token.dart | 20 +- .../token_widgets/token_balance.dart | 32 +- .../token_widgets/token_card.dart | 216 +++-- .../token_widgets/token_favorite.dart | 22 +- .../token_widgets/token_map.dart | 14 +- .../token_widgets/token_stepper.dart | 159 ++-- .../latest_transactions.dart | 106 ++- .../latest_transactions_transfer_widget.dart | 101 +-- .../pending_transactions.dart | 92 +-- .../receive/receive_large.dart | 41 +- .../receive/receive_medium.dart | 42 +- .../receive/receive_small.dart | 13 +- .../transfer_widgets/send/send_large.dart | 90 +-- .../transfer_widgets/send/send_medium.dart | 58 +- .../transfer_widgets/send/send_small.dart | 15 +- .../wallet_connect_camera_card.dart | 37 +- .../wallet_connect_pairing_list_card.dart | 24 +- .../wallet_connect_qr_card.dart | 60 +- .../wallet_connect_session_list_card.dart | 32 +- .../wallet_connect_uri_card.dart | 29 +- .../accelerator_project_details.dart | 41 +- .../access_wallet_fluid_cell.dart | 23 +- .../reusable_widgets/amount_info_column.dart | 21 +- .../reusable_widgets/available_balance.dart | 8 +- .../reusable_widgets/bullet_point_card.dart | 30 +- .../buttons/elevated_button.dart | 24 +- .../buttons/instruction_button.dart | 16 +- .../buttons/loading_button.dart | 51 +- .../buttons/material_icon_button.dart | 18 +- .../buttons/onboarding_button.dart | 11 +- .../buttons/outlined_button.dart | 51 +- .../buttons/send_payment_button.dart | 20 +- .../buttons/settings_button.dart | 10 +- .../buttons/stepper_button.dart | 36 +- .../transfer_toggle_card_size_button.dart | 12 +- .../reusable_widgets/cancel_timer.dart | 20 +- .../reusable_widgets/chart/chart_legend.dart | 15 +- .../chart/standard_chart.dart | 89 +- .../chart/standard_line_chart_bar_data.dart | 4 +- .../chart/standard_pie_chart.dart | 15 +- .../reusable_widgets/context_menu_region.dart | 10 +- .../custom_expandable_panel.dart | 14 +- .../custom_material_stepper.dart | 88 +- .../reusable_widgets/custom_slider.dart | 84 +- .../reusable_widgets/custom_table.dart | 117 ++- lib/widgets/reusable_widgets/dialogs.dart | 32 +- .../dotted_border_info_widget.dart | 20 +- .../dropdown/addresses_dropdown.dart | 18 +- .../dropdown/basic_dropdown.dart | 20 +- .../dropdown/coin_dropdown.dart | 22 +- .../reusable_widgets/error_widget.dart | 18 +- .../exchange_rate_widget.dart | 40 +- .../formatted_amount_with_tooltip.dart | 14 +- .../reusable_widgets/icons/clear_icon.dart | 8 +- .../icons/copy_to_clipboard_icon.dart | 20 +- lib/widgets/reusable_widgets/icons/icons.dart | 2 +- .../reusable_widgets/icons/link_icon.dart | 15 +- .../icons/standard_tooltip_icon.dart | 14 +- .../important_text_container.dart | 25 +- .../infinite_scroll_table.dart | 101 ++- .../input_fields/amount_input_field.dart | 44 +- .../input_fields/amount_suffix_widgets.dart | 16 +- .../input_fields/disabled_address_field.dart | 8 +- .../input_fields/input_field.dart | 65 +- .../input_fields/labeled_input_container.dart | 27 +- .../input_fields/password_input_field.dart | 20 +- .../layout_scaffold/card_scaffold.dart | 109 ++- .../layout_scaffold/overscroll_remover.dart | 2 +- .../standard_fluid_layout.dart | 21 +- .../layout_scaffold/widget_animator.dart | 14 +- .../reusable_widgets/loading_info_text.dart | 24 +- .../reusable_widgets/loading_widget.dart | 10 +- .../reusable_widgets/modals/base_modal.dart | 30 +- .../reusable_widgets/notification_widget.dart | 37 +- .../reusable_widgets/number_animation.dart | 68 +- lib/widgets/reusable_widgets/plasma_icon.dart | 12 +- .../reusable_widgets/progress_bars.dart | 58 +- .../reusable_widgets/receive_qr_image.dart | 94 ++- .../reusable_widgets/reusable_widgets.dart | 14 +- .../reusable_widgets/seed/seed_choice.dart | 40 +- .../reusable_widgets/seed/seed_grid.dart | 84 +- .../reusable_widgets/select_file_widget.dart | 34 +- .../reusable_widgets/settings_address.dart | 62 +- .../reusable_widgets/settings_node.dart | 73 +- .../reusable_widgets/stepper_utils.dart | 16 +- .../reusable_widgets/syrius_checkbox.dart | 8 +- lib/widgets/reusable_widgets/tag_widget.dart | 34 +- .../transfer_icon_legend.dart | 27 +- .../accelerator_tab_child.dart | 12 +- .../dashboard_tab_child.dart | 26 +- .../tab_children_widgets/help_tab_child.dart | 4 +- .../tab_children_widgets/lock_tab_child.dart | 34 +- .../notifications_tab_child.dart | 33 +- .../p2p_swap_tab_child.dart | 10 +- .../pillars_tab_child.dart | 8 +- .../plasma_tab_child.dart | 8 +- .../sentinels_tab_child.dart | 8 +- .../settings_tab_child.dart | 16 +- .../staking_tab_child.dart | 6 +- .../tab_children_widgets.dart | 2 +- .../tokens_tab_child.dart | 8 +- .../transfer_tab_child.dart | 10 +- .../wallet_connect_tab_child.dart | 4 +- lib/widgets/widgets.dart | 1 - linux/CMakeLists.txt | 107 ++- macos/Podfile | 2 +- macos/Runner.xcodeproj/project.pbxproj | 6 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- macos/Runner/AppDelegate.swift | 2 +- pubspec.lock | 412 +++++++--- pubspec.yaml | 28 +- run_configurations/dev.run.xml | 6 + test/balance/cubit/balance_cubit_test.dart | 183 +++++ .../cubit/delegation_cubit_test.dart | 171 ++++ .../cubit/dual_coin_stats_cubit_test.dart | 171 ++++ test/helpers/hydrated_bloc.dart | 16 + .../cubit/node_sync_status_cubit_test.dart | 161 ++++ test/pillars/cubit/pillars_cubit_test.dart | 152 ++++ .../cubit/realtime_statistics_cubit_test.dart | 226 ++++++ .../sentinels/cubit/sentinels_cubit_test.dart | 178 ++++ test/staking/cubit/staking_cubit_test.dart | 181 +++++ .../total_hourly_transactions_cubit_test.dart | 188 +++++ windows/CMakeLists.txt | 110 ++- windows/flutter/CMakeLists.txt | 3 +- windows/runner/CMakeLists.txt | 25 +- windows/runner/flutter_window.cpp | 10 + windows/runner/main.cpp | 42 +- windows/runner/runner.exe.manifest | 6 - windows/runner/utils.cpp | 15 +- windows/runner/win32_window.cpp | 92 +-- windows/runner/win32_window.h | 25 +- 513 files changed, 12713 insertions(+), 7019 deletions(-) create mode 100644 l10n.yaml delete mode 100644 lib/blocs/dashboard/balance_dashboard_bloc.dart delete mode 100644 lib/blocs/dashboard/dashboard_base_bloc.dart delete mode 100644 lib/blocs/dashboard/delegation_bloc.dart delete mode 100644 lib/blocs/dashboard/dual_coin_stats_bloc.dart delete mode 100644 lib/blocs/dashboard/pillars_bloc.dart delete mode 100644 lib/blocs/dashboard/realtime_statistics_bloc.dart delete mode 100644 lib/blocs/dashboard/sentinels_bloc.dart delete mode 100644 lib/blocs/dashboard/staking_bloc.dart delete mode 100644 lib/blocs/dashboard/total_hourly_transactions_bloc.dart delete mode 100644 lib/blocs/node_sync_status_bloc.dart create mode 100644 lib/l10n/app_en.arb create mode 100644 lib/main_dev.dart create mode 100644 lib/rearchitecture/features/balance/balance.dart create mode 100644 lib/rearchitecture/features/balance/cubit/balance_cubit.dart create mode 100644 lib/rearchitecture/features/balance/cubit/balance_cubit.g.dart create mode 100644 lib/rearchitecture/features/balance/cubit/balance_state.dart create mode 100644 lib/rearchitecture/features/balance/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/features/balance/exceptions/no_balance_exception.dart create mode 100644 lib/rearchitecture/features/balance/exceptions/no_balance_exception.g.dart create mode 100644 lib/rearchitecture/features/balance/view/balance_card.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_address.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_chart.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_chart_legend.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_empty.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_error.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_loading.dart create mode 100644 lib/rearchitecture/features/balance/widgets/balance_populated.dart create mode 100644 lib/rearchitecture/features/balance/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/delegation/cubit/delegation_cubit.dart create mode 100644 lib/rearchitecture/features/delegation/cubit/delegation_cubit.g.dart create mode 100644 lib/rearchitecture/features/delegation/cubit/delegation_state.dart create mode 100644 lib/rearchitecture/features/delegation/delegation.dart create mode 100644 lib/rearchitecture/features/delegation/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.dart create mode 100644 lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.g.dart create mode 100644 lib/rearchitecture/features/delegation/view/delegation_card.dart create mode 100644 lib/rearchitecture/features/delegation/widgets/delegation_empty.dart create mode 100644 lib/rearchitecture/features/delegation/widgets/delegation_error.dart create mode 100644 lib/rearchitecture/features/delegation/widgets/delegation_loading.dart create mode 100644 lib/rearchitecture/features/delegation/widgets/delegation_populated.dart create mode 100644 lib/rearchitecture/features/delegation/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.g.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_state.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/dual_coin_stats.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/view/dual_coin_stats_card.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend_item.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_empty.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_error.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_loading.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_populated.dart create mode 100644 lib/rearchitecture/features/dual_coin_stats/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/features.dart create mode 100644 lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.dart create mode 100644 lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.g.dart create mode 100644 lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_state.dart create mode 100644 lib/rearchitecture/features/node_sync_status/node_sync_status.dart create mode 100644 lib/rearchitecture/features/node_sync_status/view/node_sync_status_icon.dart create mode 100644 lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_empty.dart create mode 100644 lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_error.dart create mode 100644 lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_loading.dart create mode 100644 lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_populated.dart create mode 100644 lib/rearchitecture/features/node_sync_status/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/pillars/cubit/pillars_cubit.dart create mode 100644 lib/rearchitecture/features/pillars/cubit/pillars_cubit.g.dart create mode 100644 lib/rearchitecture/features/pillars/cubit/pillars_state.dart create mode 100644 lib/rearchitecture/features/pillars/pillars.dart create mode 100644 lib/rearchitecture/features/pillars/view/pillars_card.dart create mode 100644 lib/rearchitecture/features/pillars/widgets/pillars_empty.dart create mode 100644 lib/rearchitecture/features/pillars/widgets/pillars_error.dart create mode 100644 lib/rearchitecture/features/pillars/widgets/pillars_loading.dart create mode 100644 lib/rearchitecture/features/pillars/widgets/pillars_populated.dart create mode 100644 lib/rearchitecture/features/pillars/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.g.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_state.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.g.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/realtime_statistics.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/view/realtime_statistics_card.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_empty.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_error.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_loading.dart create mode 100644 lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_populated.dart rename lib/{widgets/charts => rearchitecture/features/realtime_statistics/widgets}/realtime_txs_chart.dart (73%) create mode 100644 lib/rearchitecture/features/realtime_statistics/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.dart create mode 100644 lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.g.dart create mode 100644 lib/rearchitecture/features/sentinels/cubit/sentinels_state.dart create mode 100644 lib/rearchitecture/features/sentinels/sentinels.dart create mode 100644 lib/rearchitecture/features/sentinels/view/sentinels_card.dart create mode 100644 lib/rearchitecture/features/sentinels/widgets/sentinels_empty.dart create mode 100644 lib/rearchitecture/features/sentinels/widgets/sentinels_error.dart create mode 100644 lib/rearchitecture/features/sentinels/widgets/sentinels_loading.dart create mode 100644 lib/rearchitecture/features/sentinels/widgets/sentinels_populated.dart create mode 100644 lib/rearchitecture/features/sentinels/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/staking/cubit/staking_cubit.dart create mode 100644 lib/rearchitecture/features/staking/cubit/staking_cubit.g.dart create mode 100644 lib/rearchitecture/features/staking/cubit/staking_state.dart create mode 100644 lib/rearchitecture/features/staking/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.dart create mode 100644 lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.g.dart create mode 100644 lib/rearchitecture/features/staking/staking.dart create mode 100644 lib/rearchitecture/features/staking/view/staking_card.dart create mode 100644 lib/rearchitecture/features/staking/widgets/staking_empty.dart create mode 100644 lib/rearchitecture/features/staking/widgets/staking_error.dart create mode 100644 lib/rearchitecture/features/staking/widgets/staking_loading.dart create mode 100644 lib/rearchitecture/features/staking/widgets/staking_populated.dart create mode 100644 lib/rearchitecture/features/staking/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.g.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_state.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.g.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/total_hourly_transactions.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/view/total_hourly_transactions_card.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_empty.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_error.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_loading.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_populated.dart create mode 100644 lib/rearchitecture/features/total_hourly_transactions/widgets/widgets.dart create mode 100644 lib/rearchitecture/features/transfer/transfer.dart create mode 100644 lib/rearchitecture/features/transfer/view/transfer_card.dart create mode 100644 lib/rearchitecture/rearchitecture.dart create mode 100644 lib/rearchitecture/utils/constants/app_sizes.dart create mode 100644 lib/rearchitecture/utils/constants/constants.dart create mode 100644 lib/rearchitecture/utils/constants/durations.dart create mode 100644 lib/rearchitecture/utils/constants/strings.dart create mode 100644 lib/rearchitecture/utils/cubits/cubits.dart create mode 100644 lib/rearchitecture/utils/cubits/hide_widget/hide_widget.dart create mode 100644 lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.dart create mode 100644 lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.g.dart create mode 100644 lib/rearchitecture/utils/cubits/hide_widget/hide_widget_state.dart create mode 100644 lib/rearchitecture/utils/cubits/timer_cubit.dart create mode 100644 lib/rearchitecture/utils/cubits/timer_state.dart create mode 100644 lib/rearchitecture/utils/exceptions/cubit_failure_exception.dart create mode 100644 lib/rearchitecture/utils/exceptions/cubit_failure_exception.g.dart create mode 100644 lib/rearchitecture/utils/exceptions/exceptions.dart create mode 100644 lib/rearchitecture/utils/exceptions/syrius_exception.dart create mode 100644 lib/rearchitecture/utils/extensions/buildcontext_extension.dart create mode 100644 lib/rearchitecture/utils/extensions/extensions.dart create mode 100644 lib/rearchitecture/utils/extensions/sync_state_extension.dart create mode 100644 lib/rearchitecture/utils/models/card/card.dart create mode 100644 lib/rearchitecture/utils/models/card/card_data.dart create mode 100644 lib/rearchitecture/utils/models/card/card_type.dart create mode 100644 lib/rearchitecture/utils/models/models.dart create mode 100644 lib/rearchitecture/utils/theming/new_app_themes.dart create mode 100644 lib/rearchitecture/utils/url_protocol/api.dart create mode 100644 lib/rearchitecture/utils/url_protocol/protocol.dart create mode 100644 lib/rearchitecture/utils/url_protocol/windows_protocol.dart create mode 100644 lib/rearchitecture/utils/utils.dart create mode 100644 lib/rearchitecture/utils/widgets/card_scaffold_header.dart create mode 100644 lib/rearchitecture/utils/widgets/card_scaffold_password_field.dart create mode 100644 lib/rearchitecture/utils/widgets/new_card_scaffold.dart create mode 100644 lib/rearchitecture/utils/widgets/widgets.dart create mode 100644 lib/screens/development_intialization_screen.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/balance.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/delegation_stats.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/dual_coin_stats.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/pillars.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/realtime_statistics.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/sentinels.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/staking.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/total_hourly_transactions.dart delete mode 100644 lib/widgets/modular_widgets/dashboard_widgets/transfer.dart create mode 100644 run_configurations/dev.run.xml create mode 100644 test/balance/cubit/balance_cubit_test.dart create mode 100644 test/delegation/cubit/delegation_cubit_test.dart create mode 100644 test/dual_coin_stats/cubit/dual_coin_stats_cubit_test.dart create mode 100644 test/helpers/hydrated_bloc.dart create mode 100644 test/node_sync_status/cubit/node_sync_status_cubit_test.dart create mode 100644 test/pillars/cubit/pillars_cubit_test.dart create mode 100644 test/realtime_statistics/cubit/realtime_statistics_cubit_test.dart create mode 100644 test/sentinels/cubit/sentinels_cubit_test.dart create mode 100644 test/staking/cubit/staking_cubit_test.dart create mode 100644 test/total_hourly_transactions/cubit/total_hourly_transactions_cubit_test.dart diff --git a/.metadata b/.metadata index 0b303072..ea59ad0b 100644 --- a/.metadata +++ b/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - channel: stable + revision: "2663184aa79047d0a33a14a3b607954f8fdd8730" + channel: "stable" project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - platform: windows - create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf - base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 + base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 # User provided section diff --git a/analysis_options.yaml b/analysis_options.yaml index fbd285ef..ed7808e3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,40 +1,21 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. +include: package:very_good_analysis/analysis_options.yaml -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml +analyzer: + exclude: + - "**/*.g.dart" + language: + # I've disabled it so as to make the code compile without + # strict type-checking + strict-casts: false + strict-inference: false + strict-raw-types: false linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. rules: - avoid_print: true # Uncomment to disable the `avoid_print` rule - prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - cancel_subscriptions: true - close_sinks: true - comment_references: true - one_member_abstracts: true - always_use_package_imports: true - avoid_empty_else: true - avoid_slow_async_io: true - avoid_web_libraries_in_flutter: true - control_flow_in_finally: true - empty_statements: true - depend_on_referenced_packages: true - secure_pubspec_urls: true -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options + # Always specifying types will make an unfamiliar codebase more readable for a new developer + # More details about the rule: + # https://gist.github.com/rydmike/fdb53ddd933c37d20e6f3188a936cd4c#file-analysis_options-yaml-L138 + always_specify_types: true + # This rule is in contradiction with always_specify_types, so it must be disabled if the other + # one is enabled + omit_local_variable_types: false \ No newline at end of file diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 00000000..4e6692e5 --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,3 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart \ No newline at end of file diff --git a/lib/blocs/accelerator/accelerator.dart b/lib/blocs/accelerator/accelerator.dart index eb00346e..7bdf81ba 100644 --- a/lib/blocs/accelerator/accelerator.dart +++ b/lib/blocs/accelerator/accelerator.dart @@ -1,4 +1,3 @@ -library accelerator; export 'accelerator_balance_bloc.dart'; export 'create_phase_bloc.dart'; diff --git a/lib/blocs/accelerator/accelerator_balance_bloc.dart b/lib/blocs/accelerator/accelerator_balance_bloc.dart index e42a2440..22a6c0c8 100644 --- a/lib/blocs/accelerator/accelerator_balance_bloc.dart +++ b/lib/blocs/accelerator/accelerator_balance_bloc.dart @@ -8,7 +8,7 @@ class AcceleratorBalanceBloc extends BaseBloc { Future getAcceleratorBalance() async { try { addEvent(null); - AccountInfo accountInfo = await zenon!.ledger.getAccountInfoByAddress( + final AccountInfo accountInfo = await zenon!.ledger.getAccountInfoByAddress( acceleratorAddress, ); if (accountInfo.qsr()! > BigInt.zero || diff --git a/lib/blocs/accelerator/create_phase_bloc.dart b/lib/blocs/accelerator/create_phase_bloc.dart index 905660d5..d68e8bfc 100644 --- a/lib/blocs/accelerator/create_phase_bloc.dart +++ b/lib/blocs/accelerator/create_phase_bloc.dart @@ -14,7 +14,7 @@ class CreatePhaseBloc extends BaseBloc { ) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.accelerator.addPhase( id, name, @@ -25,12 +25,10 @@ class CreatePhaseBloc extends BaseBloc { ); AccountBlockUtils.createAccountBlock(transactionParams, 'create phase') .then( - (block) => addEvent(block), + addEvent, ) .onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/accelerator/create_project_bloc.dart b/lib/blocs/accelerator/create_project_bloc.dart index f56786f9..3c142198 100644 --- a/lib/blocs/accelerator/create_project_bloc.dart +++ b/lib/blocs/accelerator/create_project_bloc.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; @@ -13,7 +15,7 @@ class CreateProjectBloc extends BaseBloc { ) { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.accelerator.createProject( name, description, @@ -25,14 +27,12 @@ class CreateProjectBloc extends BaseBloc { transactionParams, 'creating project', ).then( - (block) { + (AccountBlockTemplate block) { ZenonAddressUtils.refreshBalance(); addEvent(block); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/accelerator/project_list_bloc.dart b/lib/blocs/accelerator/project_list_bloc.dart index ce72805d..bc491cc3 100644 --- a/lib/blocs/accelerator/project_list_bloc.dart +++ b/lib/blocs/accelerator/project_list_bloc.dart @@ -9,11 +9,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ProjectListBloc with RefreshBlocMixin { - List? _allProjects; - - final List selectedProjectsFilterTag = []; - - final PillarInfo? pillarInfo; ProjectListBloc({ required this.pillarInfo, @@ -30,6 +25,11 @@ class ProjectListBloc with RefreshBlocMixin { listenToWsRestart(refreshResults); } + List? _allProjects; + + final List selectedProjectsFilterTag = []; + + final PillarInfo? pillarInfo; void refreshResults() { if (!_onSearchInputChangedSubject.isClosed) { @@ -42,11 +42,11 @@ class ProjectListBloc with RefreshBlocMixin { yield* _fetchList(0); } - static const _pageSize = 10; + static const int _pageSize = 10; - final _subscriptions = CompositeSubscription(); + final CompositeSubscription _subscriptions = CompositeSubscription(); - final _onNewListingStateController = + final BehaviorSubject> _onNewListingStateController = BehaviorSubject>.seeded( InfiniteScrollBlocListingState(), ); @@ -54,11 +54,11 @@ class ProjectListBloc with RefreshBlocMixin { Stream> get onNewListingState => _onNewListingStateController.stream; - final _onPageRequest = StreamController(); + final StreamController _onPageRequest = StreamController(); Sink get onPageRequestSink => _onPageRequest.sink; - final _onSearchInputChangedSubject = BehaviorSubject.seeded(null); + final BehaviorSubject _onSearchInputChangedSubject = BehaviorSubject.seeded(null); Sink get onRefreshResultsRequest => _onSearchInputChangedSubject.sink; @@ -72,18 +72,17 @@ class ProjectListBloc with RefreshBlocMixin { String? get _searchInputTerm => _onSearchInputChangedSubject.value; Stream> _fetchList( - int pageKey) async* { - final lastListingState = _onNewListingStateController.value; + int pageKey,) async* { + final InfiniteScrollBlocListingState lastListingState = _onNewListingStateController.value; try { - final newItems = await getData(pageKey, _pageSize, _searchInputTerm); - final isLastPage = newItems.length < _pageSize; - final nextPageKey = isLastPage ? null : pageKey + 1; - List allItems = [ - ...lastListingState.itemList ?? [], - ...newItems + final List newItems = await getData(pageKey, _pageSize, _searchInputTerm); + final bool isLastPage = newItems.length < _pageSize; + final int? nextPageKey = isLastPage ? null : pageKey + 1; + final List allItems = [ + ...lastListingState.itemList ?? [], + ...newItems, ]; yield InfiniteScrollBlocListingState( - error: null, nextPageKey: nextPageKey, itemList: allItems, ); @@ -110,15 +109,15 @@ class ProjectListBloc with RefreshBlocMixin { String? searchTerm, ) async { _allProjects ??= (await zenon!.embedded.accelerator.getAll()).list; - List results = []; + List results = []; if (searchTerm != null && searchTerm.isNotEmpty) { results = _filterProjectsBySearchKeyWord(_allProjects!, searchTerm).toList(); } else { results = _allProjects!; } - results = (await _filterProjectsAccordingToPillarInfo( - await _filterProjectsByTags(results))); + results = await _filterProjectsAccordingToPillarInfo( + await _filterProjectsByTags(results),); return results.sublist( pageKey * pageSize, (pageKey + 1) * pageSize <= results.length @@ -133,14 +132,14 @@ class ProjectListBloc with RefreshBlocMixin { projects or all owned projects */ Future> _filterProjectsAccordingToPillarInfo( - Set projectList) async { - bool isPillarAddress = pillarInfo != null; + Set projectList,) async { + final bool isPillarAddress = pillarInfo != null; if (isPillarAddress) { return projectList.toList(); } else { - List activeProjects = projectList + final List activeProjects = projectList .where( - (project) => + (Project project) => project.status == AcceleratorProjectStatus.active || kDefaultAddressList.contains(project.owner.toString()), ) @@ -154,11 +153,11 @@ class ProjectListBloc with RefreshBlocMixin { } Set _filterProjectsBySearchKeyWord( - List projects, String searchKeyWord) { - var filteredProjects = {}; + List projects, String searchKeyWord,) { + final Set filteredProjects = {}; filteredProjects.addAll( projects.where( - (element) => + (Project element) => element.id.toString().toLowerCase().contains( searchKeyWord.toLowerCase(), ) && @@ -167,7 +166,7 @@ class ProjectListBloc with RefreshBlocMixin { ); filteredProjects.addAll( projects.where( - (element) => + (Project element) => element.owner.toString().toLowerCase().contains( searchKeyWord.toLowerCase(), ) && @@ -176,7 +175,7 @@ class ProjectListBloc with RefreshBlocMixin { ); filteredProjects.addAll( projects.where( - (element) => + (Project element) => element.name.toLowerCase().contains( searchKeyWord.toLowerCase(), ) && @@ -185,7 +184,7 @@ class ProjectListBloc with RefreshBlocMixin { ); filteredProjects.addAll( projects.where( - (element) => + (Project element) => element.description.toLowerCase().contains( searchKeyWord.toLowerCase(), ) && @@ -194,7 +193,7 @@ class ProjectListBloc with RefreshBlocMixin { ); filteredProjects.addAll( projects.where( - (element) => + (Project element) => element.url.toLowerCase().contains( searchKeyWord.toLowerCase(), ) && @@ -211,25 +210,25 @@ class ProjectListBloc with RefreshBlocMixin { Iterable filteredProjects = projects; if (selectedProjectsFilterTag.contains(AccProjectsFilterTag.myProjects)) { filteredProjects = filteredProjects.where( - (project) => kDefaultAddressList.contains(project.owner.toString()), + (Project project) => kDefaultAddressList.contains(project.owner.toString()), ); } if (selectedProjectsFilterTag .contains(AccProjectsFilterTag.onlyAccepted)) { filteredProjects = filteredProjects.where( - (project) => project.status == AcceleratorProjectStatus.active); + (Project project) => project.status == AcceleratorProjectStatus.active,); } if (selectedProjectsFilterTag .contains(AccProjectsFilterTag.needsVoting)) { votedProjectIds ??= await _getVotedProjectIdsByPillar(filteredProjects); votedPhaseIds ??= await _getVotedPhaseIdsByPillar(filteredProjects); filteredProjects = filteredProjects.where( - (project) => + (Project project) => (project.status == AcceleratorProjectStatus.voting && !votedProjectIds!.contains(project.id)) || - project.phases.any((phase) => + project.phases.any((Phase phase) => phase.status == AcceleratorProjectStatus.voting && - !votedPhaseIds!.contains(phase.id)), + !votedPhaseIds!.contains(phase.id),), ); } if (selectedProjectsFilterTag @@ -237,12 +236,12 @@ class ProjectListBloc with RefreshBlocMixin { votedProjectIds ??= await _getVotedProjectIdsByPillar(filteredProjects); votedPhaseIds ??= await _getVotedPhaseIdsByPillar(filteredProjects); filteredProjects = filteredProjects.where( - (project) => + (Project project) => (project.status == AcceleratorProjectStatus.voting && votedProjectIds!.contains(project.id)) || - project.phases.any((phase) => + project.phases.any((Phase phase) => phase.status == AcceleratorProjectStatus.voting && - votedPhaseIds!.contains(phase.id)), + votedPhaseIds!.contains(phase.id),), ); } return filteredProjects.toSet(); @@ -252,23 +251,23 @@ class ProjectListBloc with RefreshBlocMixin { } Future> _getVotedProjectIdsByPillar( - Iterable projects) async { - var pillarVotes = await zenon!.embedded.accelerator.getPillarVotes( + Iterable projects,) async { + final List pillarVotes = await zenon!.embedded.accelerator.getPillarVotes( pillarInfo!.name, - projects.map((e) => e.id.toString()).toList(), + projects.map((Project e) => e.id.toString()).toList(), ); - return pillarVotes.where((e) => e != null).map((e) => e!.id); + return pillarVotes.where((PillarVote? e) => e != null).map((PillarVote? e) => e!.id); } Future> _getVotedPhaseIdsByPillar( - Iterable projects) async { - var pillarVotes = await zenon!.embedded.accelerator.getPillarVotes( + Iterable projects,) async { + final List pillarVotes = await zenon!.embedded.accelerator.getPillarVotes( pillarInfo!.name, projects - .expand((project) => project.phaseIds) - .map((id) => id.toString()) + .expand((Project project) => project.phaseIds) + .map((Hash id) => id.toString()) .toList(), ); - return pillarVotes.where((e) => e != null).map((e) => e!.id); + return pillarVotes.where((PillarVote? e) => e != null).map((PillarVote? e) => e!.id); } } diff --git a/lib/blocs/accelerator/project_vote_breakdown_bloc.dart b/lib/blocs/accelerator/project_vote_breakdown_bloc.dart index cbb897b9..0f97f0ef 100644 --- a/lib/blocs/accelerator/project_vote_breakdown_bloc.dart +++ b/lib/blocs/accelerator/project_vote_breakdown_bloc.dart @@ -8,7 +8,7 @@ class ProjectVoteBreakdownBloc Future getVoteBreakdown(String? pillarName, Hash projectId) async { try { addEvent(null); - VoteBreakdown voteBreakdown = + final VoteBreakdown voteBreakdown = await zenon!.embedded.accelerator.getVoteBreakdown( projectId, ); @@ -16,7 +16,7 @@ class ProjectVoteBreakdownBloc if (pillarName != null) { pillarVoteList = await zenon!.embedded.accelerator.getPillarVotes( pillarName, - [ + [ projectId.toString(), ], ); diff --git a/lib/blocs/accelerator/submit_donation_bloc.dart b/lib/blocs/accelerator/submit_donation_bloc.dart index 388c232e..4e6d1298 100644 --- a/lib/blocs/accelerator/submit_donation_bloc.dart +++ b/lib/blocs/accelerator/submit_donation_bloc.dart @@ -12,13 +12,13 @@ class SubmitDonationBloc extends BaseBloc { await _sendDonationBlock(zenon!.embedded.accelerator.donate( znnAmount, kZnnCoin.tokenStandard, - )); + ),); } if (qsrAmount > BigInt.zero) { await _sendDonationBlock(zenon!.embedded.accelerator.donate( qsrAmount, kQsrCoin.tokenStandard, - )); + ),); } } catch (e, stackTrace) { addError(e, stackTrace); @@ -26,19 +26,17 @@ class SubmitDonationBloc extends BaseBloc { } Future _sendDonationBlock( - AccountBlockTemplate transactionParams) async { + AccountBlockTemplate transactionParams,) async { await AccountBlockUtils.createAccountBlock( transactionParams, 'donate for accelerator', ).then( - (block) { + (AccountBlockTemplate block) { sl.get().getAcceleratorBalance(); addEvent(block); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } } diff --git a/lib/blocs/accelerator/update_phase_bloc.dart b/lib/blocs/accelerator/update_phase_bloc.dart index ece973a2..a66b8d08 100644 --- a/lib/blocs/accelerator/update_phase_bloc.dart +++ b/lib/blocs/accelerator/update_phase_bloc.dart @@ -5,10 +5,10 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class UpdatePhaseBloc extends BaseBloc { void updatePhase(Hash id, String name, String description, String url, - BigInt znnFundsNeeded, BigInt qsrFundsNeeded) { + BigInt znnFundsNeeded, BigInt qsrFundsNeeded,) { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.accelerator.updatePhase( id, name, @@ -19,12 +19,10 @@ class UpdatePhaseBloc extends BaseBloc { ); AccountBlockUtils.createAccountBlock(transactionParams, 'update phase') .then( - (block) => addEvent(block), + addEvent, ) .onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/accelerator/vote_project_bloc.dart b/lib/blocs/accelerator/vote_project_bloc.dart index 120dc012..8a9a8153 100644 --- a/lib/blocs/accelerator/vote_project_bloc.dart +++ b/lib/blocs/accelerator/vote_project_bloc.dart @@ -8,11 +8,11 @@ class VoteProjectBloc extends BaseBloc { Future voteProject(Hash id, AcceleratorProjectVote vote) async { try { addEvent(null); - PillarInfo pillarInfo = (await zenon!.embedded.pillar.getByOwner( + final PillarInfo pillarInfo = (await zenon!.embedded.pillar.getByOwner( Address.parse(kSelectedAddress!), )) .first; - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.accelerator.voteByName( id, pillarInfo.name, @@ -23,12 +23,10 @@ class VoteProjectBloc extends BaseBloc { 'vote for project', ) .then( - (block) => addEvent(block), + addEvent, ) .onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/auto_receive_tx_worker.dart b/lib/blocs/auto_receive_tx_worker.dart index e736bb02..e90ab23b 100644 --- a/lib/blocs/auto_receive_tx_worker.dart +++ b/lib/blocs/auto_receive_tx_worker.dart @@ -23,16 +23,16 @@ class AutoReceiveTxWorker extends BaseBloc { } Future autoReceiveTransactionHash( - Hash currentHash) async { + Hash currentHash,) async { if (!running) { running = true; try { - Address toAddress = + final Address toAddress = (await zenon!.ledger.getAccountBlockByHash(currentHash))!.toAddress; - AccountBlockTemplate transactionParams = AccountBlockTemplate.receive( + final AccountBlockTemplate transactionParams = AccountBlockTemplate.receive( currentHash, ); - AccountBlockTemplate response = + final AccountBlockTemplate response = await AccountBlockUtils.createAccountBlock( transactionParams, 'receive transaction', @@ -53,10 +53,10 @@ class AutoReceiveTxWorker extends BaseBloc { } Future autoReceive() async { - if (!sharedPrefsService!.get( + if (sharedPrefsService!.get( kAutoReceiveKey, defaultValue: kAutoReceiveDefaultValue, - )) { + ) == false) { pool.clear(); return; } @@ -64,14 +64,14 @@ class AutoReceiveTxWorker extends BaseBloc { // given priority to send transactions. if (pool.isNotEmpty && !running && !sl().running) { running = true; - Hash currentHash = pool.first; + final Hash currentHash = pool.first; try { - Address toAddress = + final Address toAddress = (await zenon!.ledger.getAccountBlockByHash(currentHash))!.toAddress; - AccountBlockTemplate transactionParams = AccountBlockTemplate.receive( + final AccountBlockTemplate transactionParams = AccountBlockTemplate.receive( currentHash, ); - AccountBlockTemplate response = + final AccountBlockTemplate response = await AccountBlockUtils.createAccountBlock( transactionParams, 'receive transaction', @@ -105,7 +105,7 @@ class AutoReceiveTxWorker extends BaseBloc { } Future addHash(Hash hash) async { - zenon!.stats.syncInfo().then((syncInfo) { + zenon!.stats.syncInfo().then((SyncInfo syncInfo) { if (!pool.contains(hash) && (syncInfo.state == SyncState.syncDone || (syncInfo.targetHeight > 0 && diff --git a/lib/blocs/auto_unlock_htlc_worker.dart b/lib/blocs/auto_unlock_htlc_worker.dart index 63e7a644..abd56c67 100644 --- a/lib/blocs/auto_unlock_htlc_worker.dart +++ b/lib/blocs/auto_unlock_htlc_worker.dart @@ -7,6 +7,7 @@ import 'package:zenon_syrius_wallet_flutter/blocs/base_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/notification_type.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/wallet_notification.dart'; +import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/htlc_swap.dart'; import 'package:zenon_syrius_wallet_flutter/utils/account_block_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart'; @@ -27,10 +28,10 @@ class AutoUnlockHtlcWorker extends BaseBloc { Future autoUnlock() async { if (pool.isNotEmpty && !running && kWalletFile != null) { running = true; - Hash currentHash = pool.first; + final Hash currentHash = pool.first; try { - final htlc = await zenon!.embedded.htlc.getById(currentHash); - final swap = htlcSwapsService! + final HtlcInfo htlc = await zenon!.embedded.htlc.getById(currentHash); + final HtlcSwap? swap = htlcSwapsService! .getSwapByHashLock(FormatUtils.encodeHexString(htlc.hashLock)); if (swap == null || swap.preimage == null) { throw 'Invalid swap'; @@ -38,9 +39,9 @@ class AutoUnlockHtlcWorker extends BaseBloc { if (!kDefaultAddressList.contains(htlc.hashLocked.toString())) { throw 'Swap address not in default addresses. Please add the address in the addresses list.'; } - AccountBlockTemplate transactionParams = zenon!.embedded.htlc + final AccountBlockTemplate transactionParams = zenon!.embedded.htlc .unlock(htlc.id, FormatUtils.decodeHexString(swap.preimage!)); - AccountBlockTemplate response = + final AccountBlockTemplate response = await AccountBlockUtils.createAccountBlock( transactionParams, 'complete swap', @@ -91,7 +92,7 @@ class AutoUnlockHtlcWorker extends BaseBloc { void addHash(Hash hash) { if (!processedHashes.contains(hash)) { - zenon!.stats.syncInfo().then((syncInfo) { + zenon!.stats.syncInfo().then((SyncInfo syncInfo) { if (!processedHashes.contains(hash) && (syncInfo.state == SyncState.syncDone || (syncInfo.targetHeight > 0 && @@ -101,7 +102,7 @@ class AutoUnlockHtlcWorker extends BaseBloc { processedHashes.add(hash); } }).onError( - (e, stackTrace) { + (Object? e, StackTrace stackTrace) { Logger('AutoUnlockHtlcWorker') .log(Level.WARNING, 'addHash', e, stackTrace); }, @@ -117,6 +118,6 @@ class AutoUnlockHtlcWorker extends BaseBloc { // allowing for it to be retried. void _removeHashFromHashSetAfterDelay(Hash hash) { Future.delayed( - const Duration(minutes: 2), () => processedHashes.remove(hash)); + const Duration(minutes: 2), () => processedHashes.remove(hash),); } } diff --git a/lib/blocs/base_bloc.dart b/lib/blocs/base_bloc.dart index b5bee582..e23c0a41 100644 --- a/lib/blocs/base_bloc.dart +++ b/lib/blocs/base_bloc.dart @@ -15,7 +15,7 @@ abstract class BaseBloc extends BaseViewModel { if (!_controller.isClosed) _sink.add(event); } - void addError(error, stackTrace) { + FutureOr addError(Object error, StackTrace stackTrace) async { Logger('BaseBloc').log(Level.WARNING, 'addError', error, stackTrace); if (!_controller.isClosed) { _sink.addError(error); diff --git a/lib/blocs/base_bloc_for_reloading_indicator.dart b/lib/blocs/base_bloc_for_reloading_indicator.dart index 05a62ebc..a45a52d9 100644 --- a/lib/blocs/base_bloc_for_reloading_indicator.dart +++ b/lib/blocs/base_bloc_for_reloading_indicator.dart @@ -6,12 +6,12 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; abstract class BaseBlocForReloadingIndicator extends BaseBloc with RefreshBlocMixin { - Future getDataAsync(); BaseBlocForReloadingIndicator() { updateStream(); listenToWsRestart(updateStream); } + Future getDataAsync(); Future updateStream() async { try { diff --git a/lib/blocs/base_bloc_with_refresh_mixin.dart b/lib/blocs/base_bloc_with_refresh_mixin.dart index 8e806aac..8d5a1385 100644 --- a/lib/blocs/base_bloc_with_refresh_mixin.dart +++ b/lib/blocs/base_bloc_with_refresh_mixin.dart @@ -6,12 +6,12 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; abstract class BaseBlocWithRefreshMixin extends BaseBloc with RefreshBlocMixin { - Future getDataAsync(); BaseBlocWithRefreshMixin() { updateStream(); listenToWsRestart(updateStream); } + Future getDataAsync(); Future updateStream() async { try { diff --git a/lib/blocs/blocs.dart b/lib/blocs/blocs.dart index bdfc4b21..cc499f11 100644 --- a/lib/blocs/blocs.dart +++ b/lib/blocs/blocs.dart @@ -1,23 +1,21 @@ -library blocs; +export 'accelerator/accelerator.dart'; export 'auto_receive_tx_worker.dart'; export 'base_bloc.dart'; export 'base_bloc_for_reloading_indicator.dart'; export 'base_bloc_with_refresh_mixin.dart'; +export 'dashboard/dashboard.dart'; export 'decrypt_wallet_file_bloc.dart'; export 'hide_widget_status_bloc.dart'; export 'infinite_scroll_bloc.dart'; export 'key_store_file_bloc.dart'; export 'ledger_wallet_file_bloc.dart'; export 'lock_bloc.dart'; -export 'node_sync_status_bloc.dart'; export 'notifications_bloc.dart'; -export 'pow_generating_status_bloc.dart'; -export 'refresh_bloc_mixin.dart'; -export 'accelerator/accelerator.dart'; -export 'dashboard/dashboard.dart'; export 'pillars/pillars.dart'; export 'plasma/plasma.dart'; +export 'pow_generating_status_bloc.dart'; +export 'refresh_bloc_mixin.dart'; export 'sentinels/sentinels.dart'; export 'settings/settings.dart'; export 'staking/staking.dart'; diff --git a/lib/blocs/dashboard/balance_bloc.dart b/lib/blocs/dashboard/balance_bloc.dart index 69cde008..48ac4288 100644 --- a/lib/blocs/dashboard/balance_bloc.dart +++ b/lib/blocs/dashboard/balance_bloc.dart @@ -14,15 +14,15 @@ class BalanceBloc extends BaseBloc?> Future getBalanceForAllAddresses() async { try { addEvent(null); - Map addressBalanceMap = {}; - List accountInfoList = await Future.wait( + final Map addressBalanceMap = {}; + final List accountInfoList = await Future.wait( kDefaultAddressList.map( - (address) => _getBalancePerAddress( + (String? address) => _getBalancePerAddress( address!, ), ), ); - for (var accountInfo in accountInfoList) { + for (final AccountInfo accountInfo in accountInfoList) { addressBalanceMap[accountInfo.address!] = accountInfo; } addEvent(addressBalanceMap); @@ -32,5 +32,5 @@ class BalanceBloc extends BaseBloc?> } Future _getBalancePerAddress(String address) async => - await zenon!.ledger.getAccountInfoByAddress(Address.parse(address)); + zenon!.ledger.getAccountInfoByAddress(Address.parse(address)); } diff --git a/lib/blocs/dashboard/balance_dashboard_bloc.dart b/lib/blocs/dashboard/balance_dashboard_bloc.dart deleted file mode 100644 index 7207a497..00000000 --- a/lib/blocs/dashboard/balance_dashboard_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class BalanceDashboardBloc extends DashboardBaseBloc { - @override - Future makeAsyncCall() async { - AccountInfo response = await zenon!.ledger - .getAccountInfoByAddress(Address.parse(kSelectedAddress!)); - if (response.blockCount! > 0 && - (response.znn()! > BigInt.zero || response.qsr()! > BigInt.zero)) { - return response; - } else { - throw 'Empty balance on the selected address'; - } - } -} diff --git a/lib/blocs/dashboard/dashboard.dart b/lib/blocs/dashboard/dashboard.dart index 1c36d94f..2324e8c8 100644 --- a/lib/blocs/dashboard/dashboard.dart +++ b/lib/blocs/dashboard/dashboard.dart @@ -1,12 +1,2 @@ -library dashboard; export 'balance_bloc.dart'; -export 'balance_dashboard_bloc.dart'; -export 'dashboard_base_bloc.dart'; -export 'delegation_bloc.dart'; -export 'dual_coin_stats_bloc.dart'; -export 'pillars_bloc.dart'; -export 'realtime_statistics_bloc.dart'; -export 'sentinels_bloc.dart'; -export 'staking_bloc.dart'; -export 'total_hourly_transactions_bloc.dart'; diff --git a/lib/blocs/dashboard/dashboard_base_bloc.dart b/lib/blocs/dashboard/dashboard_base_bloc.dart deleted file mode 100644 index 5daabf45..00000000 --- a/lib/blocs/dashboard/dashboard_base_bloc.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -abstract class DashboardBaseBloc extends BaseBloc with RefreshBlocMixin { - Timer? _autoRefresher; - - Future makeAsyncCall(); - - DashboardBaseBloc() { - listenToWsRestart(getDataPeriodically); - } - - Timer _getAutoRefreshTimer() => Timer( - kIntervalBetweenMomentums, - () { - _autoRefresher!.cancel(); - getDataPeriodically(); - }, - ); - - Future getDataPeriodically() async { - try { - if (!zenon!.wsClient.isClosed()) { - T data = await makeAsyncCall(); - addEvent(data); - } else { - throw noConnectionException; - } - } catch (e, stackTrace) { - addError(e, stackTrace); - } finally { - if (_autoRefresher == null) { - _autoRefresher = _getAutoRefreshTimer(); - } else if (!_autoRefresher!.isActive) { - _autoRefresher = _getAutoRefreshTimer(); - } - } - } - - @override - void dispose() { - _autoRefresher?.cancel(); - super.dispose(); - } -} diff --git a/lib/blocs/dashboard/delegation_bloc.dart b/lib/blocs/dashboard/delegation_bloc.dart deleted file mode 100644 index e2864534..00000000 --- a/lib/blocs/dashboard/delegation_bloc.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class DelegationBloc extends DashboardBaseBloc { - @override - Future makeAsyncCall() async { - try { - DelegationInfo? response = - await zenon!.embedded.pillar.getDelegatedPillar( - Address.parse(kSelectedAddress!), - ); - if (response != null) { - return response; - } else { - throw 'No delegation stats'; - } - } catch (e) { - rethrow; - } - } -} diff --git a/lib/blocs/dashboard/dual_coin_stats_bloc.dart b/lib/blocs/dashboard/dual_coin_stats_bloc.dart deleted file mode 100644 index 5a477c4f..00000000 --- a/lib/blocs/dashboard/dual_coin_stats_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class DualCoinStatsBloc extends DashboardBaseBloc> { - @override - Future> makeAsyncCall() async => await Future.wait( - [ - zenon!.embedded.token.getByZts( - kZnnCoin.tokenStandard, - ), - zenon!.embedded.token.getByZts( - kQsrCoin.tokenStandard, - ) - ], - ); -} diff --git a/lib/blocs/dashboard/pillars_bloc.dart b/lib/blocs/dashboard/pillars_bloc.dart deleted file mode 100644 index 87db9358..00000000 --- a/lib/blocs/dashboard/pillars_bloc.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; - -class PillarsBloc extends DashboardBaseBloc { - @override - Future makeAsyncCall() async { - int numOfPillars = (await zenon!.embedded.pillar.getAll()).list.length; - kNumOfPillars = numOfPillars; - return numOfPillars; - } -} diff --git a/lib/blocs/dashboard/realtime_statistics_bloc.dart b/lib/blocs/dashboard/realtime_statistics_bloc.dart deleted file mode 100644 index 8ae8e4cb..00000000 --- a/lib/blocs/dashboard/realtime_statistics_bloc.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class RealtimeStatisticsBloc extends DashboardBaseBloc> { - @override - Future> makeAsyncCall() async { - int chainHeight = (await zenon!.ledger.getFrontierMomentum()).height; - int height = chainHeight - kMomentumsPerWeek > 0 - ? chainHeight - kMomentumsPerWeek - : 1; - int pageIndex = 0; - int pageSize = 10; - bool isLastPage = false; - List blockList = []; - - while (!isLastPage) { - List response = (await zenon!.ledger.getAccountBlocksByPage( - Address.parse(kSelectedAddress!), - pageIndex: pageIndex, - pageSize: pageSize, - )) - .list ?? - []; - - if (response.isEmpty) { - break; - } - - blockList.addAll(response); - - if (response.last.confirmationDetail!.momentumHeight <= height) { - break; - } - - pageIndex += 1; - isLastPage = response.length < pageSize; - } - - if (blockList.isNotEmpty) { - return blockList; - } else { - throw 'No available data'; - } - } -} diff --git a/lib/blocs/dashboard/sentinels_bloc.dart b/lib/blocs/dashboard/sentinels_bloc.dart deleted file mode 100644 index 0217a02c..00000000 --- a/lib/blocs/dashboard/sentinels_bloc.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class SentinelsBloc extends DashboardBaseBloc> { - @override - Future> makeAsyncCall() async => - (await zenon!.embedded.sentinel.getAllActive()).list; -} diff --git a/lib/blocs/dashboard/staking_bloc.dart b/lib/blocs/dashboard/staking_bloc.dart deleted file mode 100644 index da039c6c..00000000 --- a/lib/blocs/dashboard/staking_bloc.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class StakingStatsModel { - int numActiveStakingEntries; - BigInt totalZnnStakingAmount; - - StakingStatsModel( - this.numActiveStakingEntries, - this.totalZnnStakingAmount, - ); -} - -class StakingBloc extends DashboardBaseBloc { - @override - Future makeAsyncCall() async { - StakeList stakeList = await _getStakeList(); - if (stakeList.list.isNotEmpty) { - return StakingStatsModel( - stakeList.list.length, - stakeList.totalAmount, - ); - } else { - throw 'No active staking entries'; - } - } - - Future _getStakeList() async => - await zenon!.embedded.stake.getEntriesByAddress( - Address.parse(kSelectedAddress!), - pageIndex: 0, - ); -} diff --git a/lib/blocs/dashboard/total_hourly_transactions_bloc.dart b/lib/blocs/dashboard/total_hourly_transactions_bloc.dart deleted file mode 100644 index c1a2cf78..00000000 --- a/lib/blocs/dashboard/total_hourly_transactions_bloc.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class TotalHourlyTransactionsBloc - extends DashboardBaseBloc> { - @override - Future> makeAsyncCall() async { - int chainHeight = await _ledgerGetMomentumLedgerHeight(); - if (chainHeight - kMomentumsPerHour > 0) { - List response = - (await zenon!.ledger.getDetailedMomentumsByHeight( - chainHeight - kMomentumsPerHour, - kMomentumsPerHour, - )) - .list ?? - []; - return { - 'numAccountBlocks': response.fold( - 0, - (previousValue, element) => previousValue + element.blocks.length, - ), - 'timestamp': DateTime.now().millisecondsSinceEpoch, - }; - } else { - throw 'Not enough momentums'; - } - } - - _ledgerGetMomentumLedgerHeight() async { - try { - return (await zenon!.ledger.getFrontierMomentum()).height; - } catch (e) { - rethrow; - } - } -} diff --git a/lib/blocs/decrypt_wallet_file_bloc.dart b/lib/blocs/decrypt_wallet_file_bloc.dart index 6436c362..c7346e59 100644 --- a/lib/blocs/decrypt_wallet_file_bloc.dart +++ b/lib/blocs/decrypt_wallet_file_bloc.dart @@ -6,7 +6,7 @@ class DecryptWalletFileBloc extends BaseBloc { Future decryptWalletFile(String path, String password) async { try { addEvent(null); - final walletFile = await WalletUtils.decryptWalletFile(path, password); + final WalletFile walletFile = await WalletUtils.decryptWalletFile(path, password); addEvent(walletFile); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/hide_widget_status_bloc.dart b/lib/blocs/hide_widget_status_bloc.dart index f79c3368..0e6c9c5c 100644 --- a/lib/blocs/hide_widget_status_bloc.dart +++ b/lib/blocs/hide_widget_status_bloc.dart @@ -19,8 +19,8 @@ class HideWidgetStatusBloc extends BaseBloc { } await _markWidgetAsHidden(widgetTitle, isHidden); addEvent(isHidden); - } on IncorrectPasswordException { - addError(kIncorrectPasswordNotificationTitle, null); + } on IncorrectPasswordException catch(e, stackTrace) { + addError(kIncorrectPasswordNotificationTitle, stackTrace); } catch (e, stackTrace) { addError(e, stackTrace); } diff --git a/lib/blocs/infinite_scroll_bloc.dart b/lib/blocs/infinite_scroll_bloc.dart index dc55a98d..d23b2812 100644 --- a/lib/blocs/infinite_scroll_bloc.dart +++ b/lib/blocs/infinite_scroll_bloc.dart @@ -38,11 +38,11 @@ abstract class InfiniteScrollBloc with RefreshBlocMixin { yield* _fetchList(0); } - static const _pageSize = 10; + static const int _pageSize = 10; - final _subscriptions = CompositeSubscription(); + final CompositeSubscription _subscriptions = CompositeSubscription(); - final _onNewListingStateController = + final BehaviorSubject> _onNewListingStateController = BehaviorSubject>.seeded( InfiniteScrollBlocListingState(), ); @@ -50,8 +50,8 @@ abstract class InfiniteScrollBloc with RefreshBlocMixin { Stream> get onNewListingState => _onNewListingStateController.stream; - final _onPageRequest = StreamController(); - final _onRefreshResultsRequest = StreamController(); + final StreamController _onPageRequest = StreamController(); + final StreamController _onRefreshResultsRequest = StreamController(); Sink get onPageRequestSink => _onPageRequest.sink; @@ -60,19 +60,18 @@ abstract class InfiniteScrollBloc with RefreshBlocMixin { List? get lastListingItems => _onNewListingStateController.value.itemList; Stream> _fetchList(int pageKey) async* { - final lastListingState = _onNewListingStateController.value; + final InfiniteScrollBlocListingState lastListingState = _onNewListingStateController.value; try { - final newItems = await getData(pageKey, _pageSize); - final isLastPage = newItems.length < _pageSize || !isDataRequestPaginated; - final nextPageKey = isLastPage ? null : pageKey + 1; + final List newItems = await getData(pageKey, _pageSize); + final bool isLastPage = newItems.length < _pageSize || !isDataRequestPaginated; + final int? nextPageKey = isLastPage ? null : pageKey + 1; List allItems = isDataRequestPaginated - ? [...lastListingState.itemList ?? [], ...newItems] + ? [...lastListingState.itemList ?? [], ...newItems] : newItems; if (filterItemsFunction != null) { allItems = filterItemsFunction!(allItems); } yield InfiniteScrollBlocListingState( - error: null, nextPageKey: nextPageKey, itemList: allItems, ); diff --git a/lib/blocs/key_store_file_bloc.dart b/lib/blocs/key_store_file_bloc.dart index ff09a926..f89af3f9 100644 --- a/lib/blocs/key_store_file_bloc.dart +++ b/lib/blocs/key_store_file_bloc.dart @@ -3,9 +3,9 @@ import 'dart:convert'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/init_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class KeyStoreFileBloc extends BaseBloc { @@ -16,8 +16,8 @@ class KeyStoreFileBloc extends BaseBloc { try { await WalletUtils.createKeyStoreWalletFile(mnemonic, password); await InitUtils.initWalletAfterDecryption( - Crypto.digest(utf8.encode(password))); - addEvent(kWalletFile as KeyStoreWalletFile); + Crypto.digest(utf8.encode(password)),); + addEvent(kWalletFile! as KeyStoreWalletFile); } catch (e, stackTrace) { addError(e, stackTrace); } diff --git a/lib/blocs/ledger_wallet_file_bloc.dart b/lib/blocs/ledger_wallet_file_bloc.dart index 413900b5..e71bef2f 100644 --- a/lib/blocs/ledger_wallet_file_bloc.dart +++ b/lib/blocs/ledger_wallet_file_bloc.dart @@ -3,20 +3,20 @@ import 'dart:convert'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/init_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class LedgerWalletFileBloc extends BaseBloc { Future getLedgerWalletPath(String walletId, String password, - String? walletName) async { + String? walletName,) async { try { await WalletUtils.createLedgerWalletFile(walletId, password, - walletName: walletName); + walletName: walletName,); await InitUtils.initWalletAfterDecryption( - Crypto.digest(utf8.encode(password))); - addEvent(kWalletFile as LedgerWalletFile); + Crypto.digest(utf8.encode(password)),); + addEvent(kWalletFile! as LedgerWalletFile); } catch (e, stackTrace) { addError(e, stackTrace); } diff --git a/lib/blocs/lock_bloc.dart b/lib/blocs/lock_bloc.dart index 990adad8..be7a27ae 100644 --- a/lib/blocs/lock_bloc.dart +++ b/lib/blocs/lock_bloc.dart @@ -12,7 +12,7 @@ enum LockEvent { class LockBloc extends BaseBloc { @override - void addEvent(event) { + void addEvent(LockEvent event) { if (!(kCurrentPage == Tabs.lock && event == LockEvent.resetTimer)) { super.addEvent(event); } diff --git a/lib/blocs/node_sync_status_bloc.dart b/lib/blocs/node_sync_status_bloc.dart deleted file mode 100644 index b996ee91..00000000 --- a/lib/blocs/node_sync_status_bloc.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:async'; - -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/node_utils.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -class NodeSyncStatusBloc extends DashboardBaseBloc { - SyncState lastSyncState = SyncState.unknown; - - @override - Future makeAsyncCall() async { - if (zenon!.wsClient.status() == WebsocketStatus.running) { - SyncInfo syncInfo = await zenon!.stats.syncInfo(); - if (lastSyncState != syncInfo.state && - (syncInfo.state == SyncState.syncDone || - (syncInfo.targetHeight > 0 && - syncInfo.currentHeight > 0 && - (syncInfo.targetHeight - syncInfo.currentHeight) > 3))) { - lastSyncState = syncInfo.state; - if (syncInfo.state == SyncState.syncDone) { - Future.delayed(const Duration(seconds: 5)).then((value) { - NodeUtils.getUnreceivedTransactions().then((value) { - sl().autoReceive(); - }); - }); - } - } - return syncInfo; - } - return SyncInfo.fromJson({ - 'state': 0, - 'currentHeight': 0, - 'targetHeight': 0, - }); - } -} diff --git a/lib/blocs/notifications_bloc.dart b/lib/blocs/notifications_bloc.dart index 2e58736b..b7dcb123 100644 --- a/lib/blocs/notifications_bloc.dart +++ b/lib/blocs/notifications_bloc.dart @@ -11,7 +11,7 @@ class NotificationsBloc extends BaseBloc { Future addNotification(WalletNotification? notification) async { try { await Hive.openBox(kNotificationsBox); - Box notificationsBox = Hive.box(kNotificationsBox); + final Box notificationsBox = Hive.box(kNotificationsBox); if (notificationsBox.length >= kNotificationsEntriesLimit) { while (notificationsBox.length >= kNotificationsEntriesLimit) { await notificationsBox.delete(notificationsBox.keys.first); @@ -19,7 +19,7 @@ class NotificationsBloc extends BaseBloc { } await notificationsBox.add(notification); if (notification != null && _areDesktopNotificationsEnabled()) { - LocalNotification localNotification = LocalNotification( + final LocalNotification localNotification = LocalNotification( title: notification.title ?? 'Empty title', body: notification.details ?? 'No details available', ); @@ -48,7 +48,7 @@ class NotificationsBloc extends BaseBloc { WalletNotification( title: title, timestamp: DateTime.now().millisecondsSinceEpoch, - details: '$title: ${error.toString()}', + details: '$title: $error', type: NotificationType.error, ), ); diff --git a/lib/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart index dc8d49f3..80ecb59d 100644 --- a/lib/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart @@ -11,13 +11,13 @@ class CompleteHtlcSwapBloc extends BaseBloc { }) async { try { addEvent(null); - final htlcId = swap.direction == P2pSwapDirection.outgoing + final String htlcId = swap.direction == P2pSwapDirection.outgoing ? swap.counterHtlcId! : swap.initialHtlcId; // Make sure that the HTLC exists and has a safe amount of time left // until expiration. - final htlc = await zenon!.embedded.htlc.getById(Hash.parse(htlcId)); + final HtlcInfo htlc = await zenon!.embedded.htlc.getById(Hash.parse(htlcId)); if (htlc.expirationTime <= DateTimeUtils.unixTimeNow + kMinSafeTimeToCompleteSwap.inSeconds) { throw 'The swap will expire too soon for a safe swap.'; @@ -28,19 +28,19 @@ class CompleteHtlcSwapBloc extends BaseBloc { throw 'The swap secret size exceeds the maximum allowed size.'; } - AccountBlockTemplate transactionParams = zenon!.embedded.htlc.unlock( - Hash.parse(htlcId), FormatUtils.decodeHexString(swap.preimage!)); + final AccountBlockTemplate transactionParams = zenon!.embedded.htlc.unlock( + Hash.parse(htlcId), FormatUtils.decodeHexString(swap.preimage!),); AccountBlockUtils.createAccountBlock(transactionParams, 'complete swap', - address: Address.parse(swap.selfAddress), waitForRequiredPlasma: true) + address: Address.parse(swap.selfAddress), waitForRequiredPlasma: true,) .then( - (response) async { + (AccountBlockTemplate response) async { swap.state = P2pSwapState.completed; await htlcSwapsService!.storeSwap(swap); ZenonAddressUtils.refreshBalance(); addEvent(swap); }, ).onError( - (error, stackTrace) { + (Object? error, StackTrace stackTrace) { addError(error.toString(), stackTrace); }, ); diff --git a/lib/blocs/p2p_swap/htlc_swap/htlc_swap_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/htlc_swap_bloc.dart index 058e4fb8..945516a7 100644 --- a/lib/blocs/p2p_swap/htlc_swap/htlc_swap_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/htlc_swap_bloc.dart @@ -4,9 +4,9 @@ import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/htlc_swap.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class HtlcSwapBloc extends PeriodicP2pSwapBaseBloc { - final String swapId; HtlcSwapBloc(this.swapId); + final String swapId; @override HtlcSwap makeCall() { @@ -14,7 +14,7 @@ class HtlcSwapBloc extends PeriodicP2pSwapBaseBloc { if (zenon!.wsClient.isClosed()) { throw noConnectionException; } - final swap = htlcSwapsService!.getSwapById(swapId); + final HtlcSwap? swap = htlcSwapsService!.getSwapById(swapId); if (swap != null) { return swap; } else { diff --git a/lib/blocs/p2p_swap/htlc_swap/initial_htlc_for_swap_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/initial_htlc_for_swap_bloc.dart index 406ee369..ac5d4af3 100644 --- a/lib/blocs/p2p_swap/htlc_swap/initial_htlc_for_swap_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/initial_htlc_for_swap_bloc.dart @@ -3,16 +3,18 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/base_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/model/block_data.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class InitialHtlcForSwapBloc extends BaseBloc { - final _minimumRequiredDuration = + final Duration _minimumRequiredDuration = kMinSafeTimeToFindPreimage + kCounterHtlcDuration; + Future getInitialHtlc(Hash id) async { try { - final htlc = await zenon!.embedded.htlc.getById(id); - final hashlock = FormatUtils.encodeHexString(htlc.hashLock); + final HtlcInfo htlc = await zenon!.embedded.htlc.getById(id); + final String hashlock = FormatUtils.encodeHexString(htlc.hashLock); if (!kDefaultAddressList.contains(htlc.hashLocked.toString())) { throw 'This deposit is not intended for you.'; } @@ -23,9 +25,9 @@ class InitialHtlcForSwapBloc extends BaseBloc { throw 'This deposit is already used in another swap.'; } if (htlcSwapsService!.getSwapByHashLock(hashlock) != null) { - throw 'The deposit\'s hashlock is already used in another swap.'; + throw "The deposit's hashlock is already used in another swap."; } - final remainingDuration = + final Duration remainingDuration = Duration(seconds: htlc.expirationTime - DateTimeUtils.unixTimeNow); if (remainingDuration < _minimumRequiredDuration) { if (remainingDuration.inSeconds <= 0) { @@ -34,9 +36,9 @@ class InitialHtlcForSwapBloc extends BaseBloc { throw 'This deposit will expire too soon for a safe swap.'; } if (remainingDuration > kMaxAllowedInitialHtlcDuration) { - throw 'The deposit\'s duration is too long. Expected ${kMaxAllowedInitialHtlcDuration.inHours} hours at most.'; + throw "The deposit's duration is too long. Expected ${kMaxAllowedInitialHtlcDuration.inHours} hours at most."; } - final creationBlock = await zenon!.ledger.getAccountBlockByHash(htlc.id); + final AccountBlock? creationBlock = await zenon!.ledger.getAccountBlockByHash(htlc.id); if (htlc.expirationTime - creationBlock!.confirmationDetail!.momentumTimestamp > kMaxAllowedInitialHtlcDuration.inSeconds) { @@ -45,12 +47,15 @@ class InitialHtlcForSwapBloc extends BaseBloc { // Verify that the hashlock has not been used in another currently active // HTLC. - final htlcBlocks = await AccountBlockUtils.getAccountBlocksAfterTime( - htlcAddress, - htlc.expirationTime - kMaxAllowedInitialHtlcDuration.inSeconds); - if (htlcBlocks.firstWhereOrNull((block) => - !_isInitialHtlcBlock(block, htlc.id) && - _hasMatchingHashlock(block, hashlock)) != + final List htlcBlocks = await AccountBlockUtils.getAccountBlocksAfterTime( + htlcAddress, + htlc.expirationTime - kMaxAllowedInitialHtlcDuration.inSeconds, + ); + if (htlcBlocks.firstWhereOrNull( + (AccountBlock block) => + !_isInitialHtlcBlock(block, htlc.id) && + _hasMatchingHashlock(block, hashlock), + ) != null) { throw 'The hashlock is not unique.'; } @@ -73,8 +78,10 @@ bool _hasMatchingHashlock(AccountBlock block, String hashlock) { return false; } - final blockData = AccountBlockUtils.getDecodedBlockData( - Definitions.htlc, block.pairedAccountBlock!.data); + final BlockData? blockData = AccountBlockUtils.getDecodedBlockData( + Definitions.htlc, + block.pairedAccountBlock!.data, + ); if (blockData == null || blockData.function != 'Create') { return false; @@ -84,5 +91,8 @@ bool _hasMatchingHashlock(AccountBlock block, String hashlock) { return false; } - return FormatUtils.encodeHexString(blockData.params['hashLock']) == hashlock; + return FormatUtils.encodeHexString( + blockData.params['hashLock'] as List, + ) == + hashlock; } diff --git a/lib/blocs/p2p_swap/htlc_swap/join_htlc_swap_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/join_htlc_swap_bloc.dart index 45010baf..01b2b805 100644 --- a/lib/blocs/p2p_swap/htlc_swap/join_htlc_swap_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/join_htlc_swap_bloc.dart @@ -9,7 +9,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class JoinHtlcSwapBloc extends BaseBloc { - void joinHtlcSwap({ + Future joinHtlcSwap({ required HtlcInfo initialHtlc, required Token fromToken, required Token toToken, @@ -21,7 +21,7 @@ class JoinHtlcSwapBloc extends BaseBloc { }) async { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.htlc.create( + final AccountBlockTemplate transactionParams = zenon!.embedded.htlc.create( fromToken, fromAmount, initialHtlc.timeLocked, @@ -31,10 +31,10 @@ class JoinHtlcSwapBloc extends BaseBloc { initialHtlc.hashLock, ); AccountBlockUtils.createAccountBlock(transactionParams, 'join swap', - address: initialHtlc.hashLocked, waitForRequiredPlasma: true) + address: initialHtlc.hashLocked, waitForRequiredPlasma: true,) .then( - (response) async { - final swap = HtlcSwap( + (AccountBlockTemplate response) async { + final HtlcSwap swap = HtlcSwap( id: initialHtlc.id.toString(), chainId: response.chainIdentifier, type: swapType, @@ -65,7 +65,7 @@ class JoinHtlcSwapBloc extends BaseBloc { addEvent(swap); }, ).onError( - (error, stackTrace) { + (Object? error, StackTrace stackTrace) { addError(error.toString(), stackTrace); }, ); diff --git a/lib/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart index 8aec5c9d..8e1db549 100644 --- a/lib/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart @@ -5,24 +5,24 @@ import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ReclaimHtlcSwapFundsBloc extends BaseBloc { - void reclaimFunds({ + Future reclaimFunds({ required Hash htlcId, required Address selfAddress, }) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.htlc.reclaim(htlcId); AccountBlockUtils.createAccountBlock( transactionParams, 'reclaim swap funds', - address: selfAddress, waitForRequiredPlasma: true) + address: selfAddress, waitForRequiredPlasma: true,) .then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { + (Object? error, StackTrace stackTrace) { addError(error.toString(), stackTrace); }, ); diff --git a/lib/blocs/p2p_swap/htlc_swap/recover_htlc_swap_funds_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/recover_htlc_swap_funds_bloc.dart index 7b418fda..86e116c5 100644 --- a/lib/blocs/p2p_swap/htlc_swap/recover_htlc_swap_funds_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/recover_htlc_swap_funds_bloc.dart @@ -7,9 +7,9 @@ import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class RecoverHtlcSwapFundsBloc extends ReclaimHtlcSwapFundsBloc { - void recoverFunds({required Hash htlcId}) async { + Future recoverFunds({required Hash htlcId}) async { try { - final htlc = await zenon!.embedded.htlc.getById(htlcId); + final HtlcInfo htlc = await zenon!.embedded.htlc.getById(htlcId); if (!kDefaultAddressList.contains(htlc.timeLocked.toString())) { throw 'The deposit does not belong to you.'; diff --git a/lib/blocs/p2p_swap/htlc_swap/start_htlc_swap_bloc.dart b/lib/blocs/p2p_swap/htlc_swap/start_htlc_swap_bloc.dart index 281dfe55..dde02568 100644 --- a/lib/blocs/p2p_swap/htlc_swap/start_htlc_swap_bloc.dart +++ b/lib/blocs/p2p_swap/htlc_swap/start_htlc_swap_bloc.dart @@ -11,7 +11,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StartHtlcSwapBloc extends BaseBloc { - void startHtlcSwap({ + Future startHtlcSwap({ required Address selfAddress, required Address counterpartyAddress, required Token fromToken, @@ -24,10 +24,10 @@ class StartHtlcSwapBloc extends BaseBloc { }) async { try { addEvent(null); - final preimage = _generatePreimage(); - final hashLock = await _getHashLock(hashType, preimage); - final expirationTime = await _getExpirationTime(initialHtlcDuration); - AccountBlockTemplate transactionParams = zenon!.embedded.htlc.create( + final List preimage = _generatePreimage(); + final Hash hashLock = await _getHashLock(hashType, preimage); + final int expirationTime = await _getExpirationTime(initialHtlcDuration); + final AccountBlockTemplate transactionParams = zenon!.embedded.htlc.create( fromToken, fromAmount, counterpartyAddress, @@ -37,10 +37,10 @@ class StartHtlcSwapBloc extends BaseBloc { hashLock.getBytes(), ); AccountBlockUtils.createAccountBlock(transactionParams, 'start swap', - address: selfAddress, waitForRequiredPlasma: true) + address: selfAddress, waitForRequiredPlasma: true,) .then( - (response) async { - final swap = HtlcSwap( + (AccountBlockTemplate response) async { + final HtlcSwap swap = HtlcSwap( id: response.hash.toString(), chainId: response.chainIdentifier, type: swapType, @@ -66,7 +66,7 @@ class StartHtlcSwapBloc extends BaseBloc { addEvent(swap); }, ).onError( - (error, stackTrace) { + (Object? error, StackTrace stackTrace) { addError(error.toString(), stackTrace); }, ); @@ -76,9 +76,9 @@ class StartHtlcSwapBloc extends BaseBloc { } List _generatePreimage() { - const maxInt = 256; + const int maxInt = 256; return List.generate( - htlcPreimageDefaultLength, (i) => Random.secure().nextInt(maxInt)); + htlcPreimageDefaultLength, (int i) => Random.secure().nextInt(maxInt),); } Future _getHashLock(int hashType, List preimage) async { diff --git a/lib/blocs/p2p_swap/p2p_swaps_list_bloc.dart b/lib/blocs/p2p_swap/p2p_swaps_list_bloc.dart index 084b5ad5..674f65f8 100644 --- a/lib/blocs/p2p_swap/p2p_swaps_list_bloc.dart +++ b/lib/blocs/p2p_swap/p2p_swaps_list_bloc.dart @@ -1,5 +1,6 @@ import 'package:zenon_syrius_wallet_flutter/blocs/p2p_swap/periodic_p2p_swap_base_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/htlc_swap.dart'; import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/p2p_swap.dart'; class P2pSwapsListBloc extends PeriodicP2pSwapBaseBloc> { @@ -14,7 +15,7 @@ class P2pSwapsListBloc extends PeriodicP2pSwapBaseBloc> { void getData() { try { - final data = _getSwaps(); + final List data = _getSwaps(); addEvent(data); } catch (e, stackTrace) { addError(e, stackTrace); @@ -22,8 +23,8 @@ class P2pSwapsListBloc extends PeriodicP2pSwapBaseBloc> { } List _getSwaps() { - final swaps = htlcSwapsService!.getAllSwaps(); - swaps.sort((a, b) => b.startTime.compareTo(a.startTime)); + final List swaps = htlcSwapsService!.getAllSwaps(); + swaps.sort((HtlcSwap a, HtlcSwap b) => b.startTime.compareTo(a.startTime)); return swaps; } } diff --git a/lib/blocs/p2p_swap/periodic_p2p_swap_base_bloc.dart b/lib/blocs/p2p_swap/periodic_p2p_swap_base_bloc.dart index c75b23c5..2020e06b 100644 --- a/lib/blocs/p2p_swap/periodic_p2p_swap_base_bloc.dart +++ b/lib/blocs/p2p_swap/periodic_p2p_swap_base_bloc.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:zenon_syrius_wallet_flutter/blocs/base_bloc.dart'; abstract class PeriodicP2pSwapBaseBloc extends BaseBloc { - final _refreshInterval = const Duration(seconds: 5); + final Duration _refreshInterval = const Duration(seconds: 5); Timer? _autoRefresher; @@ -11,7 +11,7 @@ abstract class PeriodicP2pSwapBaseBloc extends BaseBloc { void getDataPeriodically() { try { - T data = makeCall(); + final data = makeCall(); addEvent(data); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/delegate_button_bloc.dart b/lib/blocs/pillars/delegate_button_bloc.dart index bb65b1d5..71d440d6 100644 --- a/lib/blocs/pillars/delegate_button_bloc.dart +++ b/lib/blocs/pillars/delegate_button_bloc.dart @@ -10,7 +10,7 @@ class DelegateButtonBloc extends BaseBloc { ) async { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.pillar.delegate( + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.delegate( pillarName!, ); AccountBlockUtils.createAccountBlock( @@ -18,14 +18,12 @@ class DelegateButtonBloc extends BaseBloc { 'delegate to Pillar', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/disassemble_pillar_bloc.dart b/lib/blocs/pillars/disassemble_pillar_bloc.dart index 3e10e171..ba149ae1 100644 --- a/lib/blocs/pillars/disassemble_pillar_bloc.dart +++ b/lib/blocs/pillars/disassemble_pillar_bloc.dart @@ -12,7 +12,7 @@ class DisassemblePillarBloc extends BaseBloc { ) { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.pillar.revoke( + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.revoke( pillarName, ); AccountBlockUtils.createAccountBlock( @@ -20,14 +20,12 @@ class DisassemblePillarBloc extends BaseBloc { 'disassemble Pillar', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/pillar_rewards_history_bloc.dart b/lib/blocs/pillars/pillar_rewards_history_bloc.dart index 09f303f9..1fec99b3 100644 --- a/lib/blocs/pillars/pillar_rewards_history_bloc.dart +++ b/lib/blocs/pillars/pillar_rewards_history_bloc.dart @@ -8,12 +8,12 @@ class PillarRewardsHistoryBloc extends BaseBlocForReloadingIndicator { @override Future getDataAsync() async { - RewardHistoryList response = + final RewardHistoryList response = await zenon!.embedded.pillar.getFrontierRewardByPage( Address.parse(kSelectedAddress!), pageSize: kStandardChartNumDays.toInt(), ); - if (response.list.any((element) => element.znnAmount > BigInt.zero)) { + if (response.list.any((RewardHistoryEntry element) => element.znnAmount > BigInt.zero)) { return response; } else { throw 'No rewards in the last week'; diff --git a/lib/blocs/pillars/pillars.dart b/lib/blocs/pillars/pillars.dart index 9b8d7f82..39144d6b 100644 --- a/lib/blocs/pillars/pillars.dart +++ b/lib/blocs/pillars/pillars.dart @@ -1,4 +1,3 @@ -library pillars; export 'delegate_button_bloc.dart'; export 'delegation_info_bloc.dart'; diff --git a/lib/blocs/pillars/pillars_deploy_bloc.dart b/lib/blocs/pillars/pillars_deploy_bloc.dart index 1b7be9a9..e95d6c99 100644 --- a/lib/blocs/pillars/pillars_deploy_bloc.dart +++ b/lib/blocs/pillars/pillars_deploy_bloc.dart @@ -23,26 +23,24 @@ class PillarsDeployBloc extends BaseBloc { if (await _pillarNameAlreadyExists(pillarName)) { throw 'Pillar name already exists'; } - AccountBlockTemplate transactionParams = zenon!.embedded.pillar.register( + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.register( pillarName, Address.parse(blockProducingAddress), Address.parse(rewardAddress), giveBlockRewardPercentage, giveDelegateRewardPercentage, ); - AccountBlockUtils.createAccountBlock( + await AccountBlockUtils.createAccountBlock( transactionParams, 'register Pillar', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/pillars_deposit_qsr_bloc.dart b/lib/blocs/pillars/pillars_deposit_qsr_bloc.dart index e3cbfd35..432ea33c 100644 --- a/lib/blocs/pillars/pillars_deposit_qsr_bloc.dart +++ b/lib/blocs/pillars/pillars_deposit_qsr_bloc.dart @@ -16,7 +16,7 @@ class PillarsDepositQsrBloc extends BaseBloc { try { addEvent(null); if (!justMarkStepCompleted) { - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.depositQsr( amount, ); @@ -25,7 +25,7 @@ class PillarsDepositQsrBloc extends BaseBloc { 'deposit ${kQsrCoin.symbol} for Pillar Slot', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed( kDelayAfterAccountBlockCreationCall, ); @@ -33,9 +33,7 @@ class PillarsDepositQsrBloc extends BaseBloc { addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } } catch (e, stackTrace) { diff --git a/lib/blocs/pillars/pillars_qsr_info_bloc.dart b/lib/blocs/pillars/pillars_qsr_info_bloc.dart index c9fa4dff..8c03f3cd 100644 --- a/lib/blocs/pillars/pillars_qsr_info_bloc.dart +++ b/lib/blocs/pillars/pillars_qsr_info_bloc.dart @@ -11,10 +11,10 @@ class PillarsQsrInfoBloc extends BaseBloc { ) async { try { addEvent(null); - BigInt deposit = (await zenon!.embedded.pillar.getDepositedQsr( + final BigInt deposit = await zenon!.embedded.pillar.getDepositedQsr( Address.parse(address), - )); - BigInt cost = (await zenon!.embedded.pillar.getQsrRegistrationCost()); + ); + final BigInt cost = await zenon!.embedded.pillar.getQsrRegistrationCost(); addEvent( PillarsQsrInfo( deposit: deposit, diff --git a/lib/blocs/pillars/pillars_withdraw_qsr_bloc.dart b/lib/blocs/pillars/pillars_withdraw_qsr_bloc.dart index b4168718..390ba7e1 100644 --- a/lib/blocs/pillars/pillars_withdraw_qsr_bloc.dart +++ b/lib/blocs/pillars/pillars_withdraw_qsr_bloc.dart @@ -12,22 +12,20 @@ class PillarsWithdrawQsrBloc extends BaseBloc { Future withdrawQsr(String address) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.withdrawQsr(); AccountBlockUtils.createAccountBlock( transactionParams, 'withdraw ${kQsrCoin.symbol} from Pillar Slot', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/undelegate_button_bloc.dart b/lib/blocs/pillars/undelegate_button_bloc.dart index 6366b9de..2b021a38 100644 --- a/lib/blocs/pillars/undelegate_button_bloc.dart +++ b/lib/blocs/pillars/undelegate_button_bloc.dart @@ -9,21 +9,19 @@ class UndelegateButtonBloc extends BaseBloc { void cancelPillarVoting(BuildContext context) { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.undelegate(); AccountBlockUtils.createAccountBlock( transactionParams, 'undelegate', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/pillars/update_pillar_bloc.dart b/lib/blocs/pillars/update_pillar_bloc.dart index d1a20f38..024e813a 100644 --- a/lib/blocs/pillars/update_pillar_bloc.dart +++ b/lib/blocs/pillars/update_pillar_bloc.dart @@ -13,7 +13,7 @@ class UpdatePillarBloc extends BaseBloc { ) { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.pillar.updatePillar( name, producerAddress, @@ -26,12 +26,10 @@ class UpdatePillarBloc extends BaseBloc { 'update pillar', ) .then( - (block) => addEvent(block), + addEvent, ) .onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/plasma/cancel_plasma_bloc.dart b/lib/blocs/plasma/cancel_plasma_bloc.dart index 465ba8a9..100098cf 100644 --- a/lib/blocs/plasma/cancel_plasma_bloc.dart +++ b/lib/blocs/plasma/cancel_plasma_bloc.dart @@ -9,20 +9,18 @@ class CancelPlasmaBloc extends BaseBloc { void cancelPlasmaStaking(String id, BuildContext context) { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.plasma.cancel( + final AccountBlockTemplate transactionParams = zenon!.embedded.plasma.cancel( Hash.parse(id), ); AccountBlockUtils.createAccountBlock(transactionParams, 'cancel Plasma', - waitForRequiredPlasma: true) + waitForRequiredPlasma: true,) .then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/plasma/plasma.dart b/lib/blocs/plasma/plasma.dart index d7c6a287..02d1262f 100644 --- a/lib/blocs/plasma/plasma.dart +++ b/lib/blocs/plasma/plasma.dart @@ -1,4 +1,3 @@ -library plasma; export 'cancel_plasma_bloc.dart'; export 'plasma_list_bloc.dart'; diff --git a/lib/blocs/plasma/plasma_list_bloc.dart b/lib/blocs/plasma/plasma_list_bloc.dart index 5ed813b0..1f74e12b 100644 --- a/lib/blocs/plasma/plasma_list_bloc.dart +++ b/lib/blocs/plasma/plasma_list_bloc.dart @@ -10,16 +10,16 @@ class PlasmaListBloc extends InfiniteScrollBloc { @override Future> getData(int pageKey, int pageSize) async { - List results = + final List results = (await zenon!.embedded.plasma.getEntriesByAddress( Address.parse(kSelectedAddress!), pageIndex: pageKey, pageSize: pageSize, )) .list; - Momentum lastMomentum = await zenon!.ledger.getFrontierMomentum(); + final Momentum lastMomentum = await zenon!.ledger.getFrontierMomentum(); lastMomentumHeight = lastMomentum.height; - for (var fusionEntry in results) { + for (final FusionEntry fusionEntry in results) { fusionEntry.isRevocable = lastMomentum.height > fusionEntry.expirationHeight; } diff --git a/lib/blocs/plasma/plasma_options_bloc.dart b/lib/blocs/plasma/plasma_options_bloc.dart index 7ed77b93..da315865 100644 --- a/lib/blocs/plasma/plasma_options_bloc.dart +++ b/lib/blocs/plasma/plasma_options_bloc.dart @@ -9,7 +9,7 @@ class PlasmaOptionsBloc extends BaseBloc { void generatePlasma(String beneficiaryAddress, BigInt amount) { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.plasma.fuse( + final AccountBlockTemplate transactionParams = zenon!.embedded.plasma.fuse( Address.parse(beneficiaryAddress), amount, ); @@ -18,14 +18,12 @@ class PlasmaOptionsBloc extends BaseBloc { 'fuse ${kQsrCoin.symbol} for Plasma', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/plasma/plasma_stats_bloc.dart b/lib/blocs/plasma/plasma_stats_bloc.dart index 6f487c69..dbaf56a0 100644 --- a/lib/blocs/plasma/plasma_stats_bloc.dart +++ b/lib/blocs/plasma/plasma_stats_bloc.dart @@ -14,8 +14,8 @@ class PlasmaStatsBloc extends BaseBloc> Future getPlasmas() async { try { - List plasmaInfoWrapper = await Future.wait( - kDefaultAddressList.map((e) => _getPlasma(e!)).toList(), + final List plasmaInfoWrapper = await Future.wait( + kDefaultAddressList.map((String? e) => _getPlasma(e!)).toList(), ); addEvent(plasmaInfoWrapper); } catch (e, stackTrace) { @@ -25,7 +25,7 @@ class PlasmaStatsBloc extends BaseBloc> Future _getPlasma(String address) async { try { - PlasmaInfo plasmaInfo = await zenon!.embedded.plasma.get( + final PlasmaInfo plasmaInfo = await zenon!.embedded.plasma.get( Address.parse(address), ); return PlasmaInfoWrapper(address: address, plasmaInfo: plasmaInfo); diff --git a/lib/blocs/refresh_bloc_mixin.dart b/lib/blocs/refresh_bloc_mixin.dart index da2453ea..09f54700 100644 --- a/lib/blocs/refresh_bloc_mixin.dart +++ b/lib/blocs/refresh_bloc_mixin.dart @@ -8,7 +8,7 @@ mixin RefreshBlocMixin { void listenToWsRestart(VoidCallback onWsConnectionRestartedCallback) { _restartWsStreamSubscription = zenon!.wsClient.restartedStream.listen( - (restarted) { + (bool restarted) { if (restarted) { onWsConnectionRestartedCallback(); } diff --git a/lib/blocs/sentinels/disassemble_button_bloc.dart b/lib/blocs/sentinels/disassemble_button_bloc.dart index e3a7b29c..88e1f7e1 100644 --- a/lib/blocs/sentinels/disassemble_button_bloc.dart +++ b/lib/blocs/sentinels/disassemble_button_bloc.dart @@ -9,21 +9,19 @@ class DisassembleButtonBloc extends BaseBloc { Future disassembleSentinel(BuildContext context) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.sentinel.revoke(); AccountBlockUtils.createAccountBlock( transactionParams, 'disassemble Sentinel', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/sentinels/sentinel_deposit_qsr_bloc.dart b/lib/blocs/sentinels/sentinel_deposit_qsr_bloc.dart index 79b8e495..8f14ba6d 100644 --- a/lib/blocs/sentinels/sentinel_deposit_qsr_bloc.dart +++ b/lib/blocs/sentinels/sentinel_deposit_qsr_bloc.dart @@ -16,7 +16,7 @@ class SentinelsDepositQsrBloc extends BaseBloc { try { addEvent(null); if (!justMarkStepCompleted) { - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.sentinel.depositQsr( amount, ); @@ -25,7 +25,7 @@ class SentinelsDepositQsrBloc extends BaseBloc { 'deposit ${kQsrCoin.symbol} for Sentinel Slot', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed( kDelayAfterAccountBlockCreationCall, ); @@ -33,9 +33,7 @@ class SentinelsDepositQsrBloc extends BaseBloc { addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } } catch (e, stackTrace) { diff --git a/lib/blocs/sentinels/sentinel_qsr_info_bloc.dart b/lib/blocs/sentinels/sentinel_qsr_info_bloc.dart index 978b80d3..1491b4f6 100644 --- a/lib/blocs/sentinels/sentinel_qsr_info_bloc.dart +++ b/lib/blocs/sentinels/sentinel_qsr_info_bloc.dart @@ -7,10 +7,10 @@ class SentinelsQsrInfoBloc extends BaseBloc { Future getQsrManagementInfo(String address) async { try { addEvent(null); - BigInt deposit = (await zenon!.embedded.sentinel.getDepositedQsr( + final BigInt deposit = await zenon!.embedded.sentinel.getDepositedQsr( Address.parse(address), - )); - BigInt cost = sentinelRegisterQsrAmount; + ); + final BigInt cost = sentinelRegisterQsrAmount; addEvent( SentinelsQsrInfo( deposit: deposit, diff --git a/lib/blocs/sentinels/sentinel_register_bloc.dart b/lib/blocs/sentinels/sentinel_register_bloc.dart index 8c73624d..429076fb 100644 --- a/lib/blocs/sentinels/sentinel_register_bloc.dart +++ b/lib/blocs/sentinels/sentinel_register_bloc.dart @@ -8,21 +8,19 @@ class SentinelsDeployBloc extends BaseBloc { Future deploySentinel(BigInt amount) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.sentinel.register(); AccountBlockUtils.createAccountBlock( transactionParams, 'register Sentinel', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/sentinels/sentinel_rewards_history_bloc.dart b/lib/blocs/sentinels/sentinel_rewards_history_bloc.dart index 5a3a25bf..a516bb74 100644 --- a/lib/blocs/sentinels/sentinel_rewards_history_bloc.dart +++ b/lib/blocs/sentinels/sentinel_rewards_history_bloc.dart @@ -8,13 +8,13 @@ class SentinelRewardsHistoryBloc extends BaseBlocForReloadingIndicator { @override Future getDataAsync() async { - RewardHistoryList response = + final RewardHistoryList response = await zenon!.embedded.sentinel.getFrontierRewardByPage( Address.parse(kSelectedAddress!), pageSize: kStandardChartNumDays.toInt(), ); if (response.list.any( - (element) => + (RewardHistoryEntry element) => element.qsrAmount > BigInt.zero || element.znnAmount > BigInt.zero, )) { return response; diff --git a/lib/blocs/sentinels/sentinel_withdraw_qsr_bloc.dart b/lib/blocs/sentinels/sentinel_withdraw_qsr_bloc.dart index bc32ee4b..2a61de7e 100644 --- a/lib/blocs/sentinels/sentinel_withdraw_qsr_bloc.dart +++ b/lib/blocs/sentinels/sentinel_withdraw_qsr_bloc.dart @@ -12,22 +12,20 @@ class SentinelsWithdrawQsrBloc extends BaseBloc { withdrawQsr(String address) async { try { addEvent(null); - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.sentinel.withdrawQsr(); AccountBlockUtils.createAccountBlock( transactionParams, 'withdraw ${kQsrCoin.symbol} from Sentinel Slot', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/sentinels/sentinels.dart b/lib/blocs/sentinels/sentinels.dart index 23523180..fd1c74c7 100644 --- a/lib/blocs/sentinels/sentinels.dart +++ b/lib/blocs/sentinels/sentinels.dart @@ -1,4 +1,3 @@ -library sentinels; export 'disassemble_button_bloc.dart'; export 'get_sentinel_by_owner_bloc.dart'; diff --git a/lib/blocs/settings/account_chain_stats_bloc.dart b/lib/blocs/settings/account_chain_stats_bloc.dart index 6583266b..2146c715 100644 --- a/lib/blocs/settings/account_chain_stats_bloc.dart +++ b/lib/blocs/settings/account_chain_stats_bloc.dart @@ -8,28 +8,27 @@ class AccountChainStatsBloc extends BaseBlocForReloadingIndicator { @override Future getDataAsync() async { - AccountInfo accountInfo = await zenon!.ledger.getAccountInfoByAddress( + final AccountInfo accountInfo = await zenon!.ledger.getAccountInfoByAddress( Address.parse( kSelectedAddress!, ), ); - int pageSize = accountInfo.blockCount!; - int pageCount = ((pageSize + 1) / rpcMaxPageSize).ceil(); + final int pageSize = accountInfo.blockCount!; + final int pageCount = ((pageSize + 1) / rpcMaxPageSize).ceil(); if (pageSize > 0) { - List allBlocks = []; + final List allBlocks = []; - for (var i = 0; i < pageCount; i++) { + for (int i = 0; i < pageCount; i++) { allBlocks.addAll((await zenon!.ledger.getAccountBlocksByHeight( Address.parse( kSelectedAddress!, ), (rpcMaxPageSize * i) + 1, - rpcMaxPageSize, )) .list ?? - []); + [],); } return AccountChainStats( @@ -43,10 +42,10 @@ class AccountChainStatsBloc } Map _getNumOfBlocksForEachBlockType( - List blocks) => + List blocks,) => BlockTypeEnum.values.fold>( - {}, - (previousValue, blockType) { + {}, + (Map previousValue, BlockTypeEnum blockType) { previousValue[blockType] = _getNumOfBlockForBlockType(blocks, blockType); return previousValue; @@ -54,10 +53,10 @@ class AccountChainStatsBloc ); int _getNumOfBlockForBlockType( - List blocks, BlockTypeEnum blockType) => + List blocks, BlockTypeEnum blockType,) => blocks.fold( 0, - (dynamic previousValue, element) { + (int previousValue, AccountBlock element) { if (element.blockType == blockType.index) { return previousValue + 1; } diff --git a/lib/blocs/settings/general_stats_bloc.dart b/lib/blocs/settings/general_stats_bloc.dart index b94a0579..3f3a0323 100644 --- a/lib/blocs/settings/general_stats_bloc.dart +++ b/lib/blocs/settings/general_stats_bloc.dart @@ -10,11 +10,11 @@ class GeneralStatsBloc extends BaseBlocWithRefreshMixin { @override Future getDataAsync() async { - GeneralStats generalStats = GeneralStats( + final GeneralStats generalStats = GeneralStats( frontierMomentum: await zenon!.ledger.getFrontierMomentum(), processInfo: await zenon!.stats.processInfo(), networkInfo: await zenon!.stats.networkInfo(), - osInfo: await zenon!.stats.osInfo()); + osInfo: await zenon!.stats.osInfo(),); if (_timer == null || !_timer!.isActive) { _timer = _getTimer(); } diff --git a/lib/blocs/settings/peers_bloc.dart b/lib/blocs/settings/peers_bloc.dart index 2823cac0..88c7c704 100644 --- a/lib/blocs/settings/peers_bloc.dart +++ b/lib/blocs/settings/peers_bloc.dart @@ -4,5 +4,5 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PeersBloc extends BaseBlocWithRefreshMixin { @override - Future getDataAsync() async => await zenon!.stats.networkInfo(); + Future getDataAsync() async => zenon!.stats.networkInfo(); } diff --git a/lib/blocs/settings/settings.dart b/lib/blocs/settings/settings.dart index dbde5077..c167ae4d 100644 --- a/lib/blocs/settings/settings.dart +++ b/lib/blocs/settings/settings.dart @@ -1,4 +1,3 @@ -library settings; export 'account_chain_stats_bloc.dart'; export 'general_stats_bloc.dart'; diff --git a/lib/blocs/staking/cancel_stake_bloc.dart b/lib/blocs/staking/cancel_stake_bloc.dart index f0838fa8..199cca25 100644 --- a/lib/blocs/staking/cancel_stake_bloc.dart +++ b/lib/blocs/staking/cancel_stake_bloc.dart @@ -9,7 +9,7 @@ class CancelStakeBloc extends BaseBloc { void cancelStake(String hash, BuildContext context) { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.stake.cancel( + final AccountBlockTemplate transactionParams = zenon!.embedded.stake.cancel( Hash.parse(hash), ); AccountBlockUtils.createAccountBlock( @@ -17,14 +17,12 @@ class CancelStakeBloc extends BaseBloc { 'cancel stake', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/staking/staking.dart b/lib/blocs/staking/staking.dart index dd177baa..58aac804 100644 --- a/lib/blocs/staking/staking.dart +++ b/lib/blocs/staking/staking.dart @@ -1,4 +1,3 @@ -library staking; export 'cancel_stake_bloc.dart'; export 'staking_list_bloc.dart'; diff --git a/lib/blocs/staking/staking_options_bloc.dart b/lib/blocs/staking/staking_options_bloc.dart index 50e8a417..d1981dbc 100644 --- a/lib/blocs/staking/staking_options_bloc.dart +++ b/lib/blocs/staking/staking_options_bloc.dart @@ -11,21 +11,19 @@ class StakingOptionsBloc extends BaseBloc { ) { try { addEvent(null); - AccountBlockTemplate transactionParams = zenon!.embedded.stake.stake( + final AccountBlockTemplate transactionParams = zenon!.embedded.stake.stake( stakeDuration.inSeconds, amount, ); AccountBlockUtils.createAccountBlock(transactionParams, 'create stake', - waitForRequiredPlasma: true) + waitForRequiredPlasma: true,) .then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/staking/staking_rewards_history_bloc.dart b/lib/blocs/staking/staking_rewards_history_bloc.dart index 34a3f14e..530998fb 100644 --- a/lib/blocs/staking/staking_rewards_history_bloc.dart +++ b/lib/blocs/staking/staking_rewards_history_bloc.dart @@ -8,12 +8,12 @@ class StakingRewardsHistoryBloc extends BaseBlocForReloadingIndicator { @override Future getDataAsync() async { - RewardHistoryList? response = + final RewardHistoryList response = await zenon!.embedded.stake.getFrontierRewardByPage( Address.parse(kSelectedAddress!), pageSize: kStandardChartNumDays.toInt(), ); - if (response.list.any((element) => element.qsrAmount > BigInt.zero)) { + if (response.list.any((RewardHistoryEntry element) => element.qsrAmount > BigInt.zero)) { return response; } else { throw 'No rewards in the last week'; diff --git a/lib/blocs/tokens/burn_token_bloc.dart b/lib/blocs/tokens/burn_token_bloc.dart index e18495bd..48afc023 100644 --- a/lib/blocs/tokens/burn_token_bloc.dart +++ b/lib/blocs/tokens/burn_token_bloc.dart @@ -10,21 +10,19 @@ class BurnTokenBloc extends BaseBloc { BigInt amount, ) { try { - AccountBlockTemplate transactionParams = zenon!.embedded.token.burnToken( + final AccountBlockTemplate transactionParams = zenon!.embedded.token.burnToken( token.tokenStandard, amount, ); AccountBlockUtils.createAccountBlock(transactionParams, 'burn token', - waitForRequiredPlasma: true) + waitForRequiredPlasma: true,) .then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/tokens/issue_token_bloc.dart b/lib/blocs/tokens/issue_token_bloc.dart index 8075106c..c5252ca6 100644 --- a/lib/blocs/tokens/issue_token_bloc.dart +++ b/lib/blocs/tokens/issue_token_bloc.dart @@ -10,7 +10,7 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class IssueTokenBloc extends BaseBloc { void issueToken(NewTokenData tokenStepperData) { try { - AccountBlockTemplate transactionParams = zenon!.embedded.token.issueToken( + final AccountBlockTemplate transactionParams = zenon!.embedded.token.issueToken( tokenStepperData.tokenName, tokenStepperData.tokenSymbol, tokenStepperData.tokenDomain, @@ -19,21 +19,19 @@ class IssueTokenBloc extends BaseBloc { tokenStepperData.decimals, tokenStepperData.isMintable!, tokenStepperData.isOwnerBurnOnly!, - tokenStepperData.isUtility!); + tokenStepperData.isUtility!,); AccountBlockUtils.createAccountBlock( transactionParams, 'issue token', waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { Hive.box(kFavoriteTokensBox).add(response.tokenStandard.toString()); ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/tokens/mint_token_bloc.dart b/lib/blocs/tokens/mint_token_bloc.dart index fb06d9c0..95112d12 100644 --- a/lib/blocs/tokens/mint_token_bloc.dart +++ b/lib/blocs/tokens/mint_token_bloc.dart @@ -11,23 +11,21 @@ class MintTokenBloc extends BaseBloc { Address beneficiaryAddress, ) { try { - AccountBlockTemplate transactionParams = zenon!.embedded.token.mintToken( + final AccountBlockTemplate transactionParams = zenon!.embedded.token.mintToken( token.tokenStandard, amount, beneficiaryAddress, ); AccountBlockUtils.createAccountBlock(transactionParams, 'mint token', - waitForRequiredPlasma: true) + waitForRequiredPlasma: true,) .then( - (response) { + (AccountBlockTemplate response) { response.amount = amount; ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/tokens/token_map_bloc.dart b/lib/blocs/tokens/token_map_bloc.dart index 9756e1ad..56fe26c1 100644 --- a/lib/blocs/tokens/token_map_bloc.dart +++ b/lib/blocs/tokens/token_map_bloc.dart @@ -11,7 +11,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TokenMapBloc with RefreshBlocMixin { - List? _allTokens; TokenMapBloc() { _onPageRequest.stream @@ -26,6 +25,7 @@ class TokenMapBloc with RefreshBlocMixin { listenToWsRestart(refreshResults); } + List? _allTokens; void refreshResults() { if (!_onSearchInputChangedSubject.isClosed) { @@ -38,11 +38,11 @@ class TokenMapBloc with RefreshBlocMixin { yield* _fetchList(0); } - static const _pageSize = 10; + static const int _pageSize = 10; - final _subscriptions = CompositeSubscription(); + final CompositeSubscription _subscriptions = CompositeSubscription(); - final _onNewListingStateController = + final BehaviorSubject> _onNewListingStateController = BehaviorSubject>.seeded( InfiniteScrollBlocListingState(), ); @@ -50,11 +50,11 @@ class TokenMapBloc with RefreshBlocMixin { Stream> get onNewListingState => _onNewListingStateController.stream; - final _onPageRequest = StreamController(); + final StreamController _onPageRequest = StreamController(); Sink get onPageRequestSink => _onPageRequest.sink; - final _onSearchInputChangedSubject = BehaviorSubject.seeded(null); + final BehaviorSubject _onSearchInputChangedSubject = BehaviorSubject.seeded(null); Sink get onRefreshResultsRequest => _onSearchInputChangedSubject.sink; @@ -68,15 +68,14 @@ class TokenMapBloc with RefreshBlocMixin { String? get _searchInputTerm => _onSearchInputChangedSubject.value; Stream> _fetchList(int pageKey) async* { - final lastListingState = _onNewListingStateController.value; + final InfiniteScrollBlocListingState lastListingState = _onNewListingStateController.value; try { - final newItems = await getData(pageKey, _pageSize, _searchInputTerm); - final isLastPage = newItems.length < _pageSize; - final nextPageKey = isLastPage ? null : pageKey + 1; - List allItems = [...lastListingState.itemList ?? [], ...newItems]; + final List newItems = await getData(pageKey, _pageSize, _searchInputTerm); + final bool isLastPage = newItems.length < _pageSize; + final int? nextPageKey = isLastPage ? null : pageKey + 1; + List allItems = [...lastListingState.itemList ?? [], ...newItems]; allItems = filterItemsFunction(allItems); yield InfiniteScrollBlocListingState( - error: null, nextPageKey: nextPageKey, itemList: allItems, ); @@ -99,9 +98,9 @@ class TokenMapBloc with RefreshBlocMixin { List _sortTokenList(List tokens) { tokens = tokens.fold>( - [], - (previousValue, token) { - if (![kZnnCoin.tokenStandard, kQsrCoin.tokenStandard] + [], + (List previousValue, Token token) { + if (![kZnnCoin.tokenStandard, kQsrCoin.tokenStandard] .contains(token.tokenStandard)) { previousValue.add(token); } @@ -113,9 +112,9 @@ class TokenMapBloc with RefreshBlocMixin { } List _sortByIfTokenCreatedByUser(List tokens) { - List sortedTokens = tokens + final List sortedTokens = tokens .where( - (token) => kDefaultAddressList.contains( + (Token token) => kDefaultAddressList.contains( token.owner.toString(), ), ) @@ -123,21 +122,21 @@ class TokenMapBloc with RefreshBlocMixin { sortedTokens.addAll(tokens .where( - (token) => !kDefaultAddressList.contains( + (Token token) => !kDefaultAddressList.contains( token.owner.toString(), ), ) - .toList()); + .toList(),); return sortedTokens; } List _sortByIfTokenIsInFavorites(List tokens) { - Box favoriteTokens = Hive.box(kFavoriteTokensBox); + final Box favoriteTokens = Hive.box(kFavoriteTokensBox); - List sortedTokens = tokens + final List sortedTokens = tokens .where( - (token) => favoriteTokens.values.contains( + (Token token) => favoriteTokens.values.contains( token.tokenStandard.toString(), ), ) @@ -145,11 +144,11 @@ class TokenMapBloc with RefreshBlocMixin { sortedTokens.addAll(tokens .where( - (token) => !favoriteTokens.values.contains( + (Token token) => !favoriteTokens.values.contains( token.tokenStandard.toString(), ), ) - .toList()); + .toList(),); return sortedTokens; } @@ -166,7 +165,7 @@ class TokenMapBloc with RefreshBlocMixin { )) .list!; } else { - return await _getDataBySearchTerm(pageKey, pageSize, searchTerm); + return _getDataBySearchTerm(pageKey, pageSize, searchTerm); } } @@ -179,8 +178,8 @@ class TokenMapBloc with RefreshBlocMixin { String searchTerm, ) async { _allTokens ??= (await zenon!.embedded.token.getAll()).list!; - Iterable results = _allTokens!.where((token) => - token.symbol.toLowerCase().contains(searchTerm.toLowerCase())); + final Iterable results = _allTokens!.where((Token token) => + token.symbol.toLowerCase().contains(searchTerm.toLowerCase()),); results.toList().sublist( pageKey * pageSize, (pageKey + 1) * pageSize <= results.length @@ -188,8 +187,8 @@ class TokenMapBloc with RefreshBlocMixin { : results.length, ); return results - .where((token) => - token.symbol.toLowerCase().contains(searchTerm.toLowerCase())) + .where((Token token) => + token.symbol.toLowerCase().contains(searchTerm.toLowerCase()),) .toList(); } } diff --git a/lib/blocs/tokens/tokens.dart b/lib/blocs/tokens/tokens.dart index 6587db06..a1a566c4 100644 --- a/lib/blocs/tokens/tokens.dart +++ b/lib/blocs/tokens/tokens.dart @@ -1,4 +1,3 @@ -library tokens; export 'burn_token_bloc.dart'; export 'issue_token_bloc.dart'; diff --git a/lib/blocs/tokens/tokens_bloc.dart b/lib/blocs/tokens/tokens_bloc.dart index a89556de..87b5d6af 100644 --- a/lib/blocs/tokens/tokens_bloc.dart +++ b/lib/blocs/tokens/tokens_bloc.dart @@ -5,7 +5,7 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TokensBloc extends BaseBloc?> with RefreshBlocMixin { TokensBloc() { zenon!.wsClient.restartedStream.listen( - (restarted) { + (bool restarted) { if (restarted) { getDataAsync(); } diff --git a/lib/blocs/tokens/transfer_ownership_bloc.dart b/lib/blocs/tokens/transfer_ownership_bloc.dart index a5c7ca14..861c0226 100644 --- a/lib/blocs/tokens/transfer_ownership_bloc.dart +++ b/lib/blocs/tokens/transfer_ownership_bloc.dart @@ -11,7 +11,7 @@ class TransferOwnershipBloc extends BaseBloc { bool isBurnable, ) { try { - AccountBlockTemplate transactionParams = + final AccountBlockTemplate transactionParams = zenon!.embedded.token.updateToken( tokenStandard, owner, @@ -24,12 +24,10 @@ class TransferOwnershipBloc extends BaseBloc { waitForRequiredPlasma: true, ) .then( - (value) => addEvent(value), + addEvent, ) .onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/transfer/receive_transaction_bloc.dart b/lib/blocs/transfer/receive_transaction_bloc.dart index 83e347bb..aca53414 100644 --- a/lib/blocs/transfer/receive_transaction_bloc.dart +++ b/lib/blocs/transfer/receive_transaction_bloc.dart @@ -4,10 +4,10 @@ import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ReceiveTransactionBloc extends BaseBloc { - void receiveTransaction(String id, BuildContext context) async { + Future receiveTransaction(String id, BuildContext context) async { try { addEvent(null); - var response = await sl() + final AccountBlockTemplate? response = await sl() .autoReceiveTransactionHash(Hash.parse(id)); addEvent(response); } catch (e, stackTrace) { diff --git a/lib/blocs/transfer/send_payment_bloc.dart b/lib/blocs/transfer/send_payment_bloc.dart index 626172b0..c224349a 100644 --- a/lib/blocs/transfer/send_payment_bloc.dart +++ b/lib/blocs/transfer/send_payment_bloc.dart @@ -4,7 +4,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SendPaymentBloc extends BaseBloc { - void sendTransfer({ + Future sendTransfer({ // TODO: make this argument non-nullable String? fromAddress, String? toAddress, @@ -23,7 +23,7 @@ class SendPaymentBloc extends BaseBloc { ); try { addEvent(null); - AccountBlockTemplate accountBlock = block ?? + final AccountBlockTemplate accountBlock = block ?? AccountBlockTemplate.send( Address.parse(toAddress!), token!.tokenStandard, @@ -36,14 +36,12 @@ class SendPaymentBloc extends BaseBloc { address: Address.parse(fromAddress!), waitForRequiredPlasma: true, ).then( - (response) { + (AccountBlockTemplate response) { ZenonAddressUtils.refreshBalance(); addEvent(response); }, ).onError( - (error, stackTrace) { - addError(error, stackTrace); - }, + addError, ); } catch (e, stackTrace) { addError(e, stackTrace); diff --git a/lib/blocs/transfer/transfer.dart b/lib/blocs/transfer/transfer.dart index 525ca70a..e2c5bb2d 100644 --- a/lib/blocs/transfer/transfer.dart +++ b/lib/blocs/transfer/transfer.dart @@ -1,4 +1,3 @@ -library transfer; export 'latest_transactions_bloc.dart'; export 'send_payment_bloc.dart'; diff --git a/lib/blocs/transfer/transfer_widgets_balance_bloc.dart b/lib/blocs/transfer/transfer_widgets_balance_bloc.dart index 7192d31e..bc89b40b 100644 --- a/lib/blocs/transfer/transfer_widgets_balance_bloc.dart +++ b/lib/blocs/transfer/transfer_widgets_balance_bloc.dart @@ -14,13 +14,13 @@ class TransferWidgetsBalanceBloc extends BaseBloc?> Future getBalanceForAllAddresses() async { try { addEvent(null); - Map addressBalanceMap = {}; - List accountInfoList = await Future.wait( + final Map addressBalanceMap = {}; + final List accountInfoList = await Future.wait( kDefaultAddressList.map( - (address) => _getBalancePerAddress(address!), + (String? address) => _getBalancePerAddress(address!), ), ); - for (var accountInfo in accountInfoList) { + for (final AccountInfo accountInfo in accountInfoList) { addressBalanceMap[accountInfo.address!] = accountInfo; } addEvent(addressBalanceMap); @@ -30,7 +30,7 @@ class TransferWidgetsBalanceBloc extends BaseBloc?> } Future _getBalancePerAddress(String address) async => - await zenon!.ledger.getAccountInfoByAddress( + zenon!.ledger.getAccountInfoByAddress( Address.parse(address), ); } diff --git a/lib/blocs/wallet_connect/chains/nom_service.dart b/lib/blocs/wallet_connect/chains/nom_service.dart index 02bc3f1d..b1dfe576 100644 --- a/lib/blocs/wallet_connect/chains/nom_service.dart +++ b/lib/blocs/wallet_connect/chains/nom_service.dart @@ -28,10 +28,8 @@ extension NoMChainIdX on NoMChainId { switch (this) { case NoMChainId.mainnet: name = '1'; - break; case NoMChainId.testnet: name = '3'; - break; } return '${NoMService.namespace}:$name'; @@ -39,18 +37,6 @@ extension NoMChainIdX on NoMChainId { } class NoMService extends IChain { - static const namespace = 'zenon'; - - final IWeb3WalletService _web3WalletService = sl(); - - final NoMChainId reference; - - final _walletLockedError = const WalletConnectError( - code: 9000, - message: 'Wallet is locked', - ); - - Web3Wallet? wallet; NoMService({ required this.reference, @@ -78,6 +64,18 @@ class NoMService extends IChain { handler: _methodZnnSend, ); } + static const String namespace = 'zenon'; + + final IWeb3WalletService _web3WalletService = sl(); + + final NoMChainId reference; + + final WalletConnectError _walletLockedError = const WalletConnectError( + code: 9000, + message: 'Wallet is locked', + ); + + Web3Wallet? wallet; @override String getNamespace() { @@ -91,17 +89,17 @@ class NoMService extends IChain { @override List getEvents() { - return ['chainIdChange', 'addressChange']; + return ['chainIdChange', 'addressChange']; } Future _methodZnnInfo(String topic, dynamic params) async { if (!await windowManager.isFocused() || !await windowManager.isVisible()) { windowManager.show(); } - final dAppMetadata = wallet! + final PairingMetadata dAppMetadata = wallet! .getActiveSessions() .values - .firstWhere((element) => element.topic == topic) + .firstWhere((SessionData element) => element.topic == topic) .peer .metadata; @@ -113,14 +111,13 @@ class NoMService extends IChain { title: '${dAppMetadata.name} - Information', content: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text('Are you sure you want to allow ${dAppMetadata.name} to ' 'retrieve the current address, node URL and chain identifier information?'), kVerticalSpacing, Image( image: NetworkImage(dAppMetadata.icons.first), - height: 100.0, + height: 100, fit: BoxFit.fitHeight, ), kVerticalSpacing, @@ -128,11 +125,11 @@ class NoMService extends IChain { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text(dAppMetadata.url), LinkIcon( url: dAppMetadata.url, - ) + ), ], ), ], @@ -142,7 +139,7 @@ class NoMService extends IChain { ); if (actionWasAccepted) { - return { + return { 'address': kSelectedAddress, 'nodeUrl': kCurrentNode, 'chainId': getChainIdentifier(), @@ -150,7 +147,7 @@ class NoMService extends IChain { } else { await NotificationUtils.sendNotificationError( Errors.getSdkError(Errors.USER_REJECTED), - 'You have rejected the WalletConnect request'); + 'You have rejected the WalletConnect request',); throw Errors.getSdkError(Errors.USER_REJECTED); } } else { @@ -165,14 +162,14 @@ class NoMService extends IChain { if (!await windowManager.isFocused() || !await windowManager.isVisible()) { windowManager.show(); } - final dAppMetadata = wallet! + final PairingMetadata dAppMetadata = wallet! .getActiveSessions() .values - .firstWhere((element) => element.topic == topic) + .firstWhere((SessionData element) => element.topic == topic) .peer .metadata; if (kCurrentPage != Tabs.lock) { - final message = params as String; + final String message = params as String; if (globalNavigatorKey.currentContext!.mounted) { final actionWasAccepted = await showDialogWithNoAndYesOptions( @@ -181,14 +178,13 @@ class NoMService extends IChain { title: '${dAppMetadata.name} - Sign Message', content: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text('Are you sure you want to ' 'sign message $message ?'), kVerticalSpacing, Image( image: NetworkImage(dAppMetadata.icons.first), - height: 100.0, + height: 100, fit: BoxFit.fitHeight, ), kVerticalSpacing, @@ -196,11 +192,11 @@ class NoMService extends IChain { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text(dAppMetadata.url), LinkIcon( url: dAppMetadata.url, - ) + ), ], ), ], @@ -210,11 +206,11 @@ class NoMService extends IChain { ); if (actionWasAccepted) { - return await walletSign(message.codeUnits); + return walletSign(message.codeUnits); } else { await NotificationUtils.sendNotificationError( Errors.getSdkError(Errors.USER_REJECTED), - 'You have rejected the WalletConnect request'); + 'You have rejected the WalletConnect request',); throw Errors.getSdkError(Errors.USER_REJECTED); } } else { @@ -229,26 +225,26 @@ class NoMService extends IChain { if (!await windowManager.isFocused() || !await windowManager.isVisible()) { windowManager.show(); } - final dAppMetadata = wallet! + final PairingMetadata dAppMetadata = wallet! .getActiveSessions() .values - .firstWhere((element) => element.topic == topic) + .firstWhere((SessionData element) => element.topic == topic) .peer .metadata; if (kCurrentPage != Tabs.lock) { - final accountBlock = + final AccountBlockTemplate accountBlock = AccountBlockTemplate.fromJson(params['accountBlock']); - final toAddress = ZenonAddressUtils.getLabel( + final String toAddress = ZenonAddressUtils.getLabel( accountBlock.toAddress.toString(), ); - final token = + final Token? token = await zenon!.embedded.token.getByZts(accountBlock.tokenStandard); - final amount = accountBlock.amount.addDecimals(token!.decimals); + final String amount = accountBlock.amount.addDecimals(token!.decimals); - final sendPaymentBloc = SendPaymentBloc(); + final SendPaymentBloc sendPaymentBloc = SendPaymentBloc(); if (globalNavigatorKey.currentContext!.mounted) { final wasActionAccepted = await showDialogWithNoAndYesOptions( @@ -257,15 +253,14 @@ class NoMService extends IChain { title: '${dAppMetadata.name} - Send Payment', content: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text('Are you sure you want to transfer ' '$amount ${token.symbol} to ' '$toAddress ?'), kVerticalSpacing, Image( image: NetworkImage(dAppMetadata.icons.first), - height: 100.0, + height: 100, fit: BoxFit.fitHeight, ), kVerticalSpacing, @@ -273,11 +268,11 @@ class NoMService extends IChain { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text(dAppMetadata.url), LinkIcon( url: dAppMetadata.url, - ) + ), ], ), ], @@ -295,15 +290,15 @@ class NoMService extends IChain { block: AccountBlockTemplate.fromJson(params['accountBlock']), ); - final result = await sendPaymentBloc.stream.firstWhere( - (element) => element != null, + final AccountBlockTemplate? result = await sendPaymentBloc.stream.firstWhere( + (AccountBlockTemplate? element) => element != null, ); return result!; } else { await NotificationUtils.sendNotificationError( Errors.getSdkError(Errors.USER_REJECTED), - 'You have rejected the WalletConnect request'); + 'You have rejected the WalletConnect request',); throw Errors.getSdkError(Errors.USER_REJECTED); } } else { diff --git a/lib/blocs/wallet_connect/wallet_connect_sessions_bloc.dart b/lib/blocs/wallet_connect/wallet_connect_sessions_bloc.dart index 4d91c736..fada4f7e 100644 --- a/lib/blocs/wallet_connect/wallet_connect_sessions_bloc.dart +++ b/lib/blocs/wallet_connect/wallet_connect_sessions_bloc.dart @@ -8,9 +8,9 @@ class WalletConnectSessionsBloc extends InfiniteScrollBloc { @override Future> getData(int pageKey, int pageSize) async { - final wcService = sl.get(); - final sessions = []; - for (var pairing in wcService.pairings.value) { + final IWeb3WalletService wcService = sl.get(); + final List sessions = []; + for (final PairingInfo pairing in wcService.pairings.value) { sessions.addAll( wcService.getSessionsForPairing(pairing.topic).values, ); diff --git a/lib/embedded_node/embedded_node.dart b/lib/embedded_node/embedded_node.dart index 2cb5d5d9..3441e611 100644 --- a/lib/embedded_node/embedded_node.dart +++ b/lib/embedded_node/embedded_node.dart @@ -9,25 +9,23 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; -var invalidZnnLibPathException = +ZnnSdkException invalidZnnLibPathException = ZnnSdkException('Library libznn could not be found'); typedef _StopNodeFunc = Pointer Function(); -typedef _StopNode = Pointer Function(); _StopNodeFunc? _stopNodeFunction; typedef _RunNodeFunc = Pointer Function(); -typedef _RunNode = Pointer Function(); _RunNodeFunc? _runNodeFunction; class EmbeddedNode { static void initializeNodeLib() { - var insideSdk = path.join('syrius', 'lib', 'embedded_node', 'blobs'); - var currentPathListParts = path.split(Directory.current.path); + final String insideSdk = path.join('syrius', 'lib', 'embedded_node', 'blobs'); + final List currentPathListParts = path.split(Directory.current.path); currentPathListParts.removeLast(); - var executablePathListParts = path.split(Platform.resolvedExecutable); + final List executablePathListParts = path.split(Platform.resolvedExecutable); executablePathListParts.removeLast(); - var possiblePaths = List.empty(growable: true); + final List possiblePaths = List.empty(growable: true); possiblePaths.add(Directory.current.path); possiblePaths.add( path.join( @@ -43,10 +41,10 @@ class EmbeddedNode { .add(path.join(path.joinAll(executablePathListParts), 'Resources')); possiblePaths.add(path.join(path.joinAll(currentPathListParts), insideSdk)); - var libraryPath = ''; - var found = false; + String libraryPath = ''; + bool found = false; - for (var currentPath in possiblePaths) { + for (final String currentPath in possiblePaths) { libraryPath = path.join(currentPath, 'libznn.so'); if (Platform.isMacOS) { @@ -56,7 +54,7 @@ class EmbeddedNode { libraryPath = path.join(currentPath, 'libznn.dll'); } - var libFile = File(libraryPath); + final File libFile = File(libraryPath); if (libFile.existsSync()) { found = true; @@ -73,20 +71,20 @@ class EmbeddedNode { } // Open the dynamic library - final dylib = DynamicLibrary.open(libraryPath); + final DynamicLibrary dylib = DynamicLibrary.open(libraryPath); - final stopNodeFunctionPointer = + final Pointer> stopNodeFunctionPointer = dylib.lookup>('StopNode'); - _stopNodeFunction = stopNodeFunctionPointer.asFunction<_StopNode>(); + _stopNodeFunction = stopNodeFunctionPointer.asFunction Function()>(); - final runNodeFunctionPointer = + final Pointer> runNodeFunctionPointer = dylib.lookup>('RunNode'); - _runNodeFunction = runNodeFunctionPointer.asFunction<_RunNode>(); + _runNodeFunction = runNodeFunctionPointer.asFunction Function()>(); } - static void runNode(List args) async { - ReceivePort commandsPort = ReceivePort(); - SendPort sendPort = commandsPort.sendPort; + static Future runNode(List args) async { + final ReceivePort commandsPort = ReceivePort(); + final SendPort sendPort = commandsPort.sendPort; IsolateNameServer.registerPortWithName(sendPort, 'embeddedIsolate'); @@ -95,7 +93,7 @@ class EmbeddedNode { } _runNodeFunction!(); - Completer embeddedIsolateCompleter = Completer(); + final Completer embeddedIsolateCompleter = Completer(); commandsPort.listen((event) { _stopNodeFunction!(); IsolateNameServer.removePortNameMapping('embeddedIsolate'); @@ -113,7 +111,7 @@ class EmbeddedNode { } static bool stopNode() { - SendPort? embeddedIsolate = + final SendPort? embeddedIsolate = IsolateNameServer.lookupPortByName('embeddedIsolate'); if (embeddedIsolate != null) { embeddedIsolate.send('stop'); diff --git a/lib/handlers/htlc_swaps_handler.dart b/lib/handlers/htlc_swaps_handler.dart index 5181de93..f6cf095c 100644 --- a/lib/handlers/htlc_swaps_handler.dart +++ b/lib/handlers/htlc_swaps_handler.dart @@ -29,8 +29,8 @@ class HtlcSwapsHandler { } bool get hasActiveIncomingSwaps => - htlcSwapsService!.getSwapsByState([P2pSwapState.active]).firstWhereOrNull( - (e) => e.direction == P2pSwapDirection.incoming) != + htlcSwapsService!.getSwapsByState([P2pSwapState.active]).firstWhereOrNull( + (HtlcSwap e) => e.direction == P2pSwapDirection.incoming,) != null; Future _runPeriodically() async { @@ -38,14 +38,14 @@ class HtlcSwapsHandler { _isRunning = true; await _enableWakelockIfNeeded(); if (!zenon!.wsClient.isClosed()) { - final unresolvedSwaps = htlcSwapsService!.getSwapsByState([ + final List unresolvedSwaps = htlcSwapsService!.getSwapsByState([ P2pSwapState.pending, P2pSwapState.active, - P2pSwapState.reclaimable + P2pSwapState.reclaimable, ]); if (unresolvedSwaps.isNotEmpty) { if (await _areThereNewHtlcBlocks()) { - final newBlocks = await _getNewHtlcBlocks(unresolvedSwaps); + final List newBlocks = await _getNewHtlcBlocks(unresolvedSwaps); await _goThroughHtlcBlocks(newBlocks); } await _checkForExpiredSwaps(); @@ -56,7 +56,7 @@ class HtlcSwapsHandler { } catch (e) { Logger('HtlcSwapsHandler').log(Level.WARNING, '_runPeriodically', e); } finally { - Future.delayed(const Duration(seconds: 5), () => _runPeriodically()); + Future.delayed(const Duration(seconds: 5), _runPeriodically); } } @@ -73,7 +73,7 @@ class HtlcSwapsHandler { Future _getHtlcFrontierHeight() async { try { - final frontier = await zenon!.ledger.getFrontierAccountBlock(htlcAddress); + final AccountBlock? frontier = await zenon!.ledger.getFrontierAccountBlock(htlcAddress); return frontier?.height; } catch (e, stackTrace) { Logger('HtlcSwapsHandler') @@ -83,41 +83,41 @@ class HtlcSwapsHandler { } Future _areThereNewHtlcBlocks() async { - final frontier = await _getHtlcFrontierHeight(); + final int? frontier = await _getHtlcFrontierHeight(); return frontier != null && frontier > htlcSwapsService!.getLastCheckedHtlcBlockHeight(); } Future> _getNewHtlcBlocks(List swaps) async { - final lastCheckedHeight = htlcSwapsService!.getLastCheckedHtlcBlockHeight(); - final oldestSwapStartTime = _getOldestSwapStartTime(swaps) ?? 0; + final int lastCheckedHeight = htlcSwapsService!.getLastCheckedHtlcBlockHeight(); + final int oldestSwapStartTime = _getOldestSwapStartTime(swaps) ?? 0; int lastCheckedBlockTime = 0; if (lastCheckedHeight > 0) { try { lastCheckedBlockTime = (await AccountBlockUtils.getTimeForAccountBlockHeight( - htlcAddress, lastCheckedHeight)) ?? + htlcAddress, lastCheckedHeight,)) ?? lastCheckedBlockTime; } catch (e, stackTrace) { Logger('HtlcSwapsHandler') .log(Level.WARNING, '_getNewHtlcBlocks', e, stackTrace); - return []; + return []; } } try { return await AccountBlockUtils.getAccountBlocksAfterTime( - htlcAddress, max(oldestSwapStartTime, lastCheckedBlockTime)); + htlcAddress, max(oldestSwapStartTime, lastCheckedBlockTime),); } catch (e, stackTrace) { Logger('HtlcSwapsHandler') .log(Level.WARNING, '_getNewHtlcBlocks', e, stackTrace); - return []; + return []; } } Future _goThroughHtlcBlocks(List blocks) async { - for (final block in blocks) { + for (final AccountBlock block in blocks) { await _extractSwapDataFromBlock(block); await htlcSwapsService!.storeLastCheckedHtlcBlockHeight(block.height); } @@ -128,15 +128,15 @@ class HtlcSwapsHandler { return; } - final pairedBlock = htlcBlock.pairedAccountBlock!; - final blockData = AccountBlockUtils.getDecodedBlockData( - Definitions.htlc, pairedBlock.data); + final AccountBlock pairedBlock = htlcBlock.pairedAccountBlock!; + final BlockData? blockData = AccountBlockUtils.getDecodedBlockData( + Definitions.htlc, pairedBlock.data,); if (blockData == null) { return; } - final swap = _tryGetSwapFromBlockData(blockData); + final HtlcSwap? swap = _tryGetSwapFromBlockData(blockData); if (swap == null) { return; } @@ -221,7 +221,7 @@ class HtlcSwapsHandler { } if (data.params.containsKey('hashLock') && swap == null) { swap = htlcSwapsService!.getSwapByHashLock( - Hash.fromBytes(data.params['hashLock']).toString()); + Hash.fromBytes(data.params['hashLock']).toString(),); } return swap; } @@ -253,10 +253,10 @@ class HtlcSwapsHandler { } Future _checkForExpiredSwaps() async { - final swaps = htlcSwapsService! - .getSwapsByState([P2pSwapState.pending, P2pSwapState.active]); - final now = DateTimeUtils.unixTimeNow; - for (final swap in swaps) { + final List swaps = htlcSwapsService! + .getSwapsByState([P2pSwapState.pending, P2pSwapState.active]); + final int now = DateTimeUtils.unixTimeNow; + for (final HtlcSwap swap in swaps) { if (swap.initialHtlcExpirationTime < now || (swap.counterHtlcExpirationTime != null && swap.counterHtlcExpirationTime! - @@ -273,9 +273,9 @@ class HtlcSwapsHandler { // since the counterparty may have published the preimage at the last moment // before the HTLC would have expired. In this situation the swap's state // may have already been changed to reclaimable. - final swaps = htlcSwapsService! - .getSwapsByState([P2pSwapState.active, P2pSwapState.reclaimable]); - for (final swap in swaps) { + final List swaps = htlcSwapsService! + .getSwapsByState([P2pSwapState.active, P2pSwapState.reclaimable]); + for (final HtlcSwap swap in swaps) { if (swap.direction == P2pSwapDirection.incoming && swap.preimage != null) { sl().addHash(Hash.parse(swap.initialHtlcId)); @@ -286,7 +286,7 @@ class HtlcSwapsHandler { int? _getOldestSwapStartTime(List swaps) { return swaps.isNotEmpty ? swaps - .reduce((e1, e2) => e1.startTime > e2.startTime ? e1 : e2) + .reduce((HtlcSwap e1, HtlcSwap e2) => e1.startTime > e2.startTime ? e1 : e2) .startTime : null; } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 00000000..d933fe67 --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,29 @@ +{ + "activePillars": "Active Pillars", + "activeSentinels": "Active Sentinels", + "balance": "Balance", + "currentAmounts": "This card displays the current {kZnnCoinSymbol} and {kQsrCoinSymbol} amounts for the selected address", + "delegationStats": "Delegation Stats", + "delegationStatsDescription": "This card displays the amount of {kZnnCoinSymbol} and the name of the Pillar that you delegated to", + "dualCoinStats": "Dual Coin Stats", + "dualCoinStatsDescription": "This card displays the circulating {kZnnCoinSymbol} and {kQsrCoinSymbol} supply from the network", + "password": "Password", + "pillars": "Pillars", + "pillarsDescription": "This card displays the number of active Pillars in the network", + "realtimeStats": "Realtime Stats", + "realtimeStatsDescription": "This card displays the number of {kZnnCoinSymbol} and {kQsrCoinSymbol} transactions. For example, a delegation is considered a {kZnnCoinSymbol} transaction from the network's perspective. Every interaction with the network embedded contracts is internally considered a transaction", + "send": "Send", + "sentinels": "Sentinels", + "sentinelsDescription": "This card displays the number of active Sentinels in the network", + "stakingStats": "Staking Stats", + "stakingStatsDescription": "This card displays the number of staking entries and the total {kZnnCoinSymbol} that you are currently staking", + "receive": "Receive", + "transactions": "Transactions", + "transactionsDescription": "This card displays the total number of transactions settled in the last hour across the network", + "transactionsLastHour": "transactions in the last hour", + "transfer": "Transfer", + "transferDescription": "Redirects you to the Transfer tab where you can manage sending and receiving funds", + "waitingForDataFetching": "Waiting for data fetching", + "quasarTransactions": "{quasar} transactions", + "zenonTransactions": "{zenon} transactions" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 3c25f53d..414ec7a5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,28 +2,33 @@ import 'dart:async'; import 'dart:io'; import 'dart:isolate'; -import 'package:flutter/foundation.dart' show kDebugMode; +import 'package:flutter/foundation.dart' show kDebugMode, kIsWeb; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:layout/layout.dart'; import 'package:local_notifier/local_notifier.dart'; import 'package:logging/logging.dart'; +import 'package:nested/nested.dart'; import 'package:overlay_support/overlay_support.dart'; import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:retry/retry.dart'; import 'package:tray_manager/tray_manager.dart'; import 'package:window_manager/window_manager.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/auto_unlock_htlc_worker.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/handlers/htlc_swaps_handler.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/chains/i_chain.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/chains/nom_service.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/wallet_connect_pairings_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/wallet_connect_sessions_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/handlers/htlc_swaps_handler.dart'; import 'package:zenon_syrius_wallet_flutter/model/model.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/screens/screens.dart'; import 'package:zenon_syrius_wallet_flutter/services/htlc_swaps_service.dart'; import 'package:zenon_syrius_wallet_flutter/services/i_web3wallet_service.dart'; @@ -39,26 +44,34 @@ SharedPrefsService? sharedPrefsService; HtlcSwapsService? htlcSwapsService; IWeb3WalletService? web3WalletService; -final sl = GetIt.instance; +final GetIt sl = GetIt.instance; -final globalNavigatorKey = GlobalKey(); +final GlobalKey globalNavigatorKey = GlobalKey(); main() async { WidgetsFlutterBinding.ensureInitialized(); - + if (Platform.isWindows) { + registerProtocolHandler(kDeepLinkingUrlScheme); + } + // Init hydrated bloc storage + HydratedBloc.storage = await HydratedStorage.build( + storageDirectory: kIsWeb + ? HydratedStorage.webStorageDirectory + : await getApplicationDocumentsDirectory(), + ); Provider.debugCheckInvalidValueType = null; ensureDirectoriesExist(); - Hive.init(znnDefaultPaths.cache.path.toString()); + Hive.init(znnDefaultPaths.cache.path); // Setup logger - Directory syriusLogDir = + final Directory syriusLogDir = Directory(path.join(znnDefaultCacheDirectory.path, 'log')); if (!syriusLogDir.existsSync()) { syriusLogDir.createSync(recursive: true); } - final logFile = File( - '${syriusLogDir.path}${path.separator}syrius-${DateTime.now().millisecondsSinceEpoch}.log'); + final File logFile = File( + '${syriusLogDir.path}${path.separator}syrius-${DateTime.now().millisecondsSinceEpoch}.log',); Logger.root.level = Level.ALL; Logger.root.onRecord.listen((LogRecord record) { if (kDebugMode) { @@ -84,14 +97,12 @@ main() async { setup(); retry(() => web3WalletService!.init(), - retryIf: (e) => e is SocketException || e is TimeoutException, - maxAttempts: 0x7FFFFFFFFFFFFFFF); + retryIf: (Exception e) => e is SocketException || e is TimeoutException, + maxAttempts: 0x7FFFFFFFFFFFFFFF,); // Setup local_notifier await localNotifier.setup( appName: 's y r i u s', - // The parameter shortcutPolicy only works on Windows - shortcutPolicy: ShortcutPolicy.requireCreate, ); // Setup tray manager @@ -118,8 +129,8 @@ main() async { await windowManager.show(); if (sharedPrefsService != null) { - double? windowSizeWidth = sharedPrefsService!.get(kWindowSizeWidthKey); - double? windowSizeHeight = sharedPrefsService!.get(kWindowSizeHeightKey); + final double? windowSizeWidth = sharedPrefsService!.get(kWindowSizeWidthKey); + final double? windowSizeHeight = sharedPrefsService!.get(kWindowSizeHeightKey); if (windowSizeWidth != null && windowSizeWidth >= 1200 && windowSizeHeight != null && @@ -138,7 +149,7 @@ main() async { .setPosition(Offset(windowPositionX, windowPositionY)); } - bool? windowMaximized = sharedPrefsService!.get(kWindowMaximizedKey); + final bool? windowMaximized = sharedPrefsService!.get(kWindowMaximizedKey); if (windowMaximized == true) { await windowManager.maximize(); } @@ -159,7 +170,7 @@ Future _setupTrayManager() async { if (Platform.isMacOS) { await trayManager.setToolTip('s y r i u s'); } - List items = [ + final List items = [ MenuItem( key: 'show_wallet', label: 'Show wallet', @@ -179,11 +190,11 @@ Future _setupTrayManager() async { Future _loadDefaultCommunityNodes() async { try { - var nodes = await loadJsonFromAssets('assets/community-nodes.json') + final List nodes = await loadJsonFromAssets('assets/community-nodes.json') as List; kDefaultCommunityNodes = nodes .map((node) => node.toString()) - .where((node) => InputValidators.node(node) == null) + .where((String node) => InputValidators.node(node) == null) .toList(); } catch (e, stackTrace) { Logger('main') @@ -195,7 +206,7 @@ void setup() { sl.registerSingleton(Zenon()); zenon = sl(); sl.registerLazySingletonAsync( - (() => SharedPrefsService.getInstance().then((value) => value!))); + () => SharedPrefsService.getInstance().then((SharedPrefsService? value) => value!),); sl.registerSingleton(HtlcSwapsService.getInstance()); // Initialize WalletConnect service @@ -207,20 +218,20 @@ void setup() { sl.registerSingleton(AutoReceiveTxWorker.getInstance()); sl.registerSingleton( - AutoUnlockHtlcWorker.getInstance()); + AutoUnlockHtlcWorker.getInstance(),); sl.registerSingleton(HtlcSwapsHandler.getInstance()); sl.registerSingleton(ReceivePort(), - instanceName: 'embeddedStoppedPort'); + instanceName: 'embeddedStoppedPort',); sl.registerSingleton( sl(instanceName: 'embeddedStoppedPort').asBroadcastStream(), - instanceName: 'embeddedStoppedStream'); + instanceName: 'embeddedStoppedStream',); sl.registerSingleton(PlasmaStatsBloc()); sl.registerSingleton(BalanceBloc()); sl.registerSingleton( - TransferWidgetsBalanceBloc()); + TransferWidgetsBalanceBloc(),); sl.registerSingleton(NotificationsBloc()); sl.registerSingleton(AcceleratorBalanceBloc()); sl.registerSingleton(PowGeneratingStatusBloc()); @@ -233,7 +244,7 @@ void setup() { } class MyApp extends StatefulWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); @override State createState() { @@ -261,7 +272,7 @@ class _MyAppState extends State with WindowListener, TrayListener { @override Widget build(BuildContext context) { return MultiProvider( - providers: [ + providers: [ ChangeNotifierProvider( create: (_) => SelectedAddressNotifier(), ), @@ -279,19 +290,19 @@ class _MyAppState extends State with WindowListener, TrayListener { ), ChangeNotifierProvider>>( create: (_) => ValueNotifier>( - [], + [], ), ), Provider( create: (_) => LockBloc(), - builder: (context, child) { + builder: (BuildContext context, Widget? child) { return Consumer( - builder: (_, appThemeNotifier, __) { - LockBloc lockBloc = + builder: (_, AppThemeNotifier appThemeNotifier, __) { + final LockBloc lockBloc = Provider.of(context, listen: false); return OverlaySupport( child: Listener( - onPointerSignal: (event) { + onPointerSignal: (PointerSignalEvent event) { if (event is PointerScrollEvent) { lockBloc.addEvent(LockEvent.resetTimer); } @@ -308,9 +319,9 @@ class _MyAppState extends State with WindowListener, TrayListener { child: MouseRegion( onEnter: (_) => lockBloc.addEvent(LockEvent.resetTimer), onExit: (_) => lockBloc.addEvent(LockEvent.resetTimer), - child: RawKeyboardListener( + child: KeyboardListener( focusNode: FocusNode(), - onKey: (RawKeyEvent event) { + onKeyEvent: (KeyEvent event) { lockBloc.addEvent(LockEvent.resetTimer); }, child: Layout( @@ -323,22 +334,24 @@ class _MyAppState extends State with WindowListener, TrayListener { themeMode: appThemeNotifier.currentThemeMode, initialRoute: SplashScreen.route, scrollBehavior: RemoveOverscrollEffect(), - routes: { - AccessWalletScreen.route: (context) => + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + routes: { + AccessWalletScreen.route: (BuildContext context) => const AccessWalletScreen(), - SplashScreen.route: (context) => + SplashScreen.route: (BuildContext context) => const SplashScreen(), - MainAppContainer.route: (context) => + MainAppContainer.route: (BuildContext context) => const MainAppContainer(), NodeManagementScreen.route: (_) => const NodeManagementScreen(), }, - onGenerateRoute: (settings) { + onGenerateRoute: (RouteSettings settings) { if (settings.name == SyriusErrorWidget.route) { - final args = settings.arguments + final CustomSyriusErrorWidgetArguments args = settings.arguments! as CustomSyriusErrorWidgetArguments; return MaterialPageRoute( - builder: (context) => + builder: (BuildContext context) => SyriusErrorWidget(args.errorText), ); } @@ -359,15 +372,15 @@ class _MyAppState extends State with WindowListener, TrayListener { } @override - void onWindowClose() async { - bool windowMaximized = await windowManager.isMaximized(); + Future onWindowClose() async { + final bool windowMaximized = await windowManager.isMaximized(); await sharedPrefsService!.put( kWindowMaximizedKey, windowMaximized, ); if (windowMaximized != true) { - Size windowSize = await windowManager.getSize(); + final Size windowSize = await windowManager.getSize(); await sharedPrefsService!.put( kWindowSizeWidthKey, windowSize.width, @@ -377,7 +390,7 @@ class _MyAppState extends State with WindowListener, TrayListener { windowSize.height, ); - Offset windowPosition = await windowManager.getPosition(); + final Offset windowPosition = await windowManager.getPosition(); await sharedPrefsService!.put( kWindowPositionXKey, windowPosition.dx, @@ -410,19 +423,16 @@ class _MyAppState extends State with WindowListener, TrayListener { void onTrayIconRightMouseUp() {} @override - void onTrayMenuItemClick(MenuItem menuItem) async { + Future onTrayMenuItemClick(MenuItem menuItem) async { switch (menuItem.key) { case 'show_wallet': windowManager.show(); - break; case 'hide_wallet': if (!await windowManager.isMinimized()) { windowManager.minimize(); } - break; case 'exit': windowManager.destroy(); - break; default: break; } diff --git a/lib/main_dev.dart b/lib/main_dev.dart new file mode 100644 index 00000000..f4413980 --- /dev/null +++ b/lib/main_dev.dart @@ -0,0 +1,441 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; + +import 'package:flutter/foundation.dart' show kDebugMode, kIsWeb; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:hive/hive.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:layout/layout.dart'; +import 'package:local_notifier/local_notifier.dart'; +import 'package:logging/logging.dart'; +import 'package:nested/nested.dart'; +import 'package:overlay_support/overlay_support.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:retry/retry.dart'; +import 'package:tray_manager/tray_manager.dart'; +import 'package:window_manager/window_manager.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/auto_unlock_htlc_worker.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/chains/i_chain.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/chains/nom_service.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/wallet_connect_pairings_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/wallet_connect/wallet_connect_sessions_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/handlers/htlc_swaps_handler.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/model/model.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/screens/screens.dart'; +import 'package:zenon_syrius_wallet_flutter/services/htlc_swaps_service.dart'; +import 'package:zenon_syrius_wallet_flutter/services/i_web3wallet_service.dart'; +import 'package:zenon_syrius_wallet_flutter/services/shared_prefs_service.dart'; +import 'package:zenon_syrius_wallet_flutter/services/web3wallet_service.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/functions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +const String p = String.fromEnvironment('PASSWORD'); + +main() async { + WidgetsFlutterBinding.ensureInitialized(); + if (Platform.isWindows) { + registerProtocolHandler(kDeepLinkingUrlScheme); + } + + // Init hydrated bloc storage + HydratedBloc.storage = await HydratedStorage.build( + storageDirectory: kIsWeb + ? HydratedStorage.webStorageDirectory + : await getApplicationDocumentsDirectory(), + ); + Provider.debugCheckInvalidValueType = null; + + ensureDirectoriesExist(); + Hive.init(znnDefaultPaths.cache.path); + + // Setup logger + final Directory syriusLogDir = + Directory(path.join(znnDefaultCacheDirectory.path, 'log')); + if (!syriusLogDir.existsSync()) { + syriusLogDir.createSync(recursive: true); + } + final File logFile = File( + '${syriusLogDir.path}${path.separator}syrius-${DateTime.now().millisecondsSinceEpoch}.log',); + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((LogRecord record) { + if (kDebugMode) { + print( + '${record.level.name} ${record.loggerName} ${record.message} ${record.time}: ' + '${record.error} ${record.stackTrace}\n'); + } + logFile.writeAsString( + '${record.level.name} ${record.loggerName} ${record.message} ${record.time}: ' + '${record.error} ${record.stackTrace}\n', + mode: FileMode.append, + flush: true, + ); + }); + + windowManager.ensureInitialized(); + await windowManager.setPreventClose(true); + + web3WalletService = Web3WalletService(); + web3WalletService!.create(); + + // Setup services + setup(); + + retry(() => web3WalletService!.init(), + retryIf: (Exception e) => e is SocketException || e is TimeoutException, + maxAttempts: 0x7FFFFFFFFFFFFFFF,); + + // Setup local_notifier + await localNotifier.setup( + appName: 's y r i u s', + ); + + // Setup tray manager + await _setupTrayManager(); + + // Load default community nodes from assets + await _loadDefaultCommunityNodes(); + + // Register Hive adapters + Hive.registerAdapter(NotificationTypeAdapter()); + Hive.registerAdapter(WalletNotificationAdapter()); + + if (sharedPrefsService == null) { + sharedPrefsService = await sl.getAsync(); + } else { + await sharedPrefsService!.checkIfBoxIsOpen(); + } + + htlcSwapsService ??= sl.get(); + + windowManager.waitUntilReadyToShow().then((_) async { + await windowManager.setTitle('s y r i u s'); + await windowManager.setMinimumSize(const Size(1200, 600)); + await windowManager.show(); + + if (sharedPrefsService != null) { + final double? windowSizeWidth = sharedPrefsService!.get(kWindowSizeWidthKey); + final double? windowSizeHeight = sharedPrefsService!.get(kWindowSizeHeightKey); + if (windowSizeWidth != null && + windowSizeWidth >= 1200 && + windowSizeHeight != null && + windowSizeHeight >= 600) { + await windowManager.setSize(Size(windowSizeWidth, windowSizeHeight)); + } else { + await windowManager.setSize(const Size(1200, 600)); + } + + double? windowPositionX = sharedPrefsService!.get(kWindowPositionXKey); + double? windowPositionY = sharedPrefsService!.get(kWindowPositionYKey); + if (windowPositionX != null && windowPositionY != null) { + windowPositionX = windowPositionX >= 0 ? windowPositionX : 100; + windowPositionY = windowPositionY >= 0 ? windowPositionY : 100; + await windowManager + .setPosition(Offset(windowPositionX, windowPositionY)); + } + + final bool? windowMaximized = sharedPrefsService!.get(kWindowMaximizedKey); + if (windowMaximized == true) { + await windowManager.maximize(); + } + } + }); + + runApp( + const MyApp(), + ); +} + +Future _setupTrayManager() async { + await trayManager.setIcon( + Platform.isWindows + ? 'assets/images/tray_app_icon.ico' + : 'assets/images/tray_app_icon.png', + ); + if (Platform.isMacOS) { + await trayManager.setToolTip('s y r i u s'); + } + final List items = [ + MenuItem( + key: 'show_wallet', + label: 'Show wallet', + ), + MenuItem( + key: 'hide_wallet', + label: 'Hide wallet', + ), + MenuItem.separator(), + MenuItem( + key: 'exit', + label: 'Exit wallet', + ), + ]; + await trayManager.setContextMenu(Menu(items: items)); +} + +Future _loadDefaultCommunityNodes() async { + try { + final List nodes = await loadJsonFromAssets('assets/community-nodes.json') + as List; + kDefaultCommunityNodes = nodes + .map((node) => node.toString()) + .where((String node) => InputValidators.node(node) == null) + .toList(); + } catch (e, stackTrace) { + Logger('main') + .log(Level.WARNING, '_loadDefaultCommunityNodes', e, stackTrace); + } +} + +void setup() { + sl.registerSingleton(Zenon()); + zenon = sl(); + sl.registerLazySingletonAsync( + () => SharedPrefsService.getInstance().then((SharedPrefsService? value) => value!),); + sl.registerSingleton(HtlcSwapsService.getInstance()); + + // Initialize WalletConnect service + sl.registerSingleton(web3WalletService!); + sl.registerSingleton( + NoMService(reference: NoMChainId.mainnet), + instanceName: NoMChainId.mainnet.chain(), + ); + + sl.registerSingleton(AutoReceiveTxWorker.getInstance()); + sl.registerSingleton( + AutoUnlockHtlcWorker.getInstance(),); + + sl.registerSingleton(HtlcSwapsHandler.getInstance()); + + sl.registerSingleton(ReceivePort(), + instanceName: 'embeddedStoppedPort',); + sl.registerSingleton( + sl(instanceName: 'embeddedStoppedPort').asBroadcastStream(), + instanceName: 'embeddedStoppedStream',); + + sl.registerSingleton(PlasmaStatsBloc()); + sl.registerSingleton(BalanceBloc()); + sl.registerSingleton( + TransferWidgetsBalanceBloc(),); + sl.registerSingleton(NotificationsBloc()); + sl.registerSingleton(AcceleratorBalanceBloc()); + sl.registerSingleton(PowGeneratingStatusBloc()); + sl.registerSingleton( + WalletConnectPairingsBloc(), + ); + sl.registerSingleton( + WalletConnectSessionsBloc(), + ); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() { + return _MyAppState(); + } +} + +class _MyAppState extends State with WindowListener, TrayListener { + @override + void initState() { + windowManager.addListener(this); + trayManager.addListener(this); + initPlatformState(); + super.initState(); + } + + // Platform messages are asynchronous, so we initialize in an async method + Future initPlatformState() async { + kLocalIpAddress = + await NetworkUtils.getLocalIpAddress(InternetAddressType.IPv4); + + if (!mounted) return; + } + + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => SelectedAddressNotifier(), + ), + ChangeNotifierProvider( + create: (_) => PlasmaBeneficiaryAddressNotifier(), + ), + ChangeNotifierProvider( + create: (_) => PlasmaGeneratedNotifier(), + ), + ChangeNotifierProvider( + create: (_) => TextScalingNotifier(), + ), + ChangeNotifierProvider( + create: (_) => AppThemeNotifier(), + ), + ChangeNotifierProvider>>( + create: (_) => ValueNotifier>( + [], + ), + ), + Provider( + create: (_) => LockBloc(), + builder: (BuildContext context, Widget? child) { + return Consumer( + builder: (_, AppThemeNotifier appThemeNotifier, __) { + final LockBloc lockBloc = + Provider.of(context, listen: false); + return OverlaySupport( + child: Listener( + onPointerSignal: (PointerSignalEvent event) { + if (event is PointerScrollEvent) { + lockBloc.addEvent(LockEvent.resetTimer); + } + }, + onPointerCancel: (_) => + lockBloc.addEvent(LockEvent.resetTimer), + onPointerDown: (_) => + lockBloc.addEvent(LockEvent.resetTimer), + onPointerHover: (_) => + lockBloc.addEvent(LockEvent.resetTimer), + onPointerMove: (_) => + lockBloc.addEvent(LockEvent.resetTimer), + onPointerUp: (_) => lockBloc.addEvent(LockEvent.resetTimer), + child: MouseRegion( + onEnter: (_) => lockBloc.addEvent(LockEvent.resetTimer), + onExit: (_) => lockBloc.addEvent(LockEvent.resetTimer), + child: KeyboardListener( + focusNode: FocusNode(), + onKeyEvent: (KeyEvent event) { + lockBloc.addEvent(LockEvent.resetTimer); + }, + child: Layout( + child: MaterialApp( + title: 's y r i u s', + navigatorKey: globalNavigatorKey, + debugShowCheckedModeBanner: false, + theme: AppTheme.lightTheme, + darkTheme: AppTheme.darkTheme, + themeMode: appThemeNotifier.currentThemeMode, + initialRoute: DevelopmentInitializationScreen.route, + scrollBehavior: RemoveOverscrollEffect(), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + routes: { + AccessWalletScreen.route: (BuildContext context) => + const AccessWalletScreen(), + DevelopmentInitializationScreen.route: (BuildContext context) => + const DevelopmentInitializationScreen(), + MainAppContainer.route: (BuildContext context) => + const MainAppContainer(), + NodeManagementScreen.route: (_) => + const NodeManagementScreen(), + }, + onGenerateRoute: (RouteSettings settings) { + if (settings.name == SyriusErrorWidget.route) { + final CustomSyriusErrorWidgetArguments args = settings.arguments! + as CustomSyriusErrorWidgetArguments; + return MaterialPageRoute( + builder: (BuildContext context) => + SyriusErrorWidget(args.errorText), + ); + } + return null; + }, + ), + ), + ), + ), + ), + ); + }, + ); + }, + ), + ], + ); + } + + @override + Future onWindowClose() async { + final bool windowMaximized = await windowManager.isMaximized(); + await sharedPrefsService!.put( + kWindowMaximizedKey, + windowMaximized, + ); + + if (windowMaximized != true) { + final Size windowSize = await windowManager.getSize(); + await sharedPrefsService!.put( + kWindowSizeWidthKey, + windowSize.width, + ); + await sharedPrefsService!.put( + kWindowSizeHeightKey, + windowSize.height, + ); + + final Offset windowPosition = await windowManager.getPosition(); + await sharedPrefsService!.put( + kWindowPositionXKey, + windowPosition.dx, + ); + await sharedPrefsService!.put( + kWindowPositionYKey, + windowPosition.dy, + ); + } + + sl().wsClient.stop(); + Future.delayed(const Duration(seconds: 60)).then((value) => exit(0)); + await NodeUtils.closeEmbeddedNode(); + await sl.reset(); + super.onWindowClose(); + deactivate(); + dispose(); + exit(0); + } + + @override + void onTrayIconMouseDown() { + trayManager.popUpContextMenu(); + } + + @override + void onTrayIconRightMouseDown() {} + + @override + void onTrayIconRightMouseUp() {} + + @override + Future onTrayMenuItemClick(MenuItem menuItem) async { + switch (menuItem.key) { + case 'show_wallet': + windowManager.show(); + case 'hide_wallet': + if (!await windowManager.isMinimized()) { + windowManager.minimize(); + } + case 'exit': + windowManager.destroy(); + default: + break; + } + } + + @override + void dispose() { + windowManager.removeListener(this); + trayManager.removeListener(this); + super.dispose(); + } +} diff --git a/lib/model/account_chain_stats.dart b/lib/model/account_chain_stats.dart index 68c28d73..06cdc892 100644 --- a/lib/model/account_chain_stats.dart +++ b/lib/model/account_chain_stats.dart @@ -1,13 +1,13 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AccountChainStats { - final Hash firstHash; - final int blockCount; - final Map blockTypeNumOfBlocksMap; AccountChainStats({ required this.firstHash, required this.blockCount, required this.blockTypeNumOfBlocksMap, }); + final Hash firstHash; + final int blockCount; + final Map blockTypeNumOfBlocksMap; } diff --git a/lib/model/basic_dropdown_item.dart b/lib/model/basic_dropdown_item.dart index c8bf5aa4..a57a49ad 100644 --- a/lib/model/basic_dropdown_item.dart +++ b/lib/model/basic_dropdown_item.dart @@ -1,9 +1,9 @@ class BasicDropdownItem { - final String label; - final T value; BasicDropdownItem({ required this.label, required this.value, }); + final String label; + final T value; } diff --git a/lib/model/block_data.dart b/lib/model/block_data.dart index d8eeae0f..d6dfeb3c 100644 --- a/lib/model/block_data.dart +++ b/lib/model/block_data.dart @@ -1,9 +1,9 @@ class BlockData { - final String function; - final Map params; BlockData({ required this.function, required this.params, }); + final String function; + final Map params; } diff --git a/lib/model/database/wallet_notification.dart b/lib/model/database/wallet_notification.dart index 18814228..7dd36ced 100644 --- a/lib/model/database/wallet_notification.dart +++ b/lib/model/database/wallet_notification.dart @@ -9,6 +9,14 @@ part 'wallet_notification.g.dart'; @HiveType(typeId: kWalletNotificationHiveTypeId) class WalletNotification extends HiveObject { + + WalletNotification({ + required this.title, + required this.timestamp, + required this.details, + required this.type, + this.id, + }); @HiveField(0) final String? title; @@ -24,14 +32,6 @@ class WalletNotification extends HiveObject { @HiveField(4) final int? id; - WalletNotification({ - required this.title, - required this.timestamp, - required this.details, - required this.type, - this.id, - }); - Color getColor() { switch (type) { case NotificationType.error: @@ -47,11 +47,11 @@ class WalletNotification extends HiveObject { switch (type) { case NotificationType.stakingDeactivated: return _getCircledIcon(MaterialCommunityIcons.alert_circle_outline, - iconColor: Colors.grey); + iconColor: Colors.grey,); case NotificationType.error: return const Icon( MaterialCommunityIcons.alert_circle_outline, - size: 20.0, + size: 20, color: AppColors.errorColor, ); case NotificationType.paymentSent: @@ -80,7 +80,7 @@ class WalletNotification extends HiveObject { return _getCircledIcon(Icons.delete_forever); case NotificationType.confirm: return _getCircledIcon(Icons.remove_red_eye, - iconColor: AppColors.alertNotification); + iconColor: AppColors.alertNotification,); default: return _getCircledIcon(MaterialCommunityIcons.arrow_top_right); } @@ -91,20 +91,19 @@ class WalletNotification extends HiveObject { Color iconColor = AppColors.znnColor, }) { return Container( - padding: const EdgeInsets.all(2.0), + padding: const EdgeInsets.all(2), decoration: BoxDecoration( border: Border.all( - width: 1.0, color: iconColor, ), borderRadius: BorderRadius.circular( - 50.0, + 50, ), ), child: Icon( iconData, color: iconColor, - size: 10.0, + size: 10, ), ); } diff --git a/lib/model/general_stats.dart b/lib/model/general_stats.dart index e0933aeb..119df6a6 100644 --- a/lib/model/general_stats.dart +++ b/lib/model/general_stats.dart @@ -1,22 +1,19 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class GeneralStats { - final Momentum frontierMomentum; - final ProcessInfo processInfo; - final NetworkInfo networkInfo; - final OsInfo osInfo; GeneralStats( {required this.frontierMomentum, required this.processInfo, required this.networkInfo, - required this.osInfo}); + required this.osInfo,}); + final Momentum frontierMomentum; + final ProcessInfo processInfo; + final NetworkInfo networkInfo; + final OsInfo osInfo; } class LatestMomentum { - final String hash; - final int? height; - final int? time; LatestMomentum({ required this.hash, @@ -29,4 +26,7 @@ class LatestMomentum { height: json['Height'], time: json['Time'], ); + final String hash; + final int? height; + final int? time; } diff --git a/lib/model/model.dart b/lib/model/model.dart index ce36f258..f0a01d16 100644 --- a/lib/model/model.dart +++ b/lib/model/model.dart @@ -5,8 +5,8 @@ export 'database/wallet_notification.dart'; export 'general_stats.dart'; export 'navigation_arguments.dart'; export 'new_token_data.dart'; +export 'p2p_swap/htlc_swap.dart'; +export 'p2p_swap/p2p_swap.dart'; export 'pillars_qsr_info.dart'; export 'plasma_info_wrapper.dart'; -export 'p2p_swap/p2p_swap.dart'; -export 'p2p_swap/htlc_swap.dart'; export 'sentinels_qsr_info.dart'; diff --git a/lib/model/navigation_arguments.dart b/lib/model/navigation_arguments.dart index 17c87d8b..dc3e1cdd 100644 --- a/lib/model/navigation_arguments.dart +++ b/lib/model/navigation_arguments.dart @@ -1,5 +1,5 @@ class CustomSyriusErrorWidgetArguments { - final String errorText; CustomSyriusErrorWidgetArguments(this.errorText); + final String errorText; } diff --git a/lib/model/p2p_swap/htlc_swap.dart b/lib/model/p2p_swap/htlc_swap.dart index 941198a5..3f05326c 100644 --- a/lib/model/p2p_swap/htlc_swap.dart +++ b/lib/model/p2p_swap/htlc_swap.dart @@ -1,63 +1,36 @@ import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/p2p_swap.dart'; class HtlcSwap extends P2pSwap { - final String hashLock; - final String initialHtlcId; - final int initialHtlcExpirationTime; - final int hashType; - String? counterHtlcId; - int? counterHtlcExpirationTime; - String? preimage; HtlcSwap({ - required id, - required chainId, - required type, - required direction, - required selfAddress, - required counterpartyAddress, - required fromAmount, - required fromTokenStandard, - required fromSymbol, - required fromDecimals, - required fromChain, - required toChain, - required startTime, - required state, - toAmount, - toTokenStandard, - toSymbol, - toDecimals, required this.hashLock, required this.initialHtlcId, required this.initialHtlcExpirationTime, required this.hashType, + required super.id, + required super.chainId, + required super.type, + required super.direction, + required super.selfAddress, + required super.counterpartyAddress, + required super.fromAmount, + required super.fromTokenStandard, + required super.fromSymbol, + required super.fromDecimals, + required super.fromChain, + required super.toChain, + required super.startTime, + required super.state, + super.toAmount, + super.toDecimals, + super.toSymbol, + super.toTokenStandard, this.counterHtlcId, this.counterHtlcExpirationTime, this.preimage, - }) : super( - id: id, - chainId: chainId, - type: type, - mode: P2pSwapMode.htlc, - direction: direction, - selfAddress: selfAddress, - counterpartyAddress: counterpartyAddress, - fromAmount: fromAmount, - fromTokenStandard: fromTokenStandard, - fromSymbol: fromSymbol, - fromDecimals: fromDecimals, - fromChain: fromChain, - toChain: toChain, - startTime: startTime, - state: state, - toAmount: toAmount, - toTokenStandard: toTokenStandard, - toSymbol: toSymbol, - toDecimals: toDecimals, - ); + }) : super(mode: P2pSwapMode.htlc); - HtlcSwap.fromJson(Map json) + HtlcSwap.fromJson(super.json) : hashLock = json['hashLock'], initialHtlcId = json['initialHtlcId'], initialHtlcExpirationTime = json['initialHtlcExpirationTime'], @@ -65,11 +38,18 @@ class HtlcSwap extends P2pSwap { counterHtlcId = json['counterHtlcId'], counterHtlcExpirationTime = json['counterHtlcExpirationTime'], preimage = json['preimage'], - super.fromJson(json); + super.fromJson(); + final String hashLock; + final String initialHtlcId; + final int initialHtlcExpirationTime; + final int hashType; + String? counterHtlcId; + int? counterHtlcExpirationTime; + String? preimage; @override Map toJson() { - final data = super.toJson(); + final Map data = super.toJson(); data['hashLock'] = hashLock; data['initialHtlcId'] = initialHtlcId; data['initialHtlcExpirationTime'] = initialHtlcExpirationTime; diff --git a/lib/model/p2p_swap/p2p_swap.dart b/lib/model/p2p_swap/p2p_swap.dart index b06ffd9b..323c4e34 100644 --- a/lib/model/p2p_swap/p2p_swap.dart +++ b/lib/model/p2p_swap/p2p_swap.dart @@ -28,25 +28,6 @@ enum P2pSwapChain { } class P2pSwap { - final String id; - final int chainId; - final P2pSwapType type; - final P2pSwapMode mode; - final P2pSwapDirection direction; - final String selfAddress; - final String counterpartyAddress; - final BigInt fromAmount; - final String fromTokenStandard; - final String fromSymbol; - final int fromDecimals; - final P2pSwapChain fromChain; - final P2pSwapChain toChain; - final int startTime; - P2pSwapState state; - BigInt? toAmount; - String? toTokenStandard; - String? toSymbol; - int? toDecimals; P2pSwap( {required this.id, @@ -67,7 +48,7 @@ class P2pSwap { this.toAmount, this.toTokenStandard, this.toSymbol, - this.toDecimals}); + this.toDecimals,}); P2pSwap.fromJson(Map json) : id = json['id'], @@ -89,8 +70,27 @@ class P2pSwap { toTokenStandard = json['toTokenStandard'], toSymbol = json['toSymbol'], toDecimals = json['toDecimals']; + final String id; + final int chainId; + final P2pSwapType type; + final P2pSwapMode mode; + final P2pSwapDirection direction; + final String selfAddress; + final String counterpartyAddress; + final BigInt fromAmount; + final String fromTokenStandard; + final String fromSymbol; + final int fromDecimals; + final P2pSwapChain fromChain; + final P2pSwapChain toChain; + final int startTime; + P2pSwapState state; + BigInt? toAmount; + String? toTokenStandard; + String? toSymbol; + int? toDecimals; - Map toJson() => { + Map toJson() => { 'id': id, 'chainId': chainId, 'type': type.name, diff --git a/lib/model/pillars_qsr_info.dart b/lib/model/pillars_qsr_info.dart index 4da14a40..556fff9e 100644 --- a/lib/model/pillars_qsr_info.dart +++ b/lib/model/pillars_qsr_info.dart @@ -1,9 +1,9 @@ class PillarsQsrInfo { - final BigInt cost; - final BigInt deposit; PillarsQsrInfo({ required this.cost, required this.deposit, }); + final BigInt cost; + final BigInt deposit; } diff --git a/lib/model/plasma_info_wrapper.dart b/lib/model/plasma_info_wrapper.dart index ee535fa9..3950da39 100644 --- a/lib/model/plasma_info_wrapper.dart +++ b/lib/model/plasma_info_wrapper.dart @@ -1,11 +1,11 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PlasmaInfoWrapper { - final String address; - final PlasmaInfo plasmaInfo; PlasmaInfoWrapper({ required this.address, required this.plasmaInfo, }); + final String address; + final PlasmaInfo plasmaInfo; } diff --git a/lib/model/sentinels_qsr_info.dart b/lib/model/sentinels_qsr_info.dart index 5a627e53..1ad20c37 100644 --- a/lib/model/sentinels_qsr_info.dart +++ b/lib/model/sentinels_qsr_info.dart @@ -1,9 +1,9 @@ class SentinelsQsrInfo { - final BigInt cost; - final BigInt deposit; SentinelsQsrInfo({ required this.cost, required this.deposit, }); + final BigInt cost; + final BigInt deposit; } diff --git a/lib/rearchitecture/features/balance/balance.dart b/lib/rearchitecture/features/balance/balance.dart new file mode 100644 index 00000000..f08482a9 --- /dev/null +++ b/lib/rearchitecture/features/balance/balance.dart @@ -0,0 +1,4 @@ +export 'cubit/balance_cubit.dart'; +export 'exceptions/exceptions.dart'; +export 'view/balance_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/balance/cubit/balance_cubit.dart b/lib/rearchitecture/features/balance/cubit/balance_cubit.dart new file mode 100644 index 00000000..951ec277 --- /dev/null +++ b/lib/rearchitecture/features/balance/cubit/balance_cubit.dart @@ -0,0 +1,50 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'balance_cubit.g.dart'; + +part 'balance_state.dart'; + +/// A cubit that is responsible for managing and fetching the account balance +/// of the provided [address]. + +class BalanceCubit extends TimerCubit { + /// Constructs a BalanceCubit instance. + BalanceCubit({ + required this.address, + required super.zenon, + super.initialState = const BalanceState(), + }); + + /// The address for which the balance will be retrieved + final Address address; + + /// Fetches the balance information for a single address. + /// + /// Returns an [AccountInfo] object containing the balance details for the + /// given address. + /// + /// Throws an [NoBalanceException] if the balance for ZNN and QSR is zero. + @override + Future fetch() async { + final AccountInfo response = await zenon.ledger.getAccountInfoByAddress( + address, + ); + if (response.blockCount! > 0 && + (response.znn()! > BigInt.zero || response.qsr()! > BigInt.zero)) { + return response; + } else { + throw NoBalanceException(); + } + } + + @override + BalanceState? fromJson(Map json) => BalanceState.fromJson( + json, + ); + + @override + Map? toJson(BalanceState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/balance/cubit/balance_cubit.g.dart b/lib/rearchitecture/features/balance/cubit/balance_cubit.g.dart new file mode 100644 index 00000000..b956e1d7 --- /dev/null +++ b/lib/rearchitecture/features/balance/cubit/balance_cubit.g.dart @@ -0,0 +1,32 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'balance_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BalanceState _$BalanceStateFromJson(Map json) => BalanceState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: json['data'] == null + ? null + : AccountInfo.fromJson(json['data'] as Map), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$BalanceStateToJson(BalanceState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.toJson(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/balance/cubit/balance_state.dart b/lib/rearchitecture/features/balance/cubit/balance_state.dart new file mode 100644 index 00000000..e05a8c13 --- /dev/null +++ b/lib/rearchitecture/features/balance/cubit/balance_state.dart @@ -0,0 +1,48 @@ +part of 'balance_cubit.dart'; + +/// The class used by the [BalanceCubit] to send state updates to the +/// listening widgets. +/// +/// The data hold, when the status is [TimerStatus.success], is of type +/// [AccountInfo]. +@JsonSerializable(explicitToJson: true) +class BalanceState extends TimerState { + /// Constructs a new BalanceState. + /// + /// This state uses the default [status], [data], and [error] from the parent + /// [TimerState] class + const BalanceState({ + super.status, + super.data, + super.error, + }); + + /// {@template instance_from_json} + /// Creates a new instance from a JSON map. + /// {@endtemplate} + factory BalanceState.fromJson(Map json) => + _$BalanceStateFromJson(json); + + /// {@template state_copy_with} + /// Creates a copy of the current state with updated values for [status], + /// [data], or [error], if provided, otherwise retaining the + /// existing values. + /// {@endtemplate} + @override + TimerState copyWith({ + TimerStatus? status, + AccountInfo? data, + SyriusException? error, + }) { + return BalanceState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@template state_to_json} + /// Converts this instance to a JSON map. + /// {@endtemplate} + Map toJson() => _$BalanceStateToJson(this); +} diff --git a/lib/rearchitecture/features/balance/exceptions/exceptions.dart b/lib/rearchitecture/features/balance/exceptions/exceptions.dart new file mode 100644 index 00000000..d49c2b3b --- /dev/null +++ b/lib/rearchitecture/features/balance/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'no_balance_exception.dart'; diff --git a/lib/rearchitecture/features/balance/exceptions/no_balance_exception.dart b/lib/rearchitecture/features/balance/exceptions/no_balance_exception.dart new file mode 100644 index 00000000..033b004a --- /dev/null +++ b/lib/rearchitecture/features/balance/exceptions/no_balance_exception.dart @@ -0,0 +1,34 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; + +part 'no_balance_exception.g.dart'; + +/// A [SyriusException] used when there is no balance available on a specific +/// address +@immutable +@JsonSerializable() +class NoBalanceException extends SyriusException { + /// Creates a [NoBalanceException] instance + NoBalanceException({ + String message = 'Empty balance on the selected address', + }) : super(message); + + /// {@macro instance_from_json} + factory NoBalanceException.fromJson(Map json) => + _$NoBalanceExceptionFromJson(json); + + @override + Map toJson() => + _$NoBalanceExceptionToJson(this)..['runtimeType'] = 'NoBalanceException'; + + @override + bool operator ==(Object other) { + return other is NoBalanceException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/features/balance/exceptions/no_balance_exception.g.dart b/lib/rearchitecture/features/balance/exceptions/no_balance_exception.g.dart new file mode 100644 index 00000000..2513951d --- /dev/null +++ b/lib/rearchitecture/features/balance/exceptions/no_balance_exception.g.dart @@ -0,0 +1,18 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'no_balance_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NoBalanceException _$NoBalanceExceptionFromJson(Map json) => + NoBalanceException( + message: + json['message'] as String? ?? 'Empty balance on the selected address', + ); + +Map _$NoBalanceExceptionToJson(NoBalanceException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/features/balance/view/balance_card.dart b/lib/rearchitecture/features/balance/view/balance_card.dart new file mode 100644 index 00000000..b39e762d --- /dev/null +++ b/lib/rearchitecture/features/balance/view/balance_card.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A [BalanceCard] widget that displays balance information for a user. +/// +/// The widget uses a [BalanceCubit] to fetch and manage account balance data +/// and presents the state in different views based on the current status +/// (e.g., loading, success, failure). +/// +/// Expects a [BalanceCubit] to be provided via a [BlocProvider]. +class BalanceCard extends StatelessWidget { + /// Constructs a [BalanceCard] widget. + const BalanceCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => BalanceCubit( + address: Address.parse(kSelectedAddress!), + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.balance.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, BalanceState state) { + return switch (state.status) { + TimerStatus.initial => const BalanceEmpty(), + TimerStatus.loading => const BalanceLoading(), + TimerStatus.failure => BalanceError( + error: state.error!, + ), + TimerStatus.success => BalancePopulated( + address: kSelectedAddress!, + accountInfo: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_address.dart b/lib/rearchitecture/features/balance/widgets/balance_address.dart new file mode 100644 index 00000000..8909686c --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_address.dart @@ -0,0 +1,86 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; + +/// A stateless widget that takes in a [ValueNotifier] that holds a color +/// which will be used to highlight the prefix and the suffix of the [address] +/// +/// Inside the widget tree there is a [FocusableActionDetector] that knows +/// when the mouse hovers over the [Text] widget that displays the [address] +/// and changes the value of the [edgesColorNotifier] + +class BalanceAddress extends StatelessWidget { + /// Creates a BalanceAddress object. + const BalanceAddress({ + required this.address, + required this.edgesColorNotifier, + super.key, + }); + + /// The address that will be displayed + final String address; + + /// A notifier used to rebuild the widget + final ValueNotifier edgesColorNotifier; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: edgesColorNotifier, + builder: (_, Color? edgesColor, __) { + return FocusableActionDetector( + onShowHoverHighlight: (bool x) { + if (x) { + edgesColorNotifier.value = AppColors.znnColor; + } else { + edgesColorNotifier.value = context.themeData.hintColor; + } + }, + child: Container( + decoration: BoxDecoration( + color: context.themeData.colorScheme.surface, + borderRadius: BorderRadius.circular(15), + ), + padding: const EdgeInsets.symmetric( + vertical: 4, + horizontal: 8, + ), + margin: const EdgeInsets.only( + bottom: 12, + top: 12, + ), + child: AutoSizeText.rich( + TextSpan( + children: [ + TextSpan( + text: address.substring(0, 3), + style: TextStyle(color: edgesColor), + ), + TextSpan( + text: address.substring( + 3, + address.length - 6, + ), + style: TextStyle( + color: context.themeData.hintColor, + ), + ), + TextSpan( + text: address.substring( + address.length - 6, + address.length, + ), + style: TextStyle( + color: edgesColor, + ), + ), + ], + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_chart.dart b/lib/rearchitecture/features/balance/widgets/balance_chart.dart new file mode 100644 index 00000000..1c339de3 --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_chart.dart @@ -0,0 +1,77 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/chart/standard_pie_chart.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A customized [StandardPieChart] that shows the balance in ZNN and QSR hold +/// be the user on a certain address +/// +/// Hovering over the sections of the chart will trigger the balance - in a +/// readable format - to appear in the center of the chart +class BalanceChart extends StatelessWidget { + /// Creates a BalanceChart objects + const BalanceChart({ + required this.accountInfo, + required this.hoveredSectionId, + super.key, + }); + + /// Data needed for the chart + final AccountInfo accountInfo; + + /// Notifier that holds the id of the hovered chart section + final ValueNotifier hoveredSectionId; + + @override + Widget build(BuildContext context) { + return StandardPieChart( + sections: _getChartSection(accountInfo), + onChartSectionTouched: (PieTouchedSection? pieChartSection) { + hoveredSectionId.value = pieChartSection?.touchedSection?.title; + }, + ); + } + + List _getChartSection(AccountInfo accountInfo) { + final List sections = []; + if (accountInfo.znn()! > BigInt.zero) { + sections.add( + _getBalanceChartSection( + accountInfo.findTokenByTokenStandard(kZnnCoin.tokenStandard)!, + accountInfo, + ), + ); + } + if (accountInfo.qsr()! > BigInt.zero) { + sections.add( + _getBalanceChartSection( + accountInfo.findTokenByTokenStandard(kQsrCoin.tokenStandard)!, + accountInfo, + ), + ); + } + + return sections; + } + + PieChartSectionData _getBalanceChartSection( + Token token, + AccountInfo accountInfo, + ) { + final bool isTouched = + token.tokenStandard.toString() == hoveredSectionId.value; + final double opacity = isTouched ? 1.0 : 0.7; + + final double value = accountInfo.getBalance(token.tokenStandard) / + (accountInfo.znn()! + accountInfo.qsr()!); + + return PieChartSectionData( + title: token.tokenStandard.toString(), + showTitle: false, + radius: 7, + color: ColorUtils.getTokenColor(token.tokenStandard).withOpacity(opacity), + value: value, + ); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_chart_legend.dart b/lib/rearchitecture/features/balance/widgets/balance_chart_legend.dart new file mode 100644 index 00000000..427f7b8e --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_chart_legend.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/balance/balance.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// Adds a legend to the [BalanceChart] consisting of widgets with a tooltip +/// than will show the exact balance - including decimals - available in a +/// certain coin (QSR or ZNN) +class BalanceChartLegend extends StatelessWidget { + /// Creates a BalanceChartLegend object. + const BalanceChartLegend({required this.accountInfo, super.key}); + + /// Data used for the legend + final AccountInfo accountInfo; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: _getCoinBalanceInfo( + accountInfo: accountInfo, + coin: kZnnCoin, + context: context, + ), + ), + Expanded( + child: _getCoinBalanceInfo( + accountInfo: accountInfo, + coin: kQsrCoin, + context: context, + ), + ), + ], + ); + } + + FormattedAmountWithTooltip _getCoinBalanceInfo({ + required Token coin, + required AccountInfo accountInfo, + required BuildContext context, + }) { + return FormattedAmountWithTooltip( + amount: accountInfo + .getBalance( + coin.tokenStandard, + ) + .addDecimals(coin.decimals), + tokenSymbol: coin.symbol, + builder: (String amount, String tokenSymbol) => AmountInfoColumn( + context: context, + amount: amount, + tokenSymbol: tokenSymbol, + ), + ); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_empty.dart b/lib/rearchitecture/features/balance/widgets/balance_empty.dart new file mode 100644 index 00000000..d72abdd4 --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_empty.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/balance/balance.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A [BalanceEmpty] widget that displays a simple message indicating that there +/// is no balance data available. +/// +/// This widget is displayed when the [BalanceCubit] is in its initial state, +/// meaning no data has been loaded yet or the balance data is empty. +class BalanceEmpty extends StatelessWidget { + /// Creates a BalanceEmpty objects. + const BalanceEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_error.dart b/lib/rearchitecture/features/balance/widgets/balance_error.dart new file mode 100644 index 00000000..c07ae13f --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_error.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/balance/balance.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A [BalanceError] widget that displays an error message when the balance +/// data fetching fails. +/// +/// This widget is displayed when the [BalanceCubit] encounters an error +/// while trying to load the balance data. +class BalanceError extends StatelessWidget { + /// Creates a BalanceError object. + const BalanceError({required this.error, super.key}); + + /// The object used to display an error message. + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_loading.dart b/lib/rearchitecture/features/balance/widgets/balance_loading.dart new file mode 100644 index 00000000..52baa68c --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_loading.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_widget.dart'; + +/// A widget that displays a loading indicator while the balance data is being +/// fetched. +/// +/// This widget is shown when the [BalanceCubit] sends a [BalanceState] update +/// with a status of [TimerStatus.loading], indicating that the balance +/// data is currently being loaded. +class BalanceLoading extends StatelessWidget { + /// Creates a BalanceLoading object. + const BalanceLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/balance_populated.dart b/lib/rearchitecture/features/balance/widgets/balance_populated.dart new file mode 100644 index 00000000..acffe108 --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/balance_populated.dart @@ -0,0 +1,125 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/balance/balance.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A [BalancePopulated] widget that displays balance data once it has been +/// successfully fetched and populated. +/// +/// This widget is displayed when the [BalanceCubit] is in the +/// [TimerStatus.success] state, and the balance data is available for +/// rendering. +class BalancePopulated extends StatefulWidget { + /// Creates a BalancePopulated object. + const BalancePopulated({ + required this.address, + required this.accountInfo, + super.key, + }); + + /// The balance data that has been successfully fetched. + final AccountInfo accountInfo; + + /// The address for which the [accountInfo] was retrieved. + final String address; + + @override + State createState() => _BalancePopulatedState(); +} + +class _BalancePopulatedState extends State { + final ValueNotifier _touchedSectionId = ValueNotifier(null); + late final ValueNotifier _addressEdgesColor; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _addressEdgesColor = ValueNotifier(context.themeData.hintColor); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + kVerticalGap16, + Expanded( + child: AspectRatio( + aspectRatio: 1, + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Stack( + alignment: Alignment.center, + children: [ + BalanceChart( + accountInfo: widget.accountInfo, + hoveredSectionId: _touchedSectionId, + ), + ValueListenableBuilder( + valueListenable: _touchedSectionId, + builder: (_, String? id, __) { + final Widget center = id != null + ? _getBalance( + accountInfo: widget.accountInfo, + constraints: constraints, + tokenStandard: TokenStandard.parse( + _touchedSectionId.value!, + ), + ) + : const SizedBox.shrink(); + + return center; + }, + ), + ], + ); + }, + ), + ), + ), + BalanceAddress( + address: widget.address, + edgesColorNotifier: _addressEdgesColor, + ), + const Divider(), + Padding( + padding: const EdgeInsets.all(8), + child: BalanceChartLegend(accountInfo: widget.accountInfo), + ), + ], + ); + } + + Widget _getBalance({ + required AccountInfo accountInfo, + required BoxConstraints constraints, + required TokenStandard tokenStandard, + }) { + final String amount = accountInfo + .getBalance( + tokenStandard, + ) + .addDecimals(coinDecimals); + + final String symbol = tokenStandard == kZnnCoin.tokenStandard + ? kZnnCoin.symbol + : kQsrCoin.symbol; + + final double margin = constraints.maxWidth * 0.3; + + final double width = constraints.maxWidth - margin; + + return SizedBox( + width: width, + child: AutoSizeText( + '$amount $symbol', + textAlign: TextAlign.center, + style: context.textTheme.headlineMedium?.copyWith( + color: ColorUtils.getTokenColor(tokenStandard), + fontWeight: FontWeight.bold, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/balance/widgets/widgets.dart b/lib/rearchitecture/features/balance/widgets/widgets.dart new file mode 100644 index 00000000..4d81c39e --- /dev/null +++ b/lib/rearchitecture/features/balance/widgets/widgets.dart @@ -0,0 +1,7 @@ +export 'balance_address.dart'; +export 'balance_chart.dart'; +export 'balance_chart_legend.dart'; +export 'balance_empty.dart'; +export 'balance_error.dart'; +export 'balance_loading.dart'; +export 'balance_populated.dart'; diff --git a/lib/rearchitecture/features/delegation/cubit/delegation_cubit.dart b/lib/rearchitecture/features/delegation/cubit/delegation_cubit.dart new file mode 100644 index 00000000..9c02a572 --- /dev/null +++ b/lib/rearchitecture/features/delegation/cubit/delegation_cubit.dart @@ -0,0 +1,57 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'delegation_cubit.g.dart'; + +part 'delegation_state.dart'; + +/// A cubit that manages the fetching and state of delegation information +/// for a specific account. +class DelegationCubit extends TimerCubit { + /// Constructs a DelegationCubit object, passing the [zenon] client and the + /// initial state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// delegation information. + DelegationCubit({ + required this.address, + required super.zenon, + super.initialState = const DelegationState(), + }); + + /// The address for which the [DelegationInfo] will be fetched + final Address address; + + /// Fetches the delegation information for the account identified by its + /// address. + /// + /// This method retrieves delegation stats + /// It checks if the delegation information is available: + /// - If available, it returns the [DelegationInfo]. + /// - If not available, it throws an exception + @override + Future fetch() async { + final DelegationInfo? delegationInfo = + await zenon.embedded.pillar.getDelegatedPillar( + address, + ); + + // Check if delegation information is available + if (delegationInfo != null) { + return delegationInfo; + } else { + throw NoDelegationStatsException(); + } + } + + @override + DelegationState? fromJson(Map json) => + DelegationState.fromJson( + json, + ); + + @override + Map? toJson(DelegationState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/delegation/cubit/delegation_cubit.g.dart b/lib/rearchitecture/features/delegation/cubit/delegation_cubit.g.dart new file mode 100644 index 00000000..c9bc2a51 --- /dev/null +++ b/lib/rearchitecture/features/delegation/cubit/delegation_cubit.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'delegation_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DelegationState _$DelegationStateFromJson(Map json) => + DelegationState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: json['data'] == null + ? null + : DelegationInfo.fromJson(json['data'] as Map), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$DelegationStateToJson(DelegationState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.toJson(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/delegation/cubit/delegation_state.dart b/lib/rearchitecture/features/delegation/cubit/delegation_state.dart new file mode 100644 index 00000000..8f2c7478 --- /dev/null +++ b/lib/rearchitecture/features/delegation/cubit/delegation_state.dart @@ -0,0 +1,41 @@ +part of 'delegation_cubit.dart'; + +/// The state class for the [DelegationCubit]. +/// +/// It holds a [DelegationInfo] object that represents the retrieved delegation +/// details. + +@JsonSerializable(explicitToJson: true) +class DelegationState extends TimerState { + /// Constructs a new DelegationState object. + /// + /// This state is initialized with default [status], [data], and [error] + /// values from the parent class. + /// It manages delegation information for an account. + const DelegationState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory DelegationState.fromJson(Map json) => + _$DelegationStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState copyWith({ + TimerStatus? status, + DelegationInfo? data, + SyriusException? error, + }) { + return DelegationState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$DelegationStateToJson(this); +} diff --git a/lib/rearchitecture/features/delegation/delegation.dart b/lib/rearchitecture/features/delegation/delegation.dart new file mode 100644 index 00000000..f26173df --- /dev/null +++ b/lib/rearchitecture/features/delegation/delegation.dart @@ -0,0 +1,4 @@ +export 'cubit/delegation_cubit.dart'; +export 'exceptions/exceptions.dart'; +export 'view/delegation_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/delegation/exceptions/exceptions.dart b/lib/rearchitecture/features/delegation/exceptions/exceptions.dart new file mode 100644 index 00000000..7cb12e34 --- /dev/null +++ b/lib/rearchitecture/features/delegation/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'no_delegation_stats_exception.dart'; diff --git a/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.dart b/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.dart new file mode 100644 index 00000000..c9f1f890 --- /dev/null +++ b/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.dart @@ -0,0 +1,33 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +part 'no_delegation_stats_exception.g.dart'; + +/// An exception used when there are no delegation info available +@immutable +@JsonSerializable() +class NoDelegationStatsException extends SyriusException { + /// Creates a [NoDelegationStatsException] instance + NoDelegationStatsException({ + String message = 'No delegation stats available', + }) : super(message); + + /// {@macro instance_from_json} + factory NoDelegationStatsException.fromJson(Map json) => + _$NoDelegationStatsExceptionFromJson(json); + + @override + Map toJson() => _$NoDelegationStatsExceptionToJson(this) + ..['runtimeType'] = 'NoDelegationStatsException'; + + @override + bool operator ==(Object other) { + return other is NoDelegationStatsException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.g.dart b/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.g.dart new file mode 100644 index 00000000..ca3ad73e --- /dev/null +++ b/lib/rearchitecture/features/delegation/exceptions/no_delegation_stats_exception.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'no_delegation_stats_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NoDelegationStatsException _$NoDelegationStatsExceptionFromJson( + Map json) => + NoDelegationStatsException( + message: json['message'] as String? ?? 'No delegation stats available', + ); + +Map _$NoDelegationStatsExceptionToJson( + NoDelegationStatsException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/features/delegation/view/delegation_card.dart b/lib/rearchitecture/features/delegation/view/delegation_card.dart new file mode 100644 index 00000000..e3b56db1 --- /dev/null +++ b/lib/rearchitecture/features/delegation/view/delegation_card.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A card that receives [DelegationState] updates from the [DelegationCubit] +/// and changes the UI according to the request status - [TimerStatus] +class DelegationCard extends StatelessWidget { + /// Creates a DelegationCard object. + const DelegationCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => DelegationCubit( + address: Address.parse(kSelectedAddress!), + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.delegationStats.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, DelegationState state) { + return switch (state.status) { + TimerStatus.initial => const DelegationEmpty(), + TimerStatus.loading => const DelegationLoading(), + TimerStatus.failure => DelegationError( + error: state.error!, + ), + TimerStatus.success => DelegationPopulated( + delegationInfo: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/delegation/widgets/delegation_empty.dart b/lib/rearchitecture/features/delegation/widgets/delegation_empty.dart new file mode 100644 index 00000000..6c3fe667 --- /dev/null +++ b/lib/rearchitecture/features/delegation/widgets/delegation_empty.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A widget that displays a hardcoded error message +class DelegationEmpty extends StatelessWidget { + /// Creates a DelegationEmpty object. + const DelegationEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/delegation/widgets/delegation_error.dart b/lib/rearchitecture/features/delegation/widgets/delegation_error.dart new file mode 100644 index 00000000..de87c313 --- /dev/null +++ b/lib/rearchitecture/features/delegation/widgets/delegation_error.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A widget that display the [error] message +class DelegationError extends StatelessWidget { + /// Creates a DelegationError object. + const DelegationError({required this.error, super.key}); + + /// The object that holds the representation of the error + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/delegation/widgets/delegation_loading.dart b/lib/rearchitecture/features/delegation/widgets/delegation_loading.dart new file mode 100644 index 00000000..d85318e2 --- /dev/null +++ b/lib/rearchitecture/features/delegation/widgets/delegation_loading.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_widget.dart'; + +/// A widget that displays the apps loading indicator +class DelegationLoading extends StatelessWidget { + /// Creates a DelegationLoading object. + const DelegationLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/delegation/widgets/delegation_populated.dart b/lib/rearchitecture/features/delegation/widgets/delegation_populated.dart new file mode 100644 index 00000000..2ff70fe8 --- /dev/null +++ b/lib/rearchitecture/features/delegation/widgets/delegation_populated.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_vector_icons/flutter_vector_icons.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget that displays the delegation amount and to which pillar the amount +/// was delegated to. +class DelegationPopulated extends StatelessWidget { + /// Creates a DelegationPopulated object. + const DelegationPopulated({required this.delegationInfo, super.key}); + + /// Field that holds the needed details + final DelegationInfo delegationInfo; + + @override + Widget build(BuildContext context) { + final String pillarName = delegationInfo.name; + final BigInt weight = delegationInfo.weight; + + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox.square( + dimension: 36, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: delegationInfo.status == 1 + ? AppColors.znnColor + : AppColors.errorColor, + ), + ), + child: const Icon( + SimpleLineIcons.trophy, + size: 12, + ), + ), + ), + kHorizontalGap16, + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + pillarName, + style: context.textTheme.bodyMedium, + ), + Text( + '${weight.addDecimals(coinDecimals)} ${kZnnCoin.symbol}', + style: context.textTheme.titleMedium, + ), + ], + ), + ], + ); + } +} diff --git a/lib/rearchitecture/features/delegation/widgets/widgets.dart b/lib/rearchitecture/features/delegation/widgets/widgets.dart new file mode 100644 index 00000000..6a53cbde --- /dev/null +++ b/lib/rearchitecture/features/delegation/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'delegation_empty.dart'; +export 'delegation_error.dart'; +export 'delegation_loading.dart'; +export 'delegation_populated.dart'; diff --git a/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.dart b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.dart new file mode 100644 index 00000000..099eaf4c --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.dart @@ -0,0 +1,58 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'dual_coin_stats_cubit.g.dart'; + +part 'dual_coin_stats_state.dart'; + +/// A cubit that manages the fetching and state of dual coin statistics - ZNN +/// and QSR. +/// +/// This cubit extends [TimerCubit], using a list of [Token] objects to +/// represent the statistics for the ZNN and QSR tokens fetched from the Zenon +/// network. +class DualCoinStatsCubit extends TimerCubit, DualCoinStatsState> { + /// Constructs a [DualCoinStatsCubit], passing the [zenon] client and the + /// initial state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// token information. + DualCoinStatsCubit({ + required super.zenon, + super.initialState = const DualCoinStatsState(), + }); + + /// Fetches the statistics for both ZNN and QSR tokens. + /// + /// It returns a list containing the fetched token data for ZNN and QSR. + @override + Future> fetch() async { + final List data = await Future.wait( + >[ + zenon.embedded.token.getByZts( + znnZts, // Fetches the ZNN token statistics + ), + zenon.embedded.token.getByZts( + qsrZts, // Fetches the QSR token statistics + ), + ], + ); + + // For ZNN and QSR, the network will return non-nullable data + final List nonNullableData = data + .map( + (Token? token) => token!, + ) + .toList(); + + return nonNullableData; + } + + @override + DualCoinStatsState? fromJson(Map json) => + DualCoinStatsState.fromJson(json); + + @override + Map? toJson(DualCoinStatsState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.g.dart b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.g.dart new file mode 100644 index 00000000..c3d38e9a --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_cubit.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'dual_coin_stats_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DualCoinStatsState _$DualCoinStatsStateFromJson(Map json) => + DualCoinStatsState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: (json['data'] as List?) + ?.map((e) => Token.fromJson(e as Map)) + .toList(), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$DualCoinStatsStateToJson(DualCoinStatsState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.map((e) => e.toJson()).toList(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_state.dart b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_state.dart new file mode 100644 index 00000000..a07de338 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/cubit/dual_coin_stats_state.dart @@ -0,0 +1,43 @@ +part of 'dual_coin_stats_cubit.dart'; + +/// The state class for the [DualCoinStatsCubit], extending [TimerState] to +/// manage data related to ZNN and QSR. +/// +/// [DualCoinStatsState] stores a list of [Token] objects representing data +/// for two tokens. +/// This state is used by the [DualCoinStatsCubit] to track and update the +/// state of both tokens. +@JsonSerializable(explicitToJson: true) +class DualCoinStatsState extends TimerState> { + /// Constructs a new [DualCoinStatsState]. + /// + /// This state is initialized with default [status], [data], and [error] + /// values from the parent [TimerState] class. + /// It manages a list of [Token] objects that represent the two coins' data. + const DualCoinStatsState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory DualCoinStatsState.fromJson(Map json) => + _$DualCoinStatsStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState> copyWith({ + TimerStatus? status, + List? data, + SyriusException? error, + }) { + return DualCoinStatsState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$DualCoinStatsStateToJson(this); +} diff --git a/lib/rearchitecture/features/dual_coin_stats/dual_coin_stats.dart b/lib/rearchitecture/features/dual_coin_stats/dual_coin_stats.dart new file mode 100644 index 00000000..3f05c0c3 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/dual_coin_stats.dart @@ -0,0 +1,3 @@ +export 'cubit/dual_coin_stats_cubit.dart'; +export 'view/dual_coin_stats_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/dual_coin_stats/view/dual_coin_stats_card.dart b/lib/rearchitecture/features/dual_coin_stats/view/dual_coin_stats_card.dart new file mode 100644 index 00000000..6fa0a495 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/view/dual_coin_stats_card.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +/// Widget connected to the [DualCoinStatsCubit] that receives the state +/// - [DualCoinStatsState] - updates and rebuilds the UI according to the +/// state's status - [TimerStatus] +class DualCoinStatsCard extends StatelessWidget { + /// Create a DualCoinStatsCard. + const DualCoinStatsCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => DualCoinStatsCubit( + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.dualCoinStats.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, DualCoinStatsState state) { + return switch (state.status) { + TimerStatus.initial => const DualCoinStatsEmpty(), + TimerStatus.loading => const DualCoinStatsLoading(), + TimerStatus.failure => DualCoinStatsError( + error: state.error!, + ), + TimerStatus.success => DualCoinStatsPopulated( + tokens: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart.dart new file mode 100644 index 00000000..15c2647e --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart.dart @@ -0,0 +1,79 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/chart/standard_pie_chart.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// Takes in a list of [Token] and shows a chart with sections corresponding to +/// the total supply of each [Token]. +/// +/// When the cursor hovers over a section, that respective section is +/// highlighted +class DualCoinStatsChart extends StatelessWidget { + /// Create a DualCoinStatsChart + const DualCoinStatsChart({ + required this.tokenList, + required this.touchedSectionIndexNotifier, + super.key, + }); + + /// List of [Token] that will provide data for the chart + final List tokenList; + + /// ValueNotifier used for rebuilding the widget tree when a section of the + /// chart is being hovered over + final ValueNotifier touchedSectionIndexNotifier; + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: touchedSectionIndexNotifier, + builder: (_, int? index, ___) => AspectRatio( + aspectRatio: 1, + child: StandardPieChart( + sectionsSpace: 4, + centerSpaceRadius: 0, + sections: _showingSections( + context: context, + tokenList: tokenList, + touchedSectionIndex: index, + ), + onChartSectionTouched: (PieTouchedSection? pieTouchedSection) { + touchedSectionIndexNotifier.value = + pieTouchedSection?.touchedSectionIndex; + }, + ), + ), + ); + } + + List _showingSections({ + required BuildContext context, + required List tokenList, + required int? touchedSectionIndex, + }) { + final BigInt totalSupply = tokenList.fold( + BigInt.zero, + ( + BigInt previousValue, + Token element, + ) => + previousValue + element.totalSupply, + ); + return List.generate( + tokenList.length, + (int i) { + final Token currentTokenInfo = tokenList[i]; + final bool isTouched = i == touchedSectionIndex; + final double opacity = isTouched ? 1.0 : 0.5; + return PieChartSectionData( + color: ColorUtils.getTokenColor(currentTokenInfo.tokenStandard) + .withOpacity(opacity), + value: currentTokenInfo.totalSupply / totalSupply, + title: currentTokenInfo.symbol, + radius: 60, + ); + }, + ); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend.dart new file mode 100644 index 00000000..87b342ef --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A legend for [DualCoinStatsChartLegend] +/// +/// It shows the token symbol, the amount in a shortened format - it has a +/// tooltip for showing the exact amount, including the decimals +class DualCoinStatsChartLegend extends StatelessWidget { + /// Creates a DualCoinStatsLegend + const DualCoinStatsChartLegend({ + required this.tokens, + super.key, + }); + + /// Data used + final List tokens; + + @override + Widget build(BuildContext context) { + final List items = List.generate( + tokens.length, + (int index) { + final Token token = tokens[index]; + + return Expanded( + child: DualCoinStatsChartLegendItem( + token: token, + ), + ); + }, + ); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: items, + ); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend_item.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend_item.dart new file mode 100644 index 00000000..2ea97958 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_chart_legend_item.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// Generic legend item that takes a [token] and customizes +/// a [FormattedAmountWithTooltip] widget. +class DualCoinStatsChartLegendItem extends StatelessWidget { + /// Creates a DualCoinStatsCharLegendItem instance. + const DualCoinStatsChartLegendItem({required this.token, super.key}); + + /// Provides the needed data that will be displayed. + final Token token; + + @override + Widget build(BuildContext context) { + return FormattedAmountWithTooltip( + amount: token.totalSupply.addDecimals( + token.decimals, + ), + tokenSymbol: token.symbol, + builder: (String amount, String symbol) => AmountInfoColumn( + amount: amount, + tokenSymbol: symbol, + context: context, + ), + ); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_empty.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_empty.dart new file mode 100644 index 00000000..e4b0bc48 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_empty.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget associated with the [DualCoinStatsState] when it's status is +/// [TimerStatus.initial] that uses the [SyriusErrorWidget] to display a +/// message +class DualCoinStatsEmpty extends StatelessWidget { + /// Creates a DualCoinStatsEmpty + const DualCoinStatsEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_error.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_error.dart new file mode 100644 index 00000000..13efc85d --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_error.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A widget associated with the [DualCoinStatsState] when it's status is +/// [TimerStatus.failure] that uses the [SyriusErrorWidget] to display the +/// error message + +class DualCoinStatsError extends StatelessWidget { + /// Creates a DualCoinStatsError object + const DualCoinStatsError({required this.error, super.key}); + + /// Holds the data that will be displayed + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_loading.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_loading.dart new file mode 100644 index 00000000..de0fae6b --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_loading.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_widget.dart'; + +/// A widget associated with the [DualCoinStatsState] when it's status is +/// [TimerStatus.loading] that uses the [SyriusLoadingWidget] to display a +/// loading indicator + +class DualCoinStatsLoading extends StatelessWidget { + /// Creates a DualCoinStatsLoading object + const DualCoinStatsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_populated.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_populated.dart new file mode 100644 index 00000000..ca6ce10e --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/dual_coin_stats_populated.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget associated with the [DualCoinStatsState] when it's status is +/// [TimerStatus.success] that displays the data provided using a chart +/// - [DualCoinStatsChart] - and a legend - [DualCoinStatsChartLegend] + +class DualCoinStatsPopulated extends StatefulWidget { + /// Creates a DualCoinStatsPopulated widget + const DualCoinStatsPopulated({ + required this.tokens, + super.key, + }); + + /// The list of [Token] that will provide data for the chart + final List tokens; + + @override + State createState() => _DualCoinStatsPopulatedState(); +} + +class _DualCoinStatsPopulatedState extends State + with SingleTickerProviderStateMixin { + final ValueNotifier _touchedSectionIndexNotifier = ValueNotifier( + null, + ); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Expanded( + child: DualCoinStatsChart( + tokenList: widget.tokens, + touchedSectionIndexNotifier: _touchedSectionIndexNotifier, + ), + ), + const Divider(), + Padding( + padding: const EdgeInsets.all(8), + child: DualCoinStatsChartLegend( + tokens: widget.tokens, + ), + ), + ], + ); + } +} diff --git a/lib/rearchitecture/features/dual_coin_stats/widgets/widgets.dart b/lib/rearchitecture/features/dual_coin_stats/widgets/widgets.dart new file mode 100644 index 00000000..63eee441 --- /dev/null +++ b/lib/rearchitecture/features/dual_coin_stats/widgets/widgets.dart @@ -0,0 +1,7 @@ +export 'dual_coin_stats_chart.dart'; +export 'dual_coin_stats_chart_legend.dart'; +export 'dual_coin_stats_chart_legend_item.dart'; +export 'dual_coin_stats_empty.dart'; +export 'dual_coin_stats_error.dart'; +export 'dual_coin_stats_loading.dart'; +export 'dual_coin_stats_populated.dart'; diff --git a/lib/rearchitecture/features/features.dart b/lib/rearchitecture/features/features.dart new file mode 100644 index 00000000..cb45f5aa --- /dev/null +++ b/lib/rearchitecture/features/features.dart @@ -0,0 +1,10 @@ +export 'balance/balance.dart'; +export 'delegation/delegation.dart'; +export 'dual_coin_stats/dual_coin_stats.dart'; +export 'node_sync_status/node_sync_status.dart'; +export 'pillars/pillars.dart'; +export 'realtime_statistics/realtime_statistics.dart'; +export 'sentinels/sentinels.dart'; +export 'staking/staking.dart'; +export 'total_hourly_transactions/total_hourly_transactions.dart'; +export 'transfer/transfer.dart'; diff --git a/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.dart b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.dart new file mode 100644 index 00000000..abdb3505 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.dart @@ -0,0 +1,74 @@ +import 'dart:async'; + +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart' hide zenon; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'node_sync_status_cubit.g.dart'; + +part 'node_sync_status_state.dart'; + +/// Cubit responsible for fetching the sync state - [SyncState] - and sending +/// the states update - [NodeSyncStatusState] - back to the widget +/// +/// [SyncState] is not related to [NodeSyncStatusState], doesn't handle UI +/// updates. +/// +/// [NodeSyncStatusState] along with [TimerStatus] updates the UI of the +/// [NodeSyncStatusIcon] widget +class NodeSyncStatusCubit + extends TimerCubit, NodeSyncStatusState> { + /// Creates a NodeSyncStatusCubit using the super-initializer parameters + NodeSyncStatusCubit({ + required super.zenon, + super.initialState = const NodeSyncStatusState(), + }) : super( + refreshInterval: kNodeSyncStatusRefreshInterval, + ); + + SyncState _lastSyncState = SyncState.unknown; + + @override + Future> fetch() async { + if (zenon.wsClient.status() == WebsocketStatus.running) { + final SyncInfo syncInfo = await zenon.stats.syncInfo(); + if (_lastSyncState != syncInfo.state && + (syncInfo.state == SyncState.syncDone || + (syncInfo.targetHeight > 0 && + syncInfo.currentHeight > 0 && + (syncInfo.targetHeight - syncInfo.currentHeight) > 3))) { + _lastSyncState = syncInfo.state; + if (syncInfo.state == SyncState.syncDone) { + unawaited( + Future.delayed(const Duration(seconds: 5)).then((_) { + NodeUtils.getUnreceivedTransactions().then((_) { + sl().autoReceive(); + }); + }), + ); + } + } + return Pair(_lastSyncState, syncInfo); + } + + final SyncInfo placeholderSyncInfo = SyncInfo.fromJson({ + 'state': 0, + 'currentHeight': 0, + 'targetHeight': 0, + }); + return Pair(_lastSyncState, placeholderSyncInfo); + } + + @override + NodeSyncStatusState? fromJson(Map json) => + NodeSyncStatusState.fromJson( + json, + ); + + @override + Map? toJson(NodeSyncStatusState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.g.dart b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.g.dart new file mode 100644 index 00000000..f8ac708f --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_cubit.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'node_sync_status_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NodeSyncStatusState _$NodeSyncStatusStateFromJson(Map json) => + NodeSyncStatusState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: json['data'] == null + ? null + : Pair.fromJson( + json['data'] as Map, + (value) => $enumDecode(_$SyncStateEnumMap, value), + (value) => SyncInfo.fromJson(value as Map)), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$NodeSyncStatusStateToJson( + NodeSyncStatusState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.toJson( + (value) => _$SyncStateEnumMap[value]!, + (value) => value.toJson(), + ), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; + +const _$SyncStateEnumMap = { + SyncState.unknown: 'unknown', + SyncState.syncing: 'syncing', + SyncState.syncDone: 'syncDone', + SyncState.notEnoughPeers: 'notEnoughPeers', +}; diff --git a/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_state.dart b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_state.dart new file mode 100644 index 00000000..6bbd1b1f --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/cubit/node_sync_status_state.dart @@ -0,0 +1,33 @@ +part of 'node_sync_status_cubit.dart'; + +/// Class used by [NodeSyncStatusCubit] to send state updates to the +/// connected view +@JsonSerializable(explicitToJson: true) +class NodeSyncStatusState extends TimerState> { + /// Creates a NodeSyncStatusState object. + const NodeSyncStatusState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory NodeSyncStatusState.fromJson(Map json) => + _$NodeSyncStatusStateFromJson(json); + + @override + TimerState> copyWith({ + TimerStatus? status, + Pair? data, + SyriusException? error, + }) { + return NodeSyncStatusState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$NodeSyncStatusStateToJson(this); +} diff --git a/lib/rearchitecture/features/node_sync_status/node_sync_status.dart b/lib/rearchitecture/features/node_sync_status/node_sync_status.dart new file mode 100644 index 00000000..61881f8c --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/node_sync_status.dart @@ -0,0 +1,3 @@ +export 'cubit/node_sync_status_cubit.dart'; +export 'view/node_sync_status_icon.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/node_sync_status/view/node_sync_status_icon.dart b/lib/rearchitecture/features/node_sync_status/view/node_sync_status_icon.dart new file mode 100644 index 00000000..5336c2c4 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/view/node_sync_status_icon.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; + +/// A widget connected to the [NodeSyncStatusCubit] that receives the state +/// - [NodeSyncStatusState] - updates and rebuilds the UI according to the +/// state's status - [TimerStatus] +class NodeSyncStatusIcon extends StatelessWidget { + /// Creates a NodeSyncStatusIcon object. + const NodeSyncStatusIcon({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (BuildContext context, NodeSyncStatusState state) { + return switch (state.status) { + TimerStatus.initial => const NodeSyncStatusEmpty(), + TimerStatus.failure => NodeSyncStatusError( + error: state.error!, + ), + TimerStatus.loading => const NodeSyncStatusLoading(), + TimerStatus.success => NodeSyncPopulated(data: state.data!), + }; + }, + ); + } +} diff --git a/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_empty.dart b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_empty.dart new file mode 100644 index 00000000..c65a3fb4 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_empty.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; + +/// A widget associated with the [NodeSyncStatusState] when it's status is +/// [TimerStatus.initial] that displays an icon with a tooltip message +class NodeSyncStatusEmpty extends StatelessWidget { + /// Creates a NodeSyncStatusEmpty object. + const NodeSyncStatusEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return Tooltip( + message: 'Not ready', + child: Icon( + Icons.sync_disabled, + size: 24, + color: Theme.of(context).iconTheme.color, + ), + ); + } +} diff --git a/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_error.dart b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_error.dart new file mode 100644 index 00000000..23666947 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_error.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; + +/// A widget associated with the [NodeSyncStatusState] when it's status is +/// [TimerStatus.failure] that displays an icon with a tooltip message +class NodeSyncStatusError extends StatelessWidget { + /// Creates a NodeSyncStatusError object. + const NodeSyncStatusError({required this.error, super.key}); + + /// Error that holds the message used in the [Tooltip] + final SyriusException error; + + @override + Widget build(BuildContext context) { + return Tooltip( + message: error.toString(), + child: const Icon( + Icons.sync_problem, + size: 24, + color: AppColors.errorColor, + ), + ); + } +} diff --git a/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_loading.dart b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_loading.dart new file mode 100644 index 00000000..816e12a8 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_loading.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; + +/// A widget associated with the [NodeSyncStatusState] when it's status is +/// [TimerStatus.loading] that displays a loading indicator with a tooltip +class NodeSyncStatusLoading extends StatelessWidget { + /// Creates a NodeSyncStatusLoading object. + const NodeSyncStatusLoading({super.key}); + + @override + Widget build(BuildContext context) { + return Tooltip( + message: 'Loading status', + child: SizedBox( + height: 18, + width: 18, + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).iconTheme.color, + color: AppColors.znnColor, + strokeWidth: 3, + ), + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_populated.dart b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_populated.dart new file mode 100644 index 00000000..79ef2965 --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/widgets/node_sync_status_populated.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget associated with the [NodeSyncStatusState] when it's status is +/// [TimerStatus.success] that returns a corresponding icon depending on the +/// [SyncInfo] and [SyncState] data +class NodeSyncPopulated extends StatelessWidget { + /// Creates a NodeSyncPopulated object. + const NodeSyncPopulated({required this.data, super.key}); + + /// A Pair holding detailed info about the sync stage + final Pair data; + + @override + Widget build(BuildContext context) { + var (SyncState syncState, SyncInfo syncInfo) = (data.first, data.second); + + String message = ''; + + if (syncState == SyncState.unknown) { + message = 'Not ready'; + return Tooltip( + message: message, + child: Icon( + Icons.sync_disabled, + size: 24, + color: syncState.getColor(context: context), + ), + ); + } else if (syncState == SyncState.syncing) { + if (syncInfo.targetHeight > 0 && + syncInfo.currentHeight > 0 && + (syncInfo.targetHeight - syncInfo.currentHeight) < 3) { + message = 'Connected and synced'; + syncState = SyncState.syncDone; + return Tooltip( + message: message, + child: Icon( + Icons.radio_button_unchecked, + size: 24, + color: syncState.getColor(context: context), + ), + ); + } else if (syncInfo.targetHeight == 0 || syncInfo.currentHeight == 0) { + message = 'Started syncing with the network, please wait'; + syncState = SyncState.syncing; + return Tooltip( + message: message, + child: Icon( + Icons.sync, + size: 24, + color: syncState.getColor(context: context), + ), + ); + } else { + message = 'Sync progress: momentum ${syncInfo.currentHeight} of ' + '${syncInfo.targetHeight}'; + return Tooltip( + message: message, + child: SizedBox.square( + dimension: 18, + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).iconTheme.color, + color: syncState.getColor(context: context), + value: syncInfo.currentHeight / syncInfo.targetHeight, + strokeWidth: 3, + ), + ), + ), + ); + } + } else if (syncState == SyncState.notEnoughPeers) { + if (syncInfo.targetHeight > 0 && + syncInfo.currentHeight > 0 && + (syncInfo.targetHeight - syncInfo.currentHeight) < 20) { + message = 'Connecting to peers'; + syncState = SyncState.syncing; + return Tooltip( + message: message, + child: SizedBox.square( + dimension: 18, + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).iconTheme.color, + color: syncState.getColor(context: context), + value: syncInfo.currentHeight / syncInfo.targetHeight, + strokeWidth: 3, + ), + ), + ), + ); + } else if (syncInfo.targetHeight == 0 || syncInfo.currentHeight == 0) { + message = 'Connecting to peers, please wait'; + syncState = SyncState.syncing; + return Tooltip( + message: message, + child: Icon( + Icons.sync, + size: 24, + color: syncState.getColor(context: context), + ), + ); + } else { + message = 'Sync progress: momentum ${syncInfo.currentHeight} of ' + '${syncInfo.targetHeight}'; + syncState = SyncState.syncing; + return Tooltip( + message: message, + child: SizedBox.square( + dimension: 18, + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).iconTheme.color, + color: syncState.getColor(context: context), + value: syncInfo.currentHeight / syncInfo.targetHeight, + strokeWidth: 3, + ), + ), + ), + ); + } + } else { + message = 'Connected and synced'; + syncState = SyncState.syncDone; + } + + return Tooltip( + message: message, + child: SizedBox.square( + dimension: 18, + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).iconTheme.color, + color: syncState.getColor(context: context), + value: 1, + strokeWidth: 2, + ), + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/node_sync_status/widgets/widgets.dart b/lib/rearchitecture/features/node_sync_status/widgets/widgets.dart new file mode 100644 index 00000000..cbde982c --- /dev/null +++ b/lib/rearchitecture/features/node_sync_status/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'node_sync_status_empty.dart'; +export 'node_sync_status_error.dart'; +export 'node_sync_status_loading.dart'; +export 'node_sync_status_populated.dart'; diff --git a/lib/rearchitecture/features/pillars/cubit/pillars_cubit.dart b/lib/rearchitecture/features/pillars/cubit/pillars_cubit.dart new file mode 100644 index 00000000..f3dc4d1b --- /dev/null +++ b/lib/rearchitecture/features/pillars/cubit/pillars_cubit.dart @@ -0,0 +1,40 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'pillars_cubit.g.dart'; + +part 'pillars_state.dart'; + +/// [PillarsCubit] manages the fetching and state of pillar statistics. +/// +/// It uses an integer to represent the total number of pillars fetched from +/// the Zenon network. +class PillarsCubit extends TimerCubit { + /// Constructs a [PillarsCubit], passing the [zenon] client and the initial + /// state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// pillar information. + PillarsCubit({ + required super.zenon, + super.initialState = const PillarsState(), + }); + + /// Fetches the total count of pillars from the Zenon network. + @override + Future fetch() async { + final PillarInfoList pillarInfoList = await zenon.embedded.pillar.getAll(); + final int data = pillarInfoList.list.length; + kNumOfPillars = data; + return data; + } + + @override + PillarsState? fromJson(Map json) => + PillarsState.fromJson(json); + + @override + Map? toJson(PillarsState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/pillars/cubit/pillars_cubit.g.dart b/lib/rearchitecture/features/pillars/cubit/pillars_cubit.g.dart new file mode 100644 index 00000000..c71192ca --- /dev/null +++ b/lib/rearchitecture/features/pillars/cubit/pillars_cubit.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pillars_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PillarsState _$PillarsStateFromJson(Map json) => PillarsState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: (json['data'] as num?)?.toInt(), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$PillarsStateToJson(PillarsState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data, + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/pillars/cubit/pillars_state.dart b/lib/rearchitecture/features/pillars/cubit/pillars_state.dart new file mode 100644 index 00000000..7f7c5490 --- /dev/null +++ b/lib/rearchitecture/features/pillars/cubit/pillars_state.dart @@ -0,0 +1,40 @@ +part of 'pillars_cubit.dart'; + +/// This state is used by the [PillarsCubit] to track and update the number of +/// active pillars. +/// +/// [PillarsState] stores an integer value representing the number of pillars +/// retrieved from the Zenon network. +@JsonSerializable(explicitToJson: true) +class PillarsState extends TimerState { + /// Constructs a new [PillarsState] object. + /// + /// The [data] field in this case represents the count of active pillars on + /// the Zenon network. + const PillarsState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory PillarsState.fromJson(Map json) => + _$PillarsStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState copyWith({ + TimerStatus? status, + int? data, + SyriusException? error, + }) { + return PillarsState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$PillarsStateToJson(this); +} diff --git a/lib/rearchitecture/features/pillars/pillars.dart b/lib/rearchitecture/features/pillars/pillars.dart new file mode 100644 index 00000000..fcf6c70f --- /dev/null +++ b/lib/rearchitecture/features/pillars/pillars.dart @@ -0,0 +1,3 @@ +export 'cubit/pillars_cubit.dart'; +export 'view/pillars_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/pillars/view/pillars_card.dart b/lib/rearchitecture/features/pillars/view/pillars_card.dart new file mode 100644 index 00000000..27d2c7d4 --- /dev/null +++ b/lib/rearchitecture/features/pillars/view/pillars_card.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +/// Widget connected to the [PillarsCubit] that receives the state +/// - [PillarsState] - updates and rebuilds the UI according to the +/// state's status - [TimerStatus] +class PillarsCard extends StatelessWidget { + /// Creates a PillarsCard + const PillarsCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => PillarsCubit( + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.pillars.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, PillarsState state) { + return switch (state.status) { + TimerStatus.initial => const PillarsEmpty(), + TimerStatus.loading => const PillarsLoading(), + TimerStatus.failure => PillarsError( + error: state.error!, + ), + TimerStatus.success => PillarsPopulated( + numberOfPillars: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/pillars/widgets/pillars_empty.dart b/lib/rearchitecture/features/pillars/widgets/pillars_empty.dart new file mode 100644 index 00000000..e75af6bc --- /dev/null +++ b/lib/rearchitecture/features/pillars/widgets/pillars_empty.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget associated with the [PillarsState] when it's status is +/// [TimerStatus.initial] that uses the [SyriusErrorWidget] to display a +/// message. +class PillarsEmpty extends StatelessWidget { + /// Creates a PillarsEmpty instance + const PillarsEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/pillars/widgets/pillars_error.dart b/lib/rearchitecture/features/pillars/widgets/pillars_error.dart new file mode 100644 index 00000000..594d0dd0 --- /dev/null +++ b/lib/rearchitecture/features/pillars/widgets/pillars_error.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget associated with the [PillarsState] when it's status is +/// [TimerStatus.failure] that uses the [SyriusErrorWidget] to display the +/// error message. +class PillarsError extends StatelessWidget { + /// Creates a PillarsError object. + const PillarsError({required this.error, super.key}); + + /// Holds the data that will be displayed. + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/pillars/widgets/pillars_loading.dart b/lib/rearchitecture/features/pillars/widgets/pillars_loading.dart new file mode 100644 index 00000000..6e2e6a7b --- /dev/null +++ b/lib/rearchitecture/features/pillars/widgets/pillars_loading.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget associated with the [PillarsState] when it's status is +/// [TimerStatus.loading] that uses the [SyriusLoadingWidget] to display a +/// loading indicator. +class PillarsLoading extends StatelessWidget { + /// Creates a PillarsLoading object. + const PillarsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/pillars/widgets/pillars_populated.dart b/lib/rearchitecture/features/pillars/widgets/pillars_populated.dart new file mode 100644 index 00000000..9e7d74cb --- /dev/null +++ b/lib/rearchitecture/features/pillars/widgets/pillars_populated.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget associated with the [PillarsState] when it's status is +/// [TimerStatus.success] that displays the number of pillars. +class PillarsPopulated extends StatelessWidget { + /// Creates a PillarsPopulated object. + const PillarsPopulated({required this.numberOfPillars, super.key}); + + /// Number of pillars in the network. + final int numberOfPillars; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/svg/ic_pillars_dashboard.svg', + width: 65, + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + NumberAnimation( + end: numberOfPillars, + isInt: true, + style: context.textTheme.headlineMedium, + ), + Text( + context.l10n.activePillars, + style: context.textTheme.bodyMedium, + ), + ], + ), + ], + ); + } +} diff --git a/lib/rearchitecture/features/pillars/widgets/widgets.dart b/lib/rearchitecture/features/pillars/widgets/widgets.dart new file mode 100644 index 00000000..58cf2d1c --- /dev/null +++ b/lib/rearchitecture/features/pillars/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'pillars_empty.dart'; +export 'pillars_error.dart'; +export 'pillars_loading.dart'; +export 'pillars_populated.dart'; diff --git a/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.dart b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.dart new file mode 100644 index 00000000..0afaa442 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.dart @@ -0,0 +1,104 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'realtime_statistics_cubit.g.dart'; + +part 'realtime_statistics_state.dart'; + +/// [RealtimeStatisticsCubit] manages the fetching and state of real-time +/// account block statistics for a specific address. +class RealtimeStatisticsCubit + extends TimerCubit, RealtimeStatisticsState> { + /// Constructs a [RealtimeStatisticsCubit], passing the [zenon] client and + /// the initial state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// account block information. + RealtimeStatisticsCubit({ + required this.address, + required super.zenon, + super.initialState = const RealtimeStatisticsState(), + }); + + ///The address for which the list of account blocks is fetched + final Address address; + + /// Fetches a list of account blocks for the specified address over the past + /// week. + /// + /// This method retrieves the account blocks by: + /// - Determining the chain height. + /// - Calculating the starting height based on the momentums per week. + /// - Fetching account blocks page by page until there are no more blocks to + /// retrieve. + /// - The loop continues until either the blocks are exhausted or the last + /// block's momentum height is less than the calculated height. + /// + /// Returns: + /// - A list of [AccountBlock] objects representing the account blocks + /// fetched from the network. + /// + /// Throws: + /// - An [NoBlocksAvailableException] if no data is available + @override + Future> fetch() async { + // Get the current chain height + final int chainHeight = (await zenon.ledger.getFrontierMomentum()).height; + // Calculate the starting height for the block retrieval + final int height = chainHeight - kMomentumsPerWeek > 0 + ? chainHeight - kMomentumsPerWeek + : 1; + int pageIndex = 0; // Start from the first page + const int pageSize = 10; // Number of blocks to fetch per page + bool isLastPage = false; // Flag to determine if it's the last page + final List blockList = + []; // List to store fetched account blocks + + // Fetch account blocks until the last page is reached + while (!isLastPage) { + // Fetch account blocks for the current page + final AccountBlockList accountBlockList = + await zenon.ledger.getAccountBlocksByPage( + address, + pageIndex: pageIndex, + pageSize: pageSize, + ); + // Default to an empty list if no blocks are found + final List response = + accountBlockList.list ?? []; + + if (response.isEmpty) { + break; // Exit the loop if no more blocks are found + } + + blockList.addAll(response); // Add the fetched blocks to the list + + // Check if the last block's momentum height is less than the + // calculated height + if (response.last.confirmationDetail!.momentumHeight <= height) { + break; // Exit if we've fetched enough data + } + + pageIndex += 1; // Increment the page index for the next fetch + isLastPage = response.length < pageSize; // Check if this is the last page + } + + if (blockList.isNotEmpty) { + return blockList; // Return the list of fetched blocks if available + } else { + throw NoBlocksAvailableException(); + } + } + + @override + RealtimeStatisticsState? fromJson(Map json) => + RealtimeStatisticsState.fromJson( + json, + ); + + @override + Map? toJson(RealtimeStatisticsState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.g.dart b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.g.dart new file mode 100644 index 00000000..3763af83 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_cubit.g.dart @@ -0,0 +1,35 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'realtime_statistics_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RealtimeStatisticsState _$RealtimeStatisticsStateFromJson( + Map json) => + RealtimeStatisticsState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: (json['data'] as List?) + ?.map((e) => AccountBlock.fromJson(e as Map)) + .toList(), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$RealtimeStatisticsStateToJson( + RealtimeStatisticsState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.map((e) => e.toJson()).toList(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_state.dart b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_state.dart new file mode 100644 index 00000000..e64cee90 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/cubit/realtime_statistics_state.dart @@ -0,0 +1,43 @@ +part of 'realtime_statistics_cubit.dart'; + +/// The state class for [RealtimeStatisticsCubit], which extends +/// [TimerState] to handle real-time statistics data. +/// +/// This class manages a list of [AccountBlock] objects representing real-time +/// blockchain data, such as recent transactions. +/// It's used to track the state of the data loading process in the +/// [RealtimeStatisticsCubit]. +@JsonSerializable(explicitToJson: true) +class RealtimeStatisticsState extends TimerState> { + /// Constructs a new [RealtimeStatisticsState] with optional values for + /// [status], [data], and [error]. + /// + /// The [data] field stores a list of [AccountBlock] objects that represent + /// real-time blockchain statistics. + const RealtimeStatisticsState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory RealtimeStatisticsState.fromJson(Map json) => + _$RealtimeStatisticsStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState> copyWith({ + TimerStatus? status, + List? data, + SyriusException? error, + }) { + return RealtimeStatisticsState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$RealtimeStatisticsStateToJson(this); +} diff --git a/lib/rearchitecture/features/realtime_statistics/exceptions/exceptions.dart b/lib/rearchitecture/features/realtime_statistics/exceptions/exceptions.dart new file mode 100644 index 00000000..062f575d --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'no_blocks_available_exception.dart'; diff --git a/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.dart b/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.dart new file mode 100644 index 00000000..432de9e0 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.dart @@ -0,0 +1,35 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; + +part 'no_blocks_available_exception.g.dart'; + +/// An exception to be used with [RealtimeStatisticsCubit] when there are +/// no account blocks available on the network +@immutable +@JsonSerializable() +class NoBlocksAvailableException extends SyriusException { + /// Creates a [NoBlocksAvailableException] instance + NoBlocksAvailableException({ + String message = 'No account blocks available', + }) : super(message); + + /// {@macro instance_from_json} + factory NoBlocksAvailableException.fromJson(Map json) => + _$NoBlocksAvailableExceptionFromJson(json); + + @override + Map toJson() => _$NoBlocksAvailableExceptionToJson(this) + ..['runtimeType'] = 'NoBlocksAvailableException'; + + @override + bool operator ==(Object other) { + return other is NoBlocksAvailableException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.g.dart b/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.g.dart new file mode 100644 index 00000000..f379eaed --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/exceptions/no_blocks_available_exception.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'no_blocks_available_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NoBlocksAvailableException _$NoBlocksAvailableExceptionFromJson( + Map json) => + NoBlocksAvailableException( + message: json['message'] as String? ?? 'No account blocks available', + ); + +Map _$NoBlocksAvailableExceptionToJson( + NoBlocksAvailableException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/features/realtime_statistics/realtime_statistics.dart b/lib/rearchitecture/features/realtime_statistics/realtime_statistics.dart new file mode 100644 index 00000000..e1f1bbe7 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/realtime_statistics.dart @@ -0,0 +1,4 @@ +export 'cubit/realtime_statistics_cubit.dart'; +export 'exceptions/exceptions.dart'; +export 'view/realtime_statistics_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/realtime_statistics/view/realtime_statistics_card.dart b/lib/rearchitecture/features/realtime_statistics/view/realtime_statistics_card.dart new file mode 100644 index 00000000..5f387e47 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/view/realtime_statistics_card.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A card that receives [RealtimeStatisticsState] updates from the +/// [RealtimeStatisticsCubit] and changes the UI according to the request +/// status - [TimerStatus]. +class RealtimeStatisticsCard extends StatelessWidget { + /// Creates a RealtimeStatisticsCard object. + const RealtimeStatisticsCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => RealtimeStatisticsCubit( + address: Address.parse(kSelectedAddress!), + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.realtimeStatistics.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, RealtimeStatisticsState state) { + return switch (state.status) { + TimerStatus.initial => const RealtimeStatisticsEmpty(), + TimerStatus.loading => const RealtimeStatisticsLoading(), + TimerStatus.failure => RealtimeStatisticsError( + error: state.error!, + ), + TimerStatus.success => RealtimeStatisticsPopulated( + accountBlocks: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_empty.dart b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_empty.dart new file mode 100644 index 00000000..53fa8be4 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_empty.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget that displays a hardcoded error message +class RealtimeStatisticsEmpty extends StatelessWidget { + /// Creates a RealtimeStatisticsEmpty object. + const RealtimeStatisticsEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_error.dart b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_error.dart new file mode 100644 index 00000000..80f45717 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_error.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget that displays an error message +class RealtimeStatisticsError extends StatelessWidget { + /// Creates a RealtimeStatisticsError object + const RealtimeStatisticsError({required this.error, super.key}); + + /// The data that holds the message that will be displayed + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_loading.dart b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_loading.dart new file mode 100644 index 00000000..3ef323d9 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_loading.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/reusable_widgets.dart'; + +/// A widget that displays a loading indicator +class RealtimeStatisticsLoading extends StatelessWidget { + /// Creates a RealtimeStatisticsLoading object. + const RealtimeStatisticsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_populated.dart b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_populated.dart new file mode 100644 index 00000000..c20c7081 --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_statistics_populated.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/realtime_statistics/widgets/realtime_txs_chart.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget associated with the [RealtimeStatisticsState] when it's status is +/// [TimerStatus.success] +/// +/// Displays a chart highlighting the number of blocks in QSR and ZNN signed +/// with a particular address in the last seven days +class RealtimeStatisticsPopulated extends StatelessWidget { + /// Creates a RealtimeStatisticsPopulated object. + const RealtimeStatisticsPopulated({required this.accountBlocks, super.key}); + + /// List of account blocks containing the ZNN and QSR transactions + final List accountBlocks; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ChartLegend( + dotColor: ColorUtils.getTokenColor(kQsrCoin.tokenStandard), + mainText: context.l10n.quasarTransactions(kQsrCoin.symbol), + ), + kHorizontalGap8, + ChartLegend( + dotColor: ColorUtils.getTokenColor(kZnnCoin.tokenStandard), + mainText: context.l10n.zenonTransactions(kZnnCoin.symbol), + ), + ], + ), + Expanded(child: RealtimeTxsChart(accountBlocks)), + ], + ), + ); + } +} diff --git a/lib/widgets/charts/realtime_txs_chart.dart b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_txs_chart.dart similarity index 73% rename from lib/widgets/charts/realtime_txs_chart.dart rename to lib/rearchitecture/features/realtime_statistics/widgets/realtime_txs_chart.dart index 4c9862c8..0de12633 100644 --- a/lib/widgets/charts/realtime_txs_chart.dart +++ b/lib/rearchitecture/features/realtime_statistics/widgets/realtime_txs_chart.dart @@ -8,19 +8,22 @@ import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; +/// Shows a chart based on the provided [transactions] class RealtimeTxsChart extends StatefulWidget { - final List transactions; - + /// Creates a RealtimeTxsChart object. const RealtimeTxsChart( this.transactions, { - Key? key, - }) : super(key: key); + super.key, + }); + + /// The data needed to generate the chart + final List transactions; @override - State createState() => RealtimeTxsChartState(); + State createState() => _RealtimeTxsChartState(); } -class RealtimeTxsChartState extends State { +class _RealtimeTxsChartState extends State { double _maxTransactionsPerDay = 0; List? _znnSpots; @@ -33,21 +36,9 @@ class RealtimeTxsChartState extends State { _qsrSpots = _generateQsrSpots(); } - @override - void didUpdateWidget(RealtimeTxsChart oldWidget) { - // The spots variables must be generated before - // calling super.didUpdateWidget(oldWidget). - _znnSpots = _generateZnnSpots(); - _qsrSpots = _generateQsrSpots(); - super.didUpdateWidget(oldWidget); - } - @override Widget build(BuildContext context) { return StandardChart( - yValuesInterval: _maxTransactionsPerDay > kNumOfChartLeftSideTitles - ? _maxTransactionsPerDay / kNumOfChartLeftSideTitles - : 1, maxY: _maxTransactionsPerDay, lineBarsData: _linesBarData(), lineBarDotSymbol: 'txs', @@ -57,19 +48,19 @@ class RealtimeTxsChartState extends State { } double _getTransactionsByDay(TokenStandard tokenId, DateTime date) { - List transactions = []; - for (var transaction in widget.transactions) { + final List transactions = []; + for (final AccountBlock transaction in widget.transactions) { AccountBlock? pairedAccountBlock; if (transaction.blockType == 3 && transaction.pairedAccountBlock != null) { - pairedAccountBlock = transaction.pairedAccountBlock!; + pairedAccountBlock = transaction.pairedAccountBlock; } if (DateFormat('d MMM, yyyy').format(date) == DateFormat('d MMM, yyyy').format( DateTime.fromMillisecondsSinceEpoch( - (transaction.confirmationDetail?.momentumTimestamp ?? 0) * - 1000), + (transaction.confirmationDetail?.momentumTimestamp ?? 0) * 1000, + ), )) { if (transaction.tokenStandard == tokenId || (pairedAccountBlock != null && @@ -79,7 +70,7 @@ class RealtimeTxsChartState extends State { } } - double transactionsPerDay = transactions.length.toDouble(); + final double transactionsPerDay = transactions.length.toDouble(); if (transactionsPerDay > _maxTransactionsPerDay) { _maxTransactionsPerDay = transactionsPerDay; @@ -88,7 +79,7 @@ class RealtimeTxsChartState extends State { } List _linesBarData() { - return [ + return [ StandardLineChartBarData( color: ColorUtils.getTokenColor(kZnnCoin.tokenStandard), spots: _znnSpots, @@ -101,9 +92,9 @@ class RealtimeTxsChartState extends State { } List _generateQsrSpots() { - return List.generate( + return List.generate( kStandardChartNumDays.toInt(), - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getTransactionsByDay( kQsrCoin.tokenStandard, @@ -116,9 +107,9 @@ class RealtimeTxsChartState extends State { } List _generateZnnSpots() { - return List.generate( + return List.generate( kStandardChartNumDays.toInt(), - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getTransactionsByDay( kZnnCoin.tokenStandard, diff --git a/lib/rearchitecture/features/realtime_statistics/widgets/widgets.dart b/lib/rearchitecture/features/realtime_statistics/widgets/widgets.dart new file mode 100644 index 00000000..ed96407e --- /dev/null +++ b/lib/rearchitecture/features/realtime_statistics/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'realtime_statistics_empty.dart'; +export 'realtime_statistics_error.dart'; +export 'realtime_statistics_loading.dart'; +export 'realtime_statistics_populated.dart'; diff --git a/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.dart b/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.dart new file mode 100644 index 00000000..a91befe0 --- /dev/null +++ b/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.dart @@ -0,0 +1,39 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'sentinels_cubit.g.dart'; + +part 'sentinels_state.dart'; + +/// [SentinelsCubit] manages the fetching and state of sentinel information. +/// +/// It uses a [SentinelInfoList] object to represent the list of active +/// sentinels fetched from the Zenon network. +class SentinelsCubit extends TimerCubit { + /// Constructs a [SentinelsCubit], passing the [zenon] client and the initial + /// state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// sentinel information. + SentinelsCubit({ + required super.zenon, + super.initialState = const SentinelsState(), + }); + + /// Fetches a list of active sentinels from the Zenon network. + @override + Future fetch() async { + final SentinelInfoList data = await zenon.embedded.sentinel.getAllActive(); + return data; + } + + @override + SentinelsState? fromJson(Map json) => + SentinelsState.fromJson( + json, + ); + + @override + Map? toJson(SentinelsState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.g.dart b/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.g.dart new file mode 100644 index 00000000..2730955d --- /dev/null +++ b/lib/rearchitecture/features/sentinels/cubit/sentinels_cubit.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sentinels_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SentinelsState _$SentinelsStateFromJson(Map json) => + SentinelsState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: json['data'] == null + ? null + : SentinelInfoList.fromJson(json['data'] as Map), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$SentinelsStateToJson(SentinelsState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.toJson(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/sentinels/cubit/sentinels_state.dart b/lib/rearchitecture/features/sentinels/cubit/sentinels_state.dart new file mode 100644 index 00000000..560286ad --- /dev/null +++ b/lib/rearchitecture/features/sentinels/cubit/sentinels_state.dart @@ -0,0 +1,42 @@ +part of 'sentinels_cubit.dart'; + +/// The state class for [SentinelsCubit], which extends [TimerState] to +/// manage sentinel-related data. +/// +/// This class manages a [SentinelInfoList] object representing information +/// about active sentinels. It is used to track +/// the state of sentinel data loading within the [SentinelsCubit]. +@JsonSerializable(explicitToJson: true) +class SentinelsState extends TimerState { + /// Constructs a new [SentinelsState] with optional values for [status], + /// [data], and [error]. + /// + /// The [data] field stores a [SentinelInfoList] object, which contains the + /// details of all active sentinels on the network. + const SentinelsState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory SentinelsState.fromJson(Map json) => + _$SentinelsStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState copyWith({ + TimerStatus? status, + SentinelInfoList? data, + SyriusException? error, + }) { + return SentinelsState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$SentinelsStateToJson(this); +} diff --git a/lib/rearchitecture/features/sentinels/sentinels.dart b/lib/rearchitecture/features/sentinels/sentinels.dart new file mode 100644 index 00000000..3651698d --- /dev/null +++ b/lib/rearchitecture/features/sentinels/sentinels.dart @@ -0,0 +1,3 @@ +export 'cubit/sentinels_cubit.dart'; +export 'view/sentinels_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/sentinels/view/sentinels_card.dart b/lib/rearchitecture/features/sentinels/view/sentinels_card.dart new file mode 100644 index 00000000..0867ba49 --- /dev/null +++ b/lib/rearchitecture/features/sentinels/view/sentinels_card.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +/// Widget connected to the [SentinelsCubit] that receives the state +/// - [SentinelsState] - updates and rebuilds the UI according to the +/// state's status - [TimerStatus]. +class SentinelsCard extends StatelessWidget { + /// Creates a SentinelsCard object. + const SentinelsCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => SentinelsCubit( + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.sentinels.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, SentinelsState state) { + return switch (state.status) { + TimerStatus.initial => const SentinelsEmpty(), + TimerStatus.loading => const SentinelsLoading(), + TimerStatus.failure => SentinelsError( + error: state.error!, + ), + TimerStatus.success => SentinelsPopulated( + sentinelInfoList: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/sentinels/widgets/sentinels_empty.dart b/lib/rearchitecture/features/sentinels/widgets/sentinels_empty.dart new file mode 100644 index 00000000..9170dddd --- /dev/null +++ b/lib/rearchitecture/features/sentinels/widgets/sentinels_empty.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [SentinelsState] when it's status is +/// [TimerStatus.initial] that uses the [SyriusErrorWidget] to display a +/// message +class SentinelsEmpty extends StatelessWidget { + /// Creates a SentinelsEmpty object + const SentinelsEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/sentinels/widgets/sentinels_error.dart b/lib/rearchitecture/features/sentinels/widgets/sentinels_error.dart new file mode 100644 index 00000000..37950174 --- /dev/null +++ b/lib/rearchitecture/features/sentinels/widgets/sentinels_error.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [SentinelsState] when it's status is +/// [TimerStatus.failure] that uses the [SyriusErrorWidget] to display an +/// error. +class SentinelsError extends StatelessWidget { + /// Creates a SentinelsError objects. + const SentinelsError({required this.error, super.key}); + + /// The object that holds the representation of the error. + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/sentinels/widgets/sentinels_loading.dart b/lib/rearchitecture/features/sentinels/widgets/sentinels_loading.dart new file mode 100644 index 00000000..674910c4 --- /dev/null +++ b/lib/rearchitecture/features/sentinels/widgets/sentinels_loading.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [SentinelsState] when it's status is +/// [TimerStatus.loading] that uses the [SyriusLoadingWidget] to display a +/// loading indicator. +class SentinelsLoading extends StatelessWidget { + /// Creates a SentinelsLoading object. + const SentinelsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/sentinels/widgets/sentinels_populated.dart b/lib/rearchitecture/features/sentinels/widgets/sentinels_populated.dart new file mode 100644 index 00000000..1a334b6d --- /dev/null +++ b/lib/rearchitecture/features/sentinels/widgets/sentinels_populated.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget associated with the [SentinelsState] when it's status is +/// [TimerStatus.success] that displays the current number of sentinels. +class SentinelsPopulated extends StatelessWidget { + /// Creates a SentinelsPopulated object. + const SentinelsPopulated({required this.sentinelInfoList, super.key}); + + /// The data needed to display the current number of sentinels. + final SentinelInfoList sentinelInfoList; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(12), + child: SvgPicture.asset( + 'assets/svg/ic_sentinels_dashboard.svg', + width: 42, + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + NumberAnimation( + end: sentinelInfoList.count, + isInt: true, + style: context.textTheme.headlineMedium, + ), + Text( + context.l10n.activeSentinels, + style: context.textTheme.bodyMedium, + ), + ], + ), + ], + ); + } +} diff --git a/lib/rearchitecture/features/sentinels/widgets/widgets.dart b/lib/rearchitecture/features/sentinels/widgets/widgets.dart new file mode 100644 index 00000000..7a94c0ca --- /dev/null +++ b/lib/rearchitecture/features/sentinels/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'sentinels_empty.dart'; +export 'sentinels_error.dart'; +export 'sentinels_loading.dart'; +export 'sentinels_populated.dart'; diff --git a/lib/rearchitecture/features/staking/cubit/staking_cubit.dart b/lib/rearchitecture/features/staking/cubit/staking_cubit.dart new file mode 100644 index 00000000..6aa63478 --- /dev/null +++ b/lib/rearchitecture/features/staking/cubit/staking_cubit.dart @@ -0,0 +1,59 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'staking_cubit.g.dart'; + +part 'staking_state.dart'; + +/// [StakingCubit] manages the fetching and state of staking information. +/// +/// It uses a [StakeList] object to represent the list of staking entries for a +/// specific address. +class StakingCubit extends TimerCubit { + /// Constructs a [StakingCubit], passing the [zenon] client and the initial + /// state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// staking information. + StakingCubit({ + required this.address, + required super.zenon, + super.initialState = const StakingState(), + }); + + /// The address for which the [StakeList] will be fetched + final Address address; + + /// Fetches a list of staking entries for a specific address from the Zenon + /// network. + /// + /// Throws: + /// - An error if no active staking entries are found or if any exception + /// occurs during the fetching process. + @override + Future fetch() async { + final StakeList data = await _getStakeList(address); + if (data.list.isNotEmpty) { + return data; + } else { + throw NoActiveStakingEntriesException(); + } + } + + /// Retrieves the staking entries for a specific address. + Future _getStakeList(Address address) async { + return zenon.embedded.stake.getEntriesByAddress( + address, + ); + } + + @override + StakingState? fromJson(Map json) => StakingState.fromJson( + json, + ); + + @override + Map? toJson(StakingState state) => state.toJson(); +} diff --git a/lib/rearchitecture/features/staking/cubit/staking_cubit.g.dart b/lib/rearchitecture/features/staking/cubit/staking_cubit.g.dart new file mode 100644 index 00000000..b70655c6 --- /dev/null +++ b/lib/rearchitecture/features/staking/cubit/staking_cubit.g.dart @@ -0,0 +1,32 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'staking_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +StakingState _$StakingStateFromJson(Map json) => StakingState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: json['data'] == null + ? null + : StakeList.fromJson(json['data'] as Map), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$StakingStateToJson(StakingState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data?.toJson(), + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/staking/cubit/staking_state.dart b/lib/rearchitecture/features/staking/cubit/staking_state.dart new file mode 100644 index 00000000..55bc08ac --- /dev/null +++ b/lib/rearchitecture/features/staking/cubit/staking_state.dart @@ -0,0 +1,40 @@ +part of 'staking_cubit.dart'; + +/// This class manages a [StakeList] object representing the list of active +/// staking entries. +/// It tracks the loading, success, or failure of fetching staking data within +/// the [StakingCubit]. +@JsonSerializable(explicitToJson: true) +class StakingState extends TimerState { + /// Constructs a new [StakingState] with optional values for [status], + /// [data], and [error]. + /// + /// The [data] field holds a [StakeList] object, which contains the list of + /// active staking entries for a particular address. + const StakingState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory StakingState.fromJson(Map json) => + _$StakingStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState copyWith({ + TimerStatus? status, + StakeList? data, + SyriusException? error, + }) { + return StakingState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$StakingStateToJson(this); +} diff --git a/lib/rearchitecture/features/staking/exceptions/exceptions.dart b/lib/rearchitecture/features/staking/exceptions/exceptions.dart new file mode 100644 index 00000000..9d859e4a --- /dev/null +++ b/lib/rearchitecture/features/staking/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'no_active_skaking_entries_exception.dart'; diff --git a/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.dart b/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.dart new file mode 100644 index 00000000..00801ebe --- /dev/null +++ b/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.dart @@ -0,0 +1,35 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; + +part 'no_active_skaking_entries_exception.g.dart'; + +/// An exception to be used with [StakingCubit] when there are no active +/// staking entries found on an address. +@immutable +@JsonSerializable() +class NoActiveStakingEntriesException extends SyriusException { + /// Creates a [NoActiveStakingEntriesException] instance. + NoActiveStakingEntriesException({ + String message = 'No active staking entries', + }) : super(message); + + /// {@macro instance_from_json} + factory NoActiveStakingEntriesException.fromJson(Map json) => + _$NoActiveStakingEntriesExceptionFromJson(json); + + @override + Map toJson() => _$NoActiveStakingEntriesExceptionToJson(this) + ..['runtimeType'] = 'NoActiveStakingEntriesException'; + + @override + bool operator ==(Object other) { + return other is NoActiveStakingEntriesException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.g.dart b/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.g.dart new file mode 100644 index 00000000..bf327e85 --- /dev/null +++ b/lib/rearchitecture/features/staking/exceptions/no_active_skaking_entries_exception.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'no_active_skaking_entries_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NoActiveStakingEntriesException _$NoActiveStakingEntriesExceptionFromJson( + Map json) => + NoActiveStakingEntriesException( + message: json['message'] as String? ?? 'No active staking entries', + ); + +Map _$NoActiveStakingEntriesExceptionToJson( + NoActiveStakingEntriesException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/features/staking/staking.dart b/lib/rearchitecture/features/staking/staking.dart new file mode 100644 index 00000000..272c685c --- /dev/null +++ b/lib/rearchitecture/features/staking/staking.dart @@ -0,0 +1,4 @@ +export 'cubit/staking_cubit.dart'; +export 'exceptions/exceptions.dart'; +export 'view/staking_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/staking/view/staking_card.dart b/lib/rearchitecture/features/staking/view/staking_card.dart new file mode 100644 index 00000000..f1c46959 --- /dev/null +++ b/lib/rearchitecture/features/staking/view/staking_card.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget connected to the [StakingCubit] that receives the state +/// - [StakingState] - updates and rebuilds the UI according to the +/// state's status - [TimerStatus]. +class StakingCard extends StatelessWidget { + /// Creates a StakingCard object. + const StakingCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => StakingCubit( + address: Address.parse(kSelectedAddress!), + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.staking.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, StakingState state) { + return switch (state.status) { + TimerStatus.initial => const StakingEmpty(), + TimerStatus.loading => const StakingLoading(), + TimerStatus.failure => StakingError( + error: state.error!, + ), + TimerStatus.success => StakingPopulated( + stakingList: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/staking/widgets/staking_empty.dart b/lib/rearchitecture/features/staking/widgets/staking_empty.dart new file mode 100644 index 00000000..4189d6c6 --- /dev/null +++ b/lib/rearchitecture/features/staking/widgets/staking_empty.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [StakingState] when it's status is +/// [TimerStatus.initial] that uses the [SyriusErrorWidget] to display a +/// message. +class StakingEmpty extends StatelessWidget { + /// Creates a StakingEmpty object. + const StakingEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/staking/widgets/staking_error.dart b/lib/rearchitecture/features/staking/widgets/staking_error.dart new file mode 100644 index 00000000..516d3048 --- /dev/null +++ b/lib/rearchitecture/features/staking/widgets/staking_error.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A widget associated with the [StakingState] when it's status is +/// [TimerStatus.failure] that uses the [SyriusErrorWidget] to display the +/// error. +class StakingError extends StatelessWidget { + /// Creates a StakingError object. + const StakingError({required this.error, super.key}); + + /// Error containing the message that will be displayed. + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/staking/widgets/staking_loading.dart b/lib/rearchitecture/features/staking/widgets/staking_loading.dart new file mode 100644 index 00000000..414883be --- /dev/null +++ b/lib/rearchitecture/features/staking/widgets/staking_loading.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [StakingState] when it's status is +/// [TimerStatus.loading] that uses the [SyriusLoadingWidget] to display a +/// loading indicator. +class StakingLoading extends StatelessWidget { + /// Creates a StakingLoading object. + const StakingLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/staking/widgets/staking_populated.dart b/lib/rearchitecture/features/staking/widgets/staking_populated.dart new file mode 100644 index 00000000..4df94e7e --- /dev/null +++ b/lib/rearchitecture/features/staking/widgets/staking_populated.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_vector_icons/flutter_vector_icons.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// A widget associated with the [StakingState] when it's status is +/// [TimerStatus.success] that displays the number of active staking entries +/// and the total staked amount. +class StakingPopulated extends StatelessWidget { + /// Creates a StakingPopulated object. + const StakingPopulated({required this.stakingList, super.key}); + + /// Field containing the data that will be displayed. + final StakeList stakingList; + + @override + Widget build(BuildContext context) { + final int numActiveStakingEntries = stakingList.list.length; + final BigInt totalStakedAmount = stakingList.totalAmount; + final String totalStakedAmountWithDecimals = totalStakedAmount.addDecimals( + coinDecimals, + ); + + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox.square( + dimension: 36, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: AppColors.znnColor, + ), + ), + child: const Icon( + SimpleLineIcons.energy, + size: 12, + ), + ), + ), + kHorizontalGap16, + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + NumberAnimation( + end: numActiveStakingEntries, + isInt: true, + style: context.textTheme.headlineMedium, + ), + Text( + '$totalStakedAmountWithDecimals ${kZnnCoin.symbol}', + style: context.textTheme.bodyMedium, + ), + ], + ), + ], + ); + } +} diff --git a/lib/rearchitecture/features/staking/widgets/widgets.dart b/lib/rearchitecture/features/staking/widgets/widgets.dart new file mode 100644 index 00000000..74fcab9a --- /dev/null +++ b/lib/rearchitecture/features/staking/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'staking_empty.dart'; +export 'staking_error.dart'; +export 'staking_loading.dart'; +export 'staking_populated.dart'; diff --git a/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.dart b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.dart new file mode 100644 index 00000000..5cade4b3 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.dart @@ -0,0 +1,79 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'total_hourly_transactions_cubit.g.dart'; + +part 'total_hourly_transactions_state.dart'; + +/// [TotalHourlyTransactionsCubit] manages the fetching and state of total +/// hourly transactions. +class TotalHourlyTransactionsCubit + extends TimerCubit { + /// Constructs a [TotalHourlyTransactionsCubit], passing the [zenon] client + /// and the initial state to the parent class. + /// + /// The [zenon] client is used to interact with the Zenon network to retrieve + /// transaction information. + TotalHourlyTransactionsCubit({ + required super.zenon, + super.initialState = const TotalHourlyTransactionsState(), + }); + + /// Fetches the total number of account blocks for the last hour from the + /// Zenon network. + /// + /// This method retrieves the height of the chain, checks if there are enough + /// momentums, and fetches detailed momentums from the Zenon ledger. It + /// calculates then the total number of account blocks + /// + /// Throws: + /// - An error if there are not enough momentums or if any exception occurs + /// during the fetching process. + @override + Future fetch() async { + // Retrieve the current chain height + final int chainHeight = await _ledgerGetMomentumLedgerHeight(); + if (chainHeight - kMomentumsPerHour > 0) { + // Fetch detailed momentums for the past hour + final List response = + (await zenon.ledger.getDetailedMomentumsByHeight( + chainHeight - kMomentumsPerHour, + kMomentumsPerHour, + )) + .list ?? + []; + + // Prepare the transaction summary + final int transactions = response.fold( + 0, + (int previousValue, DetailedMomentum element) => + previousValue + element.blocks.length, + ); + return transactions; // Return the summary of transactions + } else { + throw NotEnoughMomentumsException(); + } + } + + /// Retrieves the current momentum ledger height from the Zenon network. + Future _ledgerGetMomentumLedgerHeight() async { + try { + return (await zenon.ledger.getFrontierMomentum()).height; + } catch (e) { + rethrow; + } + } + + @override + TotalHourlyTransactionsState? fromJson(Map json) => + TotalHourlyTransactionsState.fromJson(json); + + @override + Map? toJson(TotalHourlyTransactionsState state) => + state.toJson(); +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.g.dart b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.g.dart new file mode 100644 index 00000000..62fbd2c5 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_cubit.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'total_hourly_transactions_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +TotalHourlyTransactionsState _$TotalHourlyTransactionsStateFromJson( + Map json) => + TotalHourlyTransactionsState( + status: $enumDecodeNullable(_$TimerStatusEnumMap, json['status']) ?? + TimerStatus.initial, + data: (json['data'] as num?)?.toInt(), + error: json['error'] == null + ? null + : SyriusException.fromJson(json['error'] as Map), + ); + +Map _$TotalHourlyTransactionsStateToJson( + TotalHourlyTransactionsState instance) => + { + 'status': _$TimerStatusEnumMap[instance.status]!, + 'data': instance.data, + 'error': instance.error?.toJson(), + }; + +const _$TimerStatusEnumMap = { + TimerStatus.failure: 'failure', + TimerStatus.initial: 'initial', + TimerStatus.loading: 'loading', + TimerStatus.success: 'success', +}; diff --git a/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_state.dart b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_state.dart new file mode 100644 index 00000000..3a5eb7eb --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/cubit/total_hourly_transactions_state.dart @@ -0,0 +1,38 @@ +part of 'total_hourly_transactions_cubit.dart'; + +/// The state class for [TotalHourlyTransactionsCubit]. It tracks the state of +/// fetching hourly transaction data. +@JsonSerializable(explicitToJson: true) +class TotalHourlyTransactionsState extends TimerState { + /// Constructs a new [TotalHourlyTransactionsState] with optional values for + /// [status], [data], and [error]. + /// + /// The [data] field holds a map containing the transaction statistics for + /// the last hour. + const TotalHourlyTransactionsState({ + super.status, + super.data, + super.error, + }); + + /// {@macro instance_from_json} + factory TotalHourlyTransactionsState.fromJson(Map json) => + _$TotalHourlyTransactionsStateFromJson(json); + + /// {@macro state_copy_with} + @override + TimerState copyWith({ + TimerStatus? status, + int? data, + SyriusException? error, + }) { + return TotalHourlyTransactionsState( + status: status ?? this.status, + data: data ?? this.data, + error: error ?? this.error, + ); + } + + /// {@macro state_to_json} + Map toJson() => _$TotalHourlyTransactionsStateToJson(this); +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/exceptions/exceptions.dart b/lib/rearchitecture/features/total_hourly_transactions/exceptions/exceptions.dart new file mode 100644 index 00000000..d4116f2f --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'not_enough_momentums_exception.dart'; diff --git a/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.dart b/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.dart new file mode 100644 index 00000000..c969474e --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.dart @@ -0,0 +1,35 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; + +part 'not_enough_momentums_exception.g.dart'; + +/// Custom [Exception] to be used with [TotalHourlyTransactionsCubit] when +/// the network is less than one hour old +@immutable +@JsonSerializable() +class NotEnoughMomentumsException extends SyriusException { + /// Creates a [NotEnoughMomentumsException] instance. + NotEnoughMomentumsException({ + String message = 'Not enough momentums', + }) : super(message); + + /// {@macro instance_from_json} + factory NotEnoughMomentumsException.fromJson(Map json) => + _$NotEnoughMomentumsExceptionFromJson(json); + + @override + Map toJson() => _$NotEnoughMomentumsExceptionToJson(this) + ..['runtimeType'] = 'NotEnoughMomentumsException'; + + @override + bool operator ==(Object other) { + return other is NotEnoughMomentumsException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.g.dart b/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.g.dart new file mode 100644 index 00000000..b949dc73 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/exceptions/not_enough_momentums_exception.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'not_enough_momentums_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NotEnoughMomentumsException _$NotEnoughMomentumsExceptionFromJson( + Map json) => + NotEnoughMomentumsException( + message: json['message'] as String? ?? 'Not enough momentums', + ); + +Map _$NotEnoughMomentumsExceptionToJson( + NotEnoughMomentumsException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/features/total_hourly_transactions/total_hourly_transactions.dart b/lib/rearchitecture/features/total_hourly_transactions/total_hourly_transactions.dart new file mode 100644 index 00000000..6e55e599 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/total_hourly_transactions.dart @@ -0,0 +1,4 @@ +export 'cubit/total_hourly_transactions_cubit.dart'; +export 'exceptions/exceptions.dart'; +export 'view/total_hourly_transactions_card.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/features/total_hourly_transactions/view/total_hourly_transactions_card.dart b/lib/rearchitecture/features/total_hourly_transactions/view/total_hourly_transactions_card.dart new file mode 100644 index 00000000..b963ff5c --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/view/total_hourly_transactions_card.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +/// A widget connected to the [TotalHourlyTransactionsCubit] that receives the +/// state - [TotalHourlyTransactionsState] - updates and rebuilds the UI +/// according to the state's status - [TimerStatus]. +class TotalHourlyTransactionsCard extends StatelessWidget { + /// Creates a TotalHourlyTransactionsCard object. + const TotalHourlyTransactionsCard({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => TotalHourlyTransactionsCubit( + zenon: zenon!, + )..fetchDataPeriodically(), + child: NewCardScaffold( + data: CardType.totalHourlyTransactions.getData(context: context), + body: BlocBuilder( + builder: (BuildContext context, TotalHourlyTransactionsState state) { + return switch (state.status) { + TimerStatus.initial => const TotalHourlyTransactionsEmpty(), + TimerStatus.loading => const TotalHourlyTransactionsLoading(), + TimerStatus.failure => TotalHourlyTransactionsError( + error: state.error!, + ), + TimerStatus.success => TotalHourlyTransactionsPopulated( + count: state.data!, + ), + }; + }, + ), + ), + ); + } +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_empty.dart b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_empty.dart new file mode 100644 index 00000000..eeb3a2f5 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_empty.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [TotalHourlyTransactionsState] when it's +/// status is [TimerStatus.initial] that uses the [SyriusErrorWidget] to +/// display a message. +class TotalHourlyTransactionsEmpty extends StatelessWidget { + /// Creates a TotalHourlyTransactionsEmpty object. + const TotalHourlyTransactionsEmpty({super.key}); + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(context.l10n.waitingForDataFetching); + } +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_error.dart b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_error.dart new file mode 100644 index 00000000..dc3b3d7c --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_error.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; + +/// A widget associated with the [TotalHourlyTransactionsState] when it's +/// status is [TimerStatus.failure] that uses the [SyriusErrorWidget] to +/// display the error. +class TotalHourlyTransactionsError extends StatelessWidget { + /// Creates a TotalHourlyTransactionError object. + const TotalHourlyTransactionsError({required this.error, super.key}); + + /// Error containing the message that will be displayed. + final SyriusException error; + + @override + Widget build(BuildContext context) { + return SyriusErrorWidget(error); + } +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_loading.dart b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_loading.dart new file mode 100644 index 00000000..8787f3f5 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_loading.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_widget.dart'; + +/// A widget associated with the [TotalHourlyTransactionsState] when it's +/// status is [TimerStatus.loading] that uses the [SyriusLoadingWidget] to +/// display a loading indicator. +class TotalHourlyTransactionsLoading extends StatelessWidget { + /// Creates a TotalHourlyTransactionsLoading object. + const TotalHourlyTransactionsLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const SyriusLoadingWidget(); + } +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_populated.dart b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_populated.dart new file mode 100644 index 00000000..e07495e1 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/widgets/total_hourly_transactions_populated.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A widget associated with the [TotalHourlyTransactionsState] when it's +/// status is [TimerStatus.success] that displays the number of transactions +/// confirmed in the last one hour. +class TotalHourlyTransactionsPopulated extends StatelessWidget { + /// Creates a TotalHourlyTransactionsPopulated object. + const TotalHourlyTransactionsPopulated({required this.count, super.key}); + + /// The number of confirmed transactions in the last one hour. + final int count; + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + NumberAnimation( + end: count, + isInt: true, + style: context.textTheme.headlineLarge, + ), + kVerticalGap16, + Text(context.l10n.transactionsLastHour), + ], + ); + } +} diff --git a/lib/rearchitecture/features/total_hourly_transactions/widgets/widgets.dart b/lib/rearchitecture/features/total_hourly_transactions/widgets/widgets.dart new file mode 100644 index 00000000..4471a813 --- /dev/null +++ b/lib/rearchitecture/features/total_hourly_transactions/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'total_hourly_transactions_empty.dart'; +export 'total_hourly_transactions_error.dart'; +export 'total_hourly_transactions_loading.dart'; +export 'total_hourly_transactions_populated.dart'; diff --git a/lib/rearchitecture/features/transfer/transfer.dart b/lib/rearchitecture/features/transfer/transfer.dart new file mode 100644 index 00000000..c5de3cf7 --- /dev/null +++ b/lib/rearchitecture/features/transfer/transfer.dart @@ -0,0 +1 @@ +export 'view/transfer_card.dart'; diff --git a/lib/rearchitecture/features/transfer/view/transfer_card.dart b/lib/rearchitecture/features/transfer/view/transfer_card.dart new file mode 100644 index 00000000..6ffa4b2c --- /dev/null +++ b/lib/rearchitecture/features/transfer/view/transfer_card.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_vector_icons/flutter_vector_icons.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A card with two [IconButton] widgets that redirect to the Transfer tab. +class TransferCard extends StatefulWidget { + /// Creates a Transfer object. + const TransferCard({ + super.key, + this.changePage, + }); + + /// Function that triggers the redirect to the Transfer tab. + final Function( + Tabs, { + bool redirectWithSendContainerLarge, + bool redirectWithReceiveContainerLarge, + })? changePage; + + @override + State createState() => _TransferCardState(); +} + +class _TransferCardState extends State { + @override + Widget build(BuildContext context) { + return NewCardScaffold( + data: CardType.transfer.getData(context: context), + body: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton( + onPressed: () { + widget.changePage!( + Tabs.transfer, + redirectWithSendContainerLarge: true, + ); + }, + icon: const Icon( + SimpleLineIcons.arrow_up_circle, + ), + color: AppColors.darkHintTextColor, + iconSize: 48, + ), + TransferIconLegend( + legendText: '● ${context.l10n.send}', + ), + IconButton( + onPressed: () { + widget.changePage!( + Tabs.transfer, + redirectWithReceiveContainerLarge: true, + ); + }, + icon: const Icon( + SimpleLineIcons.arrow_down_circle, + ), + iconSize: 48, + color: AppColors.lightHintTextColor, + ), + TransferIconLegend( + legendText: '● ${context.l10n.receive}', + ), + ], + ), + ); + } +} diff --git a/lib/rearchitecture/rearchitecture.dart b/lib/rearchitecture/rearchitecture.dart new file mode 100644 index 00000000..6b3ea428 --- /dev/null +++ b/lib/rearchitecture/rearchitecture.dart @@ -0,0 +1 @@ +export 'utils/cubits/timer_cubit.dart'; diff --git a/lib/rearchitecture/utils/constants/app_sizes.dart b/lib/rearchitecture/utils/constants/app_sizes.dart new file mode 100644 index 00000000..7772e473 --- /dev/null +++ b/lib/rearchitecture/utils/constants/app_sizes.dart @@ -0,0 +1,10 @@ +import 'package:flutter/widgets.dart'; + +// ignore_for_file: public_member_api_docs +/// Constant vertical gaps +const SizedBox kVerticalGap16 = SizedBox(height: 16); + +/// Constants horizontal gaps +const SizedBox kHorizontalGap4 = SizedBox(width: 4); +const SizedBox kHorizontalGap8 = SizedBox(width: 8); +const SizedBox kHorizontalGap16 = SizedBox(width: 16); diff --git a/lib/rearchitecture/utils/constants/constants.dart b/lib/rearchitecture/utils/constants/constants.dart new file mode 100644 index 00000000..cef4e8b6 --- /dev/null +++ b/lib/rearchitecture/utils/constants/constants.dart @@ -0,0 +1,3 @@ +export 'app_sizes.dart'; +export 'durations.dart'; +export 'strings.dart'; diff --git a/lib/rearchitecture/utils/constants/durations.dart b/lib/rearchitecture/utils/constants/durations.dart new file mode 100644 index 00000000..a8c42a6f --- /dev/null +++ b/lib/rearchitecture/utils/constants/durations.dart @@ -0,0 +1,5 @@ +/// The default interval at which the TimerCubit fetches data +const Duration kTimerCubitRefreshInterval = Duration(minutes: 1); + +/// The interval at which we check the node sync status +const Duration kNodeSyncStatusRefreshInterval = Duration(seconds: 10); diff --git a/lib/rearchitecture/utils/constants/strings.dart b/lib/rearchitecture/utils/constants/strings.dart new file mode 100644 index 00000000..01b7ff78 --- /dev/null +++ b/lib/rearchitecture/utils/constants/strings.dart @@ -0,0 +1,2 @@ +/// The custom URL scheme by which the app can be opened through deep linking +const String kDeepLinkingUrlScheme = 'syrius'; diff --git a/lib/rearchitecture/utils/cubits/cubits.dart b/lib/rearchitecture/utils/cubits/cubits.dart new file mode 100644 index 00000000..bf447e52 --- /dev/null +++ b/lib/rearchitecture/utils/cubits/cubits.dart @@ -0,0 +1,2 @@ +export 'hide_widget/hide_widget.dart'; +export 'timer_cubit.dart'; diff --git a/lib/rearchitecture/utils/cubits/hide_widget/hide_widget.dart b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget.dart new file mode 100644 index 00000000..b0e09964 --- /dev/null +++ b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget.dart @@ -0,0 +1 @@ +export 'hide_widget_cubit.dart'; diff --git a/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.dart b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.dart new file mode 100644 index 00000000..85af2495 --- /dev/null +++ b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.dart @@ -0,0 +1,83 @@ +import 'package:equatable/equatable.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:logging/logging.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'hide_widget_cubit.g.dart'; + +part 'hide_widget_state.dart'; + +/// A cubit that handles saving whether a widget is hidden or not +/// +/// When the user wants to make the widget visible, it checks that the provided +/// wallet password is correct +class HideWidgetCubit extends HydratedCubit { + /// Creates a new instance with an initial state + HideWidgetCubit() : super(const HideWidgetState.initial()); + + @override + HideWidgetState? fromJson(Map json) => + HideWidgetState.fromJson(json); + + /// A method that handles saving the widget as hidden or not + Future saveValue({ + required bool isHidden, + required String widgetTitle, + String? password, + }) async { + emit(state.copyWith(status: HideWidgetStatus.loading)); + try { + if (!isHidden) { + // TODO(maznnwell): use an Isolate + await WalletUtils.decryptWalletFile(kWalletPath!, password!); + } + await _markWidgetAsHidden(widgetTitle, isHidden); + emit( + state.copyWith( + isHidden: isHidden, + status: HideWidgetStatus.success, + ), + ); + } on IncorrectPasswordException catch (e, stackTrace) { + emit( + state.copyWith( + status: HideWidgetStatus.failure, + exception: SyriusException(kIncorrectPasswordNotificationTitle), + ), + ); + addError(kIncorrectPasswordNotificationTitle, stackTrace); + } catch (error, stackTrace) { + emit( + state.copyWith( + status: HideWidgetStatus.failure, + exception: CubitFailureException(), + ), + ); + addError(error, stackTrace); + } + } + + Future _markWidgetAsHidden(String widgetTitle, bool isHidden) async { + await sharedPrefsService!.put( + WidgetUtils.isWidgetHiddenKey(widgetTitle), + isHidden, + ); + } + + @override + Map? toJson(HideWidgetState state) => state.toJson(); + + @override + void onError(Object error, StackTrace stackTrace) { + Logger('HideWidgetCubit').warning( + 'onError triggered', + error, + stackTrace, + ); + super.onError(error, stackTrace); + } +} diff --git a/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.g.dart b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.g.dart new file mode 100644 index 00000000..dd672b18 --- /dev/null +++ b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_cubit.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'hide_widget_cubit.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +HideWidgetState _$HideWidgetStateFromJson(Map json) => + HideWidgetState( + status: $enumDecode(_$HideWidgetStatusEnumMap, json['status']), + exception: json['exception'] == null + ? null + : SyriusException.fromJson(json['exception'] as Map), + isHidden: json['isHidden'] as bool?, + ); + +Map _$HideWidgetStateToJson(HideWidgetState instance) => + { + 'exception': instance.exception, + 'isHidden': instance.isHidden, + 'status': _$HideWidgetStatusEnumMap[instance.status]!, + }; + +const _$HideWidgetStatusEnumMap = { + HideWidgetStatus.failure: 'failure', + HideWidgetStatus.initial: 'initial', + HideWidgetStatus.loading: 'loading', + HideWidgetStatus.success: 'success', +}; diff --git a/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_state.dart b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_state.dart new file mode 100644 index 00000000..7979045c --- /dev/null +++ b/lib/rearchitecture/utils/cubits/hide_widget/hide_widget_state.dart @@ -0,0 +1,61 @@ +part of 'hide_widget_cubit.dart'; + +/// A class that represents the status of hiding a widget +enum HideWidgetStatus { + /// The hiding process has failed + failure, + /// The hiding process has not started + initial, + /// The hiding process is ongoing + loading, + /// The hiding process has succeeded + success, +} + +@JsonSerializable() +/// A class that holds the state emitted by the [HideWidgetCubit] +class HideWidgetState extends Equatable { + /// Creates a new instance. + const HideWidgetState({ + required this.status, + this.exception, + this.isHidden, + }); + + /// Creates a new instance with the [status] of [HideWidgetStatus.initial] + const HideWidgetState.initial() + : this( + status: HideWidgetStatus.initial, + ); + + /// Creates a new instance from a JSON map. + factory HideWidgetState.fromJson(Map json) => + _$HideWidgetStateFromJson(json); + + /// The exception that can be contained by a state emitted when the cubit + /// encounters an error + final SyriusException? exception; + /// A field that tells if a widget should be hidden or not + final bool? isHidden; + /// The current status of hiding or un-hiding a widget + final HideWidgetStatus status; + + @override + List get props => [isHidden, exception, status]; + + /// {@macro state_copy_with} + HideWidgetState copyWith({ + SyriusException? exception, + bool? isHidden, + HideWidgetStatus? status, + }) { + return HideWidgetState( + exception: exception ?? this.exception, + isHidden: isHidden ?? this.isHidden, + status: status ?? this.status, + ); + } + + /// Converts this instance to a JSON map. + Map toJson() => _$HideWidgetStateToJson(this); +} diff --git a/lib/rearchitecture/utils/cubits/timer_cubit.dart b/lib/rearchitecture/utils/cubits/timer_cubit.dart new file mode 100644 index 00000000..3c706e8d --- /dev/null +++ b/lib/rearchitecture/utils/cubits/timer_cubit.dart @@ -0,0 +1,133 @@ +import 'dart:async'; + +import 'package:equatable/equatable.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:logging/logging.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/balance/balance.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +part 'timer_state.dart'; + +/// An abstract class that manages periodic data fetching for a +/// +/// The cubit emits different states based on data loading, +/// success, or failure, and it periodically refreshes the data automatically. +/// +/// The generic type [T] represents the type of data managed by this cubit. +/// +/// The generic type [S] represents the type of the states emitted by the cubit. +/// [S] extends [TimerState] +abstract class TimerCubit> extends HydratedCubit { + /// Constructs a [TimerCubit] with the provided [zenon] client and initial + /// state. + /// + /// The auto-refresh functionality is initialized upon the cubit's creation. + TimerCubit({ + required this.zenon, + required S initialState, + this.refreshInterval = kTimerCubitRefreshInterval, + }) : super(initialState); + + /// A timer that handles the auto-refreshing of data. + Timer? _autoRefresher; + + /// The Zenon client used to fetch data from the Zenon ledger. + final Zenon zenon; + + /// The interval at which to fetch the data again. + final Duration refreshInterval; + + /// Fetches data of type [T] that is managed by the cubit. + /// + /// This method needs to be implemented by subclasses, and it should define + /// the specific data-fetching logic (e.g., fetching account information). + /// + /// It shouldn't be used to emit states + Future fetch(); + + /// Returns a [Timer] that triggers the auto-refresh functionality after + /// the predefined [kTimerCubitRefreshInterval]. + /// + /// This method cancels any existing timers and initiates a new periodic + /// fetch cycle by calling [fetchDataPeriodically]. + Timer _getAutoRefreshTimer() => Timer( + refreshInterval, + () { + _autoRefresher!.cancel(); + fetchDataPeriodically(); + }, + ); + + /// Periodically fetches data and updates the state with either success or + /// failure. + /// + /// This method fetches new data by calling [fetch], emits a loading state + /// while fetching, and updates the state with success or failure based on + /// the outcome. + /// If the WebSocket client is closed, it throws a [noConnectionException]. + Future fetchDataPeriodically() async { + try { + if (state.status != TimerStatus.success) { + emit(state.copyWith(status: TimerStatus.loading) as S); + } + if (!zenon.wsClient.isClosed()) { + final T data = await fetch(); + emit(state.copyWith(data: data, status: TimerStatus.success) as S); + } else { + throw noConnectionException; + } + } on SyriusException catch (e) { + emit(state.copyWith(status: TimerStatus.failure, error: e) as S); + } catch (e, stackTrace) { + emit( + state.copyWith( + status: TimerStatus.failure, + error: CubitFailureException(), + ) as S, + ); + // Reports only the unexpected errors + addError(e, stackTrace); + } finally { + /// Ensure that the auto-refresher is restarted if it's not active. + if (!isTimerActive) { + _startAutoRefresh(); + } + } + } + + /// Starts the auto-refresh cycle by initializing the [_autoRefresher] timer. + void _startAutoRefresh() { + _autoRefresher = _getAutoRefreshTimer(); + } + + /// Checks if a timer was set and if it's active + bool get isTimerActive => _autoRefresher?.isActive ?? false; + + /// Cancels the auto-refresh timer and closes the cubit. + /// + /// This method is called when the cubit is closed, ensuring that no + /// background tasks remain active after the cubit is disposed. + @override + Future close() { + _autoRefresher?.cancel(); + return super.close(); + } + + @override + void onError(Object error, StackTrace stackTrace) { + Level logLevel = Level.WARNING; + if (error is SyriusException) { + logLevel = Level.INFO; + } + // state.runtimeType has the roll to identify in which cubit subclass + // the error happened + Logger('TimerCubit - ${state.runtimeType}').log( + logLevel, + 'onError triggered', + error, + stackTrace, + ); + super.onError(error, stackTrace); + } +} diff --git a/lib/rearchitecture/utils/cubits/timer_state.dart b/lib/rearchitecture/utils/cubits/timer_state.dart new file mode 100644 index 00000000..a30ff429 --- /dev/null +++ b/lib/rearchitecture/utils/cubits/timer_state.dart @@ -0,0 +1,79 @@ +part of 'timer_cubit.dart'; + +/// Represents the various statuses a cubit's request can have. +/// +/// This enum is used to track and emit states with different statuses. +enum TimerStatus { + /// Indicates that the cubit has encountered an error. + failure, + + /// The initial state before any data has been loaded. + initial, + + /// Data is currently being fetched. + loading, + + /// Data has been successfully loaded. + success, +} + +/// An abstract class that defines the common structure for all cubit states +/// +/// The [TimerState] is designed to be generic, with [T] representing the +/// type of data that is managed by each specific cubit state (e.g., balances, +/// transactions, etc.). Subclasses like [BalanceState] extend this class to +/// handle specific data types. +/// +/// The state includes: +/// - [status]: A [TimerStatus] that indicates the current state (loading, +/// success, etc.). +/// - [data]: The data of type [T] that is managed by the cubit. +/// - [error]: An optional [error] object that contains error details if the +/// cubit is in a failure state. +abstract class TimerState extends Equatable { + /// Constructs a [TimerState] with an [status], [data], and + /// [error]. + /// + /// - The [status] defaults to [TimerStatus.initial] if not provided. + /// - The [data] and [error] can be null, indicating that either no data has + /// been fetched yet, or an error has occurred. + const TimerState({ + this.status = TimerStatus.initial, + this.data, + this.error, + }) : assert( + (status == TimerStatus.initial && data == null && error == null) || + (status == TimerStatus.success && data != null) || + (status == TimerStatus.failure && error != null) || + (status == TimerStatus.loading), + 'when status is initial, data and error must be null, ' + 'when status is success, data must be different than null, ' + 'when status is failure, error must be different than null', + ); + + /// Represents the current status of the cubit, such as loading, success, or + /// failure. + final TimerStatus status; + + /// The data of type [T] managed by the cubit, which can be null if no data + /// has been loaded or if there was an error. + final T? data; + + /// An optional error object that holds a message to be presented to the user. + final SyriusException? error; + + /// Creates a copy of the current state with the option to modify specific + /// fields. + /// + /// - [status]: The new status of the cubit (e.g., loading, success). + /// - [data]: The new data of type [T], if it has changed. + /// - [error]: The new error, if any occurred. + TimerState copyWith({ + TimerStatus? status, + T? data, + SyriusException? error, + }); + + @override + List get props => [status, data, error]; +} diff --git a/lib/rearchitecture/utils/exceptions/cubit_failure_exception.dart b/lib/rearchitecture/utils/exceptions/cubit_failure_exception.dart new file mode 100644 index 00000000..cb8abecf --- /dev/null +++ b/lib/rearchitecture/utils/exceptions/cubit_failure_exception.dart @@ -0,0 +1,34 @@ +import 'package:flutter/cupertino.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; + +part 'cubit_failure_exception.g.dart'; + +/// A class to be used as a generic exception when something unexpected goes +/// wrong inside a cubit. +@immutable +@JsonSerializable() +class CubitFailureException extends SyriusException { + /// Creates a [CubitFailureException] instance. + CubitFailureException({ + String message = 'Something went wrong', + }) : super(message); + + /// {@macro instance_from_json} + factory CubitFailureException.fromJson(Map json) => + _$CubitFailureExceptionFromJson(json); + + @override + Map toJson() => _$CubitFailureExceptionToJson(this) + ..['runtimeType'] = 'CubitFailureException'; + + @override + bool operator ==(Object other) { + return other is CubitFailureException && + other.runtimeType == runtimeType && + other.message == message; + } + + @override + int get hashCode => message.hashCode; +} diff --git a/lib/rearchitecture/utils/exceptions/cubit_failure_exception.g.dart b/lib/rearchitecture/utils/exceptions/cubit_failure_exception.g.dart new file mode 100644 index 00000000..8ec429b3 --- /dev/null +++ b/lib/rearchitecture/utils/exceptions/cubit_failure_exception.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'cubit_failure_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +CubitFailureException _$CubitFailureExceptionFromJson( + Map json) => + CubitFailureException( + message: json['message'] as String? ?? 'Something went wrong', + ); + +Map _$CubitFailureExceptionToJson( + CubitFailureException instance) => + { + 'message': instance.message, + }; diff --git a/lib/rearchitecture/utils/exceptions/exceptions.dart b/lib/rearchitecture/utils/exceptions/exceptions.dart new file mode 100644 index 00000000..f99c26b0 --- /dev/null +++ b/lib/rearchitecture/utils/exceptions/exceptions.dart @@ -0,0 +1,2 @@ +export 'cubit_failure_exception.dart'; +export 'syrius_exception.dart'; diff --git a/lib/rearchitecture/utils/exceptions/syrius_exception.dart b/lib/rearchitecture/utils/exceptions/syrius_exception.dart new file mode 100644 index 00000000..1d789b5d --- /dev/null +++ b/lib/rearchitecture/utils/exceptions/syrius_exception.dart @@ -0,0 +1,49 @@ +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; + +/// A custom exception that displays only the message when printed. +class SyriusException implements Exception { + /// Creates a [SyriusException] with a required message. + SyriusException(this.message); + + /// Factory constructor for creating a new instance from a map. + /// + /// The classes that extend from [SyriusException] should also add to the + /// [Map] generated by the [toJson] method a key - 'runtimeType' - with the + /// name of the class as a value. This is needed for serialization and + /// deserialization; in the case of [TimerState], instead of using the + /// concrete child classes, like [NoActiveStakingEntriesException], the + /// parent [SyriusException] is used as a type for the error inside the state + factory SyriusException.fromJson(Map json) { + final String? type = json['runtimeType'] as String?; + if (type != null) { + switch (type) { + case 'NoActiveStakingEntriesException': + return NoActiveStakingEntriesException.fromJson(json); + case 'NoBalanceException': + return NoBalanceException.fromJson(json); + case 'NoBlocksAvailableException': + return NoBlocksAvailableException.fromJson(json); + case 'CubitFailureException': + return CubitFailureException.fromJson(json); + case 'NoDelegationStatsException': + return NoDelegationStatsException.fromJson(json); + case 'NotEnoughMomentumsException': + return NotEnoughMomentumsException.fromJson(json); + default: + throw UnsupportedError('Unknown subclass: $type'); + } + } + return SyriusException(json['message'] as String); + } + /// The exception message + final String message; + + /// Returns the exception message without the 'Exception:' prefix. + @override + String toString() => message; + + /// Method to convert the object into a map. + Map toJson() => {'message': message}; +} diff --git a/lib/rearchitecture/utils/extensions/buildcontext_extension.dart b/lib/rearchitecture/utils/extensions/buildcontext_extension.dart new file mode 100644 index 00000000..186bf3ce --- /dev/null +++ b/lib/rearchitecture/utils/extensions/buildcontext_extension.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +/// Extension on the [BuildContext] class +extension BuildContextExtension on BuildContext { + /// Getter method for easier access to the [AppLocalizations] instance + AppLocalizations get l10n => AppLocalizations.of(this)!; + + /// Returns the current ThemeData + ThemeData get themeData => Theme.of(this); + + /// Returns the current TextTheme + TextTheme get textTheme => themeData.textTheme; + + /// Whether the app is currently in dark mode + bool get isDarkMode => Theme.of(this).brightness == Brightness.dark; +} diff --git a/lib/rearchitecture/utils/extensions/extensions.dart b/lib/rearchitecture/utils/extensions/extensions.dart new file mode 100644 index 00000000..97e02ab1 --- /dev/null +++ b/lib/rearchitecture/utils/extensions/extensions.dart @@ -0,0 +1,2 @@ +export 'buildcontext_extension.dart'; +export 'sync_state_extension.dart'; diff --git a/lib/rearchitecture/utils/extensions/sync_state_extension.dart b/lib/rearchitecture/utils/extensions/sync_state_extension.dart new file mode 100644 index 00000000..c05f9cbf --- /dev/null +++ b/lib/rearchitecture/utils/extensions/sync_state_extension.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +/// Extension on the [SyncState] class +extension SyncStateExtension on SyncState { + /// Returns a color, depending on the enum value + Color? getColor({required BuildContext context}) { + return switch (this) { + SyncState.unknown => Theme.of(context).iconTheme.color, + SyncState.syncing => Colors.orange, + SyncState.syncDone => AppColors.znnColor, + SyncState.notEnoughPeers => AppColors.errorColor, + }; + } +} diff --git a/lib/rearchitecture/utils/models/card/card.dart b/lib/rearchitecture/utils/models/card/card.dart new file mode 100644 index 00000000..46ee2832 --- /dev/null +++ b/lib/rearchitecture/utils/models/card/card.dart @@ -0,0 +1,2 @@ +export 'card_data.dart'; +export 'card_type.dart'; diff --git a/lib/rearchitecture/utils/models/card/card_data.dart b/lib/rearchitecture/utils/models/card/card_data.dart new file mode 100644 index 00000000..e4b9f8ed --- /dev/null +++ b/lib/rearchitecture/utils/models/card/card_data.dart @@ -0,0 +1,12 @@ +/// A class that holds data needed in a card, like the [description] and the +/// [title] +class CardData { + /// Creates a [CardData] instance. + CardData({required this.description, required this.title}); + + /// The description of a card. + final String description; + + /// The title of a card. + final String title; +} diff --git a/lib/rearchitecture/utils/models/card/card_type.dart b/lib/rearchitecture/utils/models/card/card_type.dart new file mode 100644 index 00000000..b31d182c --- /dev/null +++ b/lib/rearchitecture/utils/models/card/card_type.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; + +/// A class that helps distinguish between the card widgets +enum CardType { + /// A type for a card displaying information related to balance + balance, + + /// A type for a card displaying information related to delegation + delegationStats, + + /// A type for a card displaying information related to ZNN and QSR + dualCoinStats, + + /// A type for a card displaying information related to pillars + pillars, + + /// A type for a card displaying information in realtime + realtimeStatistics, + + /// A type for a card displaying information related to sentinels + sentinels, + + /// A type for a card displaying information related to staking + staking, + + /// A type for a card displaying information related to transactions + /// confirmed in the last hour + totalHourlyTransactions, + + /// A type for a card that redirects to the Transfer tab + transfer; + + /// Returns the [CardData] assigned to a specific [CardType] value. + /// + /// The parameter [context] is used to retrieve the localized strings + CardData getData({ + required BuildContext context, + }) { + return switch (this) { + CardType.balance => CardData( + title: context.l10n.balance, + description: context.l10n.currentAmounts( + kQsrCoin.symbol, + kZnnCoin.symbol, + ), + ), + CardType.delegationStats => CardData( + title: context.l10n.delegationStats, + description: context.l10n.delegationStatsDescription(kZnnCoin.symbol), + ), + CardType.dualCoinStats => CardData( + title: context.l10n.dualCoinStats, + description: context.l10n.dualCoinStatsDescription( + kQsrCoin.symbol, + kZnnCoin.symbol, + ), + ), + CardType.pillars => CardData( + title: context.l10n.pillars, + description: context.l10n.pillarsDescription, + ), + CardType.realtimeStatistics => CardData( + title: context.l10n.realtimeStats, + description: context.l10n + .realtimeStatsDescription(kQsrCoin.symbol, kZnnCoin.symbol), + ), + CardType.sentinels => CardData( + title: context.l10n.sentinels, + description: context.l10n.sentinelsDescription, + ), + CardType.staking => CardData( + description: context.l10n.stakingStatsDescription(kZnnCoin.symbol), + title: context.l10n.stakingStats, + ), + CardType.totalHourlyTransactions => CardData( + description: context.l10n.transactionsDescription, + title: context.l10n.transactions, + ), + CardType.transfer => CardData( + description: context.l10n.transferDescription, + title: context.l10n.transfer, + ), + }; + } +} diff --git a/lib/rearchitecture/utils/models/models.dart b/lib/rearchitecture/utils/models/models.dart new file mode 100644 index 00000000..1cd32ceb --- /dev/null +++ b/lib/rearchitecture/utils/models/models.dart @@ -0,0 +1 @@ +export 'card/card.dart'; diff --git a/lib/rearchitecture/utils/theming/new_app_themes.dart b/lib/rearchitecture/utils/theming/new_app_themes.dart new file mode 100644 index 00000000..e3e51570 --- /dev/null +++ b/lib/rearchitecture/utils/theming/new_app_themes.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; + +/// The new light theme closer to the default Material ThemeData +final ThemeData newLightTheme = ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: AppColors.znnColor, + ), + dividerTheme: kDefaultDividerThemeData, + inputDecorationTheme: InputDecorationTheme( + fillColor: AppColors.lightTextFormFieldFill, + filled: true, + errorStyle: kTextFormFieldErrorStyle, + hintStyle: kHintTextStyle.copyWith( + color: AppColors.lightHintTextColor, + ), + enabledBorder: kOutlineInputBorder.copyWith( + borderSide: BorderSide.none, + ), + disabledBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide(color: AppColors.inactiveIconsGray), + ), + focusedBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide(color: AppColors.inactiveIconsGray), + ), + errorBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide( + color: AppColors.errorColor, + width: 2, + ), + ), + focusedErrorBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide( + color: AppColors.errorColor, + width: 2, + ), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + side: const BorderSide( + color: AppColors.znnColor, + ), + ), + ), +); + +/// The new dark theme closer to the default Material ThemeData +final ThemeData newDarkTheme = ThemeData( + brightness: Brightness.dark, + colorScheme: ColorScheme.fromSeed( + brightness: Brightness.dark, + seedColor: AppColors.znnColor, + ), + dividerTheme: kDefaultDividerThemeData, + inputDecorationTheme: InputDecorationTheme( + fillColor: AppColors.darkTextFormFieldFill, + filled: true, + errorStyle: kTextFormFieldErrorStyle, + hintStyle: kHintTextStyle.copyWith( + color: AppColors.darkHintTextColor, + ), + enabledBorder: kOutlineInputBorder.copyWith( + borderSide: BorderSide.none, + ), + disabledBorder: kOutlineInputBorder.copyWith( + borderSide: BorderSide( + color: Colors.white.withOpacity(0.1), + ), + ), + focusedBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide(color: AppColors.znnColor), + ), + errorBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide( + color: AppColors.errorColor, + width: 2, + ), + ), + focusedErrorBorder: kOutlineInputBorder.copyWith( + borderSide: const BorderSide( + color: AppColors.errorColor, + width: 2, + ), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + side: const BorderSide( + color: AppColors.znnColor, + ), + ), + ), +); diff --git a/lib/rearchitecture/utils/url_protocol/api.dart b/lib/rearchitecture/utils/url_protocol/api.dart new file mode 100644 index 00000000..6f79793d --- /dev/null +++ b/lib/rearchitecture/utils/url_protocol/api.dart @@ -0,0 +1,52 @@ +import 'dart:io'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter/foundation.dart'; +import 'package:win32/win32.dart'; + +part 'protocol.dart'; +part 'windows_protocol.dart'; + +/// Implementation copied from the example app_links project: +/// +/// https://github.com/llfbandit/app_links/tree/master/app_links/example/lib + +/// Registers a protocol by [scheme] to allow for links in the form `://...` +/// to be processed by this application. By default, opening a link will open +/// the executable that was used to register the scheme with the URL as the first +/// argument passed to the executable. +/// +/// If a protocol is already registered for the given scheme, this function will +/// attempt to overwrite the previous handler with the current executable information. +/// However, note that depending on process permissions, this operation may be +/// disallowed by the underlying platform. +/// +/// You may pass an [executable] to override the path to the executable to run +/// when accessing the URL. +/// +/// [arguments] is a list of arguments to be used when running the executable. +/// If passed, the list must contain at least one element, and at least one of +/// those elements must contain the literal value `%s` to denote the URL to open. +/// Quoting arguments is not necessary, as this will be handled for you. +/// Escaping the `%s` as an unprocessed literal is currently unsupported. +void registerProtocolHandler( + String scheme, { + String? executable, + List? arguments, +}) { + WindowsProtocolHandler().register( + scheme, + executable: executable, + arguments: arguments, + ); +} + +/// Unregisters the protocol handler with the underlying platform. The provided +/// [scheme] will no longer be used in links. +/// +/// Note that this will unregister a protocol by scheme regardless of which process +/// had registered it. Unregistering a scheme that was not registered by this +/// application is undefined and depends on platform-specific restrictions. +void unregisterProtocolHandler(String scheme) { + WindowsProtocolHandler().unregister(scheme); +} diff --git a/lib/rearchitecture/utils/url_protocol/protocol.dart b/lib/rearchitecture/utils/url_protocol/protocol.dart new file mode 100644 index 00000000..aa7575d3 --- /dev/null +++ b/lib/rearchitecture/utils/url_protocol/protocol.dart @@ -0,0 +1,20 @@ +part of 'api.dart'; + +/// An abstract calls that helps manage a custom URL scheme used to open the +/// app +abstract class ProtocolHandler { + /// Registers the scheme. + void register(String scheme, {String? executable, List? arguments}); + /// Unregisters the scheme. + void unregister(String scheme); + /// Gets arguments from the scheme. + List getArguments(List? arguments) { + if (arguments == null) return ['%s']; + + if (arguments.isEmpty && !arguments.any((e) => e.contains('%s'))) { + throw ArgumentError('arguments must contain at least 1 instance of "%s"'); + } + + return arguments; + } +} diff --git a/lib/rearchitecture/utils/url_protocol/windows_protocol.dart b/lib/rearchitecture/utils/url_protocol/windows_protocol.dart new file mode 100644 index 00000000..c0fa9764 --- /dev/null +++ b/lib/rearchitecture/utils/url_protocol/windows_protocol.dart @@ -0,0 +1,70 @@ +part of 'api.dart'; + +const int _hive = HKEY_CURRENT_USER; + +/// An Windows implementation of [ProtocolHandler] that helps creating a custom +/// URL scheme which can open the app through deep linking +/// +/// The wallet can be opened through a link like `syrius://...`. It's currently +/// used by the bridge (`https://bridge.mainnet.zenon.community/`) to open the +/// app and send an WalletConnect URI +class WindowsProtocolHandler extends ProtocolHandler { + @override + void register(String scheme, {String? executable, List? arguments}) { + if (defaultTargetPlatform != TargetPlatform.windows) return; + + final String prefix = _regPrefix(scheme); + final String capitalized = scheme[0].toUpperCase() + scheme.substring(1); + final Iterable args = getArguments(arguments).map( + _sanitize, + ); + final String cmd = + '${executable ?? Platform.resolvedExecutable} ${args.join(' ')}'; + + _regCreateStringKey(_hive, prefix, '', 'URL:$capitalized'); + _regCreateStringKey(_hive, prefix, 'URL Protocol', ''); + _regCreateStringKey(_hive, '$prefix\\shell\\open\\command', '', cmd); + } + + @override + void unregister(String scheme) { + if (defaultTargetPlatform != TargetPlatform.windows) return; + + final LPWSTR txtKey = TEXT(_regPrefix(scheme)); + try { + RegDeleteTree(HKEY_CURRENT_USER, txtKey); + } finally { + free(txtKey); + } + } + + String _regPrefix(String scheme) => 'SOFTWARE\\Classes\\$scheme'; + + int _regCreateStringKey(int hKey, String key, String valueName, String data) { + final LPWSTR txtKey = TEXT(key); + final LPWSTR txtValue = TEXT(valueName); + final LPWSTR txtData = TEXT(data); + try { + return RegSetKeyValue( + hKey, + txtKey, + txtValue, + REG_VALUE_TYPE.REG_SZ, + txtData, + txtData.length * 2 + 2, + ); + } finally { + free(txtKey); + free(txtValue); + free(txtData); + } + } + + String _sanitize(String value) { + final String finalValue = value.replaceAll('%s', '%1').replaceAll( + '"', + r'\"', + ); + return '"$finalValue"'; + } +} diff --git a/lib/rearchitecture/utils/utils.dart b/lib/rearchitecture/utils/utils.dart new file mode 100644 index 00000000..47022aff --- /dev/null +++ b/lib/rearchitecture/utils/utils.dart @@ -0,0 +1,7 @@ +export 'constants/constants.dart'; +export 'cubits/cubits.dart'; +export 'exceptions/exceptions.dart'; +export 'extensions/extensions.dart'; +export 'models/models.dart'; +export 'url_protocol/api.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/rearchitecture/utils/widgets/card_scaffold_header.dart b/lib/rearchitecture/utils/widgets/card_scaffold_header.dart new file mode 100644 index 00000000..5ec17569 --- /dev/null +++ b/lib/rearchitecture/utils/widgets/card_scaffold_header.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/constants/constants.dart'; + +/// A widget showing a [title] along with some icon buttons +class CardScaffoldHeader extends StatelessWidget { + /// Creates a new instance. + const CardScaffoldHeader({ + required this.onMoreIconPressed, + required this.onRefreshPressed, + required this.title, + super.key, + }); + + /// Title that will appear in the header. + final String title; + /// Callback triggered when the more icon is pressed. + final VoidCallback onMoreIconPressed; + /// Optional callback that can be trigger from the refresh icon. + final VoidCallback? onRefreshPressed; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(14), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + kHorizontalGap4, + ], + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Visibility( + visible: onRefreshPressed != null, + child: IconButton( + icon: const Icon(Icons.refresh), + onPressed: onRefreshPressed, + ), + ), + IconButton( + icon: const Icon(Icons.more_horiz), + onPressed: onMoreIconPressed, + ), + ], + ), + ], + ); + } +} diff --git a/lib/rearchitecture/utils/widgets/card_scaffold_password_field.dart b/lib/rearchitecture/utils/widgets/card_scaffold_password_field.dart new file mode 100644 index 00000000..7b99ecfa --- /dev/null +++ b/lib/rearchitecture/utils/widgets/card_scaffold_password_field.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; + +/// A TextField for entering the wallet password +class CardScaffoldPasswordField extends StatelessWidget { + /// Creates a new instance. + const CardScaffoldPasswordField({ + required this.controller, + required this.obscureText, + required this.onSuffixIconPressed, + required this.onSubmitted, + this.errorText, + super.key, + }); + + /// Controller that holds the inputted text + final TextEditingController controller; + /// Text that will appear under the text field, if it's not null + final String? errorText; + /// Callback triggered when input is submitted + final void Function(String) onSubmitted; + /// Whether or not to obscure the password + final bool obscureText; + /// Callback triggered when the suffix icon is pressed + final VoidCallback onSuffixIconPressed; + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + obscureText: obscureText, + decoration: InputDecoration( + errorText: errorText, + hintText: context.l10n.password, + suffixIcon: IconButton( + onPressed: onSuffixIconPressed, + icon: Icon( + obscureText + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + color: AppColors.znnColor, + ), + ), + ), + onSubmitted: onSubmitted, + ); + } +} diff --git a/lib/rearchitecture/utils/widgets/new_card_scaffold.dart b/lib/rearchitecture/utils/widgets/new_card_scaffold.dart new file mode 100644 index 00000000..a270062a --- /dev/null +++ b/lib/rearchitecture/utils/widgets/new_card_scaffold.dart @@ -0,0 +1,315 @@ +import 'dart:async'; + +import 'package:expandable/expandable.dart'; +import 'package:flip_card/flip_card.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_vector_icons/flutter_vector_icons.dart'; +import 'package:lottie/lottie.dart'; +import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/theming/new_app_themes.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/widgets/card_scaffold_header.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/widgets/card_scaffold_password_field.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// A scaffold for the standard card used across the app +/// +/// It comes with a lot of predefined styling and features +/// +/// On the front, it display a title, contained by [data], a [body], the main +/// front widget, an [IconButton] to flip the card and, if [onRefreshPressed] +/// is not null, an [IconButton] to trigger a callback +/// On the back, it display a description, contained by [data], a [Switch] to +/// hide the [body] and - if the widget is already hidden - an +/// [PasswordInputField] to input the wallet password and make the [body] +/// visible again +class NewCardScaffold extends StatefulWidget { + /// Creates a [NewCardScaffold] instance. + const NewCardScaffold({ + required this.body, + required this.data, + this.onRefreshPressed, + super.key, + }); + + /// Widget that will appear on the front of the card + final Widget body; + + /// Data needed for certain UI parts of the card + final CardData data; + + /// Optional callback that can be trigger from the card + final VoidCallback? onRefreshPressed; + + @override + State createState() => _NewCardScaffoldState(); +} + +class _NewCardScaffoldState extends State { + GlobalKey cardKey = GlobalKey(); + final GlobalKey _actionButtonKey = GlobalKey(); + + final TextEditingController _passwordController = TextEditingController(); + + bool _showPasswordInputField = false; + + SyriusException? _error; + + late LoadingButton _actionButton; + + String get _title => widget.data.title; + + String get _description => widget.data.description; + + final ValueNotifier _obscureTextNotifier = ValueNotifier(true); + + @override + Widget build(BuildContext context) { + final Widget header = CardScaffoldHeader( + onMoreIconPressed: () { + cardKey.currentState!.toggleCard(); + }, + onRefreshPressed: widget.onRefreshPressed, + title: _title, + ); + + final Widget front = + _isFrontWidgetHidden(_title) ? _getHiddenInfoWidget() : widget.body; + + final Color background = + context.isDarkMode ? AppColors.darkPrimary : Colors.white; + + final ThemeData themeData = + context.isDarkMode ? newDarkTheme : newLightTheme; + + return Theme( + data: themeData, + child: Builder( + builder: (BuildContext context) { + return FlipCard( + flipOnTouch: false, + key: cardKey, + onFlipDone: (bool status) {}, + front: ClipRRect( + borderRadius: BorderRadius.circular( + 15, + ), + child: ColoredBox( + color: background, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + header, + const Divider(), + Expanded( + child: front, + ), + ], + ), + ), + ), + back: ClipRRect( + borderRadius: BorderRadius.circular( + 15, + ), + child: ColoredBox( + color: background, + child: Column( + children: [ + header, + const Divider(), + Expanded( + child: _getHideWidgetInfoViewModel(), + ), + ], + ), + ), + ), + ); + }, + ), + ); + } + + Widget _getBackBody() { + return Builder( + builder: (BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8), + child: ListView( + shrinkWrap: true, + children: [ + ExpandablePanel( + collapsed: const SizedBox.shrink(), + theme: ExpandableThemeData( + iconColor: context.themeData.iconTheme.color, + iconPlacement: ExpandablePanelIconPlacement.right, + headerAlignment: ExpandablePanelHeaderAlignment.center, + ), + header: Row( + children: [ + const Icon( + Icons.info, + color: AppColors.znnColor, + ), + kHorizontalGap4, + Expanded( + child: Text( + 'Description', + style: context.themeData.textTheme.titleSmall, + ), + ), + ], + ), + expanded: Padding( + padding: const EdgeInsets.all(8), + child: Text( + _description, + style: context.themeData.textTheme.bodyMedium, + ), + ), + ), + Row( + children: [ + const Icon( + Icons.remove_red_eye_rounded, + color: AppColors.znnColor, + ), + kHorizontalGap4, + Expanded( + child: Text( + 'Discreet mode', + style: context.themeData.textTheme.titleSmall, + ), + ), + const Spacer(), + Switch( + value: _isFrontWidgetHidden(_title), + onChanged: (bool shouldHideFrontWidget) { + if (shouldHideFrontWidget) { + context.read().saveValue( + isHidden: shouldHideFrontWidget, + widgetTitle: _title, + ); + } else { + // To make the front widget visible, the user needs to + // confirm the action with it's wallet password + setState(() { + _showPasswordInputField = true; + }); + } + }, + ), + ], + ), + Visibility( + visible: _showPasswordInputField, + child: Row( + children: [ + Expanded( + child: ValueListenableBuilder( + valueListenable: _obscureTextNotifier, + builder: (_, bool obscureText, __) { + return CardScaffoldPasswordField( + controller: _passwordController, + errorText: _error?.toString(), + onSubmitted: (String value) { + _actionButton.onPressed!(); + }, + obscureText: obscureText, + onSuffixIconPressed: () { + _obscureTextNotifier.value = !obscureText; + }, + ); + }, + ), + ), + kHorizontalGap8, + _actionButton, + ], + ), + ), + ], + ), + ); + }, + ); + } + + Widget _getHideWidgetInfoViewModel() { + return BlocProvider( + create: (_) { + final HideWidgetCubit cubit = HideWidgetCubit(); + + _actionButton = LoadingButton.icon( + onPressed: () => _onActionButtonPressed(cubit: cubit), + key: _actionButtonKey, + icon: const Icon( + AntDesign.arrowright, + color: AppColors.znnColor, + size: 25, + ), + ); + + return cubit; + }, + child: BlocListener( + listener: (BuildContext context, HideWidgetState state) { + final HideWidgetStatus status = state.status; + switch (status) { + case HideWidgetStatus.failure: + _actionButtonKey.currentState?.animateReverse(); + setState(() { + _error = state.exception; + }); + case HideWidgetStatus.initial: + break; + case HideWidgetStatus.loading: + _actionButtonKey.currentState?.animateForward(); + case HideWidgetStatus.success: + _actionButtonKey.currentState?.animateReverse(); + _passwordController.clear(); + if (!state.isHidden!) { + _showPasswordInputField = false; + } + _error = null; + setState(() {}); + } + }, + child: _getBackBody(), + ), + ); + } + + Widget _getHiddenInfoWidget() { + return Lottie.asset('assets/lottie/ic_anim_eye.json'); + } + + bool _isFrontWidgetHidden(String title) { + return sharedPrefsService!.get( + WidgetUtils.isWidgetHiddenKey(title), + defaultValue: false, + ); + } + + Future _onActionButtonPressed({required HideWidgetCubit cubit}) async { + if (_passwordController.text.isNotEmpty && + _actionButtonKey.currentState!.btnState == ButtonState.idle) { + unawaited( + cubit.saveValue( + isHidden: false, + password: _passwordController.text, + widgetTitle: _title, + ), + ); + } + } + + @override + void dispose() { + _passwordController.dispose(); + super.dispose(); + } +} diff --git a/lib/rearchitecture/utils/widgets/widgets.dart b/lib/rearchitecture/utils/widgets/widgets.dart new file mode 100644 index 00000000..0a687079 --- /dev/null +++ b/lib/rearchitecture/utils/widgets/widgets.dart @@ -0,0 +1 @@ +export 'new_card_scaffold.dart'; diff --git a/lib/screens/change_wallet_password_screen.dart b/lib/screens/change_wallet_password_screen.dart index 6c382423..24987153 100644 --- a/lib/screens/change_wallet_password_screen.dart +++ b/lib/screens/change_wallet_password_screen.dart @@ -5,16 +5,17 @@ import 'package:stacked/stacked.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/decrypt_wallet_file_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/services/htlc_swaps_service.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ChangeWalletPasswordScreen extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const ChangeWalletPasswordScreen({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => @@ -43,7 +44,7 @@ class _ChangeWalletPasswordScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -56,7 +57,7 @@ class _ChangeWalletPasswordScreenState style: Theme.of(context).textTheme.headlineLarge, ), Column( - children: [ + children: [ Form( key: _currentPasswordKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -64,7 +65,7 @@ class _ChangeWalletPasswordScreenState errorText: _currentPassErrorText, controller: _currentPasswordController, hintText: 'Current password', - onChanged: (value) { + onChanged: (String value) { setState(() { if (_currentPassErrorText != null) { _currentPassErrorText = null; @@ -80,7 +81,7 @@ class _ChangeWalletPasswordScreenState child: PasswordInputField( controller: _newPasswordController, validator: InputValidators.validatePassword, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, hintText: 'New password', @@ -92,23 +93,23 @@ class _ChangeWalletPasswordScreenState autovalidateMode: AutovalidateMode.onUserInteraction, child: PasswordInputField( controller: _confirmPasswordController, - validator: (value) => InputValidators.checkPasswordMatch( + validator: (String? value) => InputValidators.checkPasswordMatch( _newPasswordController.text, value, ), hintText: 'Repeat new password', - onSubmitted: (value) { + onSubmitted: (String value) { if (_arePasswordsValid()) { _loadingButton.onPressed!(); } }, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), ), const SizedBox( - height: 35.0, + height: 35, ), PasswordProgressBar( password: _newPasswordController.text, @@ -148,7 +149,7 @@ class _ChangeWalletPasswordScreenState String currentPassword, String newPassword, ) async { - final baseAddress = WalletUtils.baseAddress; + final Address baseAddress = WalletUtils.baseAddress; await kWalletFile!.changePassword(currentPassword, newPassword); await HtlcSwapsService.getInstance().closeBoxes(); await HtlcSwapsService.getInstance().openBoxes( @@ -172,8 +173,8 @@ class _ChangeWalletPasswordScreenState Widget _getDecryptKeyStoreFileViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { - model.stream.listen((walletFile) async { + onViewModelReady: (DecryptWalletFileBloc model) { + model.stream.listen((WalletFile? walletFile) async { if (walletFile != null) { setState(() { _currentPassErrorText = null; @@ -204,13 +205,13 @@ class _ChangeWalletPasswordScreenState 'An error occurred while trying to decrypt wallet', ); } - }); + },); }, - builder: (_, model, __) { + builder: (_, DecryptWalletFileBloc model, __) { _loadingButton = _getLoadingButton(model); return _getLoadingButton(model); }, - viewModelBuilder: () => DecryptWalletFileBloc(), + viewModelBuilder: DecryptWalletFileBloc.new, ); } @@ -221,7 +222,7 @@ class _ChangeWalletPasswordScreenState ? () { _loadingButtonKey.currentState!.animateForward(); model.decryptWalletFile( - kWalletPath!, _currentPasswordController.text); + kWalletPath!, _currentPasswordController.text,); } : null, text: 'Change password', diff --git a/lib/screens/development_intialization_screen.dart b/lib/screens/development_intialization_screen.dart new file mode 100644 index 00000000..250415d0 --- /dev/null +++ b/lib/screens/development_intialization_screen.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/screens/screens.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; + +/// This will be used to quickly initialize the app when testing in the +/// development phase + +class DevelopmentInitializationScreen extends StatefulWidget { + + const DevelopmentInitializationScreen({super.key}); + static const String route = 'development-initialization-screen'; + + @override + State createState() => + _DevelopmentInitializationScreenState(); +} + +class _DevelopmentInitializationScreenState + extends State { + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _checkIfWalletPathIsNull(context: context), + builder: (_, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + final bool isWalletPathNull = snapshot.data!; + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (isWalletPathNull) { + _navigateToAccessWalletScreen(context: context); + } else { + _navigateToHomeScreen(context: context); + } + }); + + return const SizedBox.shrink(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } + + return const Center(child: CircularProgressIndicator()); + }, + ); + } + + Future _checkIfWalletPathIsNull({required BuildContext context}) async { + try { + await InitUtils.initApp(context); + return kWalletPath == null; + } on Exception catch (_) { + rethrow; + } + } + + void _navigateToHomeScreen({required BuildContext context}) { + Navigator.of( + context, + rootNavigator: true, + ).pushReplacementNamed(MainAppContainer.route); + } + + void _navigateToAccessWalletScreen({required BuildContext context}) { + Navigator.pushReplacementNamed( + context, + AccessWalletScreen.route, + ); + } +} diff --git a/lib/screens/dump_mnemonic_screen.dart b/lib/screens/dump_mnemonic_screen.dart index c1b3fc04..bd7a4f38 100644 --- a/lib/screens/dump_mnemonic_screen.dart +++ b/lib/screens/dump_mnemonic_screen.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class DumpMnemonicScreen extends StatefulWidget { - const DumpMnemonicScreen({Key? key}) : super(key: key); + const DumpMnemonicScreen({super.key}); @override State createState() => _DumpMnemonicScreenState(); @@ -27,7 +28,7 @@ class _DumpMnemonicScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -44,10 +45,10 @@ class _DumpMnemonicScreenState extends State { child: PasswordInputField( controller: _passwordController, hintText: 'Current password', - onSubmitted: (value) { + onSubmitted: (String value) { _continueButton!.onPressed!(); }, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, errorText: _passwordError, @@ -65,12 +66,12 @@ class _DumpMnemonicScreenState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ _getLockButton(), Visibility( visible: _seedWords == null, child: Row( - children: [ + children: [ kSpacingBetweenActionButtons, _continueButton!, ], @@ -103,11 +104,11 @@ class _DumpMnemonicScreenState extends State { if (_passwordController.text.isNotEmpty) { try { _continueButtonKey.currentState!.animateForward(); - var walletFile = await WalletUtils.decryptWalletFile( + final WalletFile walletFile = await WalletUtils.decryptWalletFile( kWalletPath!, _passwordController.text, ); - walletFile.open().then((wallet) { + walletFile.open().then((Wallet wallet) { setState(() { _passwordController.clear(); _seedWords = (wallet as KeyStore).mnemonic!.split(' '); diff --git a/lib/screens/export/export.dart b/lib/screens/export/export.dart index 0445e076..222c2a2b 100644 --- a/lib/screens/export/export.dart +++ b/lib/screens/export/export.dart @@ -1,4 +1,3 @@ -library export; export 'export_wallet_info_screen.dart'; export 'export_wallet_password_screen.dart'; diff --git a/lib/screens/export/export_wallet_info_screen.dart b/lib/screens/export/export_wallet_info_screen.dart index 2b4c3f99..e765a694 100644 --- a/lib/screens/export/export_wallet_info_screen.dart +++ b/lib/screens/export/export_wallet_info_screen.dart @@ -6,14 +6,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class ExportWalletInfoScreen extends StatefulWidget { - final String seed; - final bool backupWalletFlow; const ExportWalletInfoScreen( this.seed, { this.backupWalletFlow = false, - Key? key, - }) : super(key: key); + super.key, + }); + final String seed; + final bool backupWalletFlow; @override State createState() => _ExportWalletInfoScreenState(); @@ -27,7 +27,7 @@ class _ExportWalletInfoScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -42,7 +42,7 @@ class _ExportWalletInfoScreenState extends State { 'assets/svg/ic_export_seed.svg', colorFilter: const ColorFilter.mode(AppColors.znnColor, BlendMode.srcIn), - height: 55.0, + height: 55, ), ), Text( @@ -60,23 +60,23 @@ class _ExportWalletInfoScreenState extends State { } Widget _getSeedFieldsGrid() { - double seedFieldsGridWidth = MediaQuery.of(context).size.width * 0.5; - String text = 'A Seed Vault is an encrypted file for backing up your Seed.' + final double seedFieldsGridWidth = MediaQuery.of(context).size.width * 0.5; + const String text = 'A Seed Vault is an encrypted file for backing up your Seed.' ' The Seed is encrypted with a Seed Vault Key and cannot be accessed ' 'without it. Make sure you backup your Seed Vault in multiple offline locations ' '(e.g. USB, external HDD) and do not lose your Seed Vault Key.' - ' If you lose the Seed Vault file or you don\'t remember the Seed Vault ' + " If you lose the Seed Vault file or you don't remember the Seed Vault " 'Key you lose access to your funds.'; return Container( width: seedFieldsGridWidth, padding: const EdgeInsets.symmetric( - vertical: 40.0, - horizontal: 50.0, + vertical: 40, + horizontal: 50, ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondaryContainer, borderRadius: const BorderRadius.all( - Radius.circular(10.0), + Radius.circular(10), ), ), child: Text( @@ -102,33 +102,33 @@ class _ExportWalletInfoScreenState extends State { child: SvgPicture.asset( 'assets/svg/ic_seed.svg', colorFilter: const ColorFilter.mode( - AppColors.qsrColor, BlendMode.srcIn), - height: 50.0, + AppColors.qsrColor, BlendMode.srcIn,), + height: 50, ), ), const Padding( - padding: EdgeInsets.only(top: 8.0), + padding: EdgeInsets.only(top: 8), ), Text( 'Seed', style: Theme.of(context).textTheme.bodyLarge, - ) + ), ], ), Column( children: [ const Icon( SimpleLineIcons.key, - size: 50.0, + size: 50, color: AppColors.errorColor, ), const Padding( - padding: EdgeInsets.only(top: 8.0), + padding: EdgeInsets.only(top: 8), ), Text( 'Seed Vault Key', style: Theme.of(context).textTheme.bodyLarge, - ) + ), ], ), Column( @@ -138,17 +138,17 @@ class _ExportWalletInfoScreenState extends State { child: SvgPicture.asset( 'assets/svg/ic_vault_seed.svg', colorFilter: const ColorFilter.mode( - AppColors.znnColor, BlendMode.srcIn), - height: 50.0, + AppColors.znnColor, BlendMode.srcIn,), + height: 50, ), ), const Padding( - padding: EdgeInsets.only(top: 8.0), + padding: EdgeInsets.only(top: 8), ), Text( 'Seed Vault', style: Theme.of(context).textTheme.bodyLarge, - ) + ), ], ), ], @@ -173,7 +173,7 @@ class _ExportWalletInfoScreenState extends State { Text( 'I will securely store the Seed Vault & Seed Vault Key', style: Theme.of(context).textTheme.headlineSmall, - ) + ), ], ); } diff --git a/lib/screens/export/export_wallet_password_screen.dart b/lib/screens/export/export_wallet_password_screen.dart index a489d76c..aa635219 100644 --- a/lib/screens/export/export_wallet_password_screen.dart +++ b/lib/screens/export/export_wallet_password_screen.dart @@ -14,14 +14,14 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ExportWalletPasswordScreen extends StatefulWidget { - final String seed; - final bool backupWalletFlow; const ExportWalletPasswordScreen( this.seed, { this.backupWalletFlow = false, - Key? key, - }) : super(key: key); + super.key, + }); + final String seed; + final bool backupWalletFlow; @override State createState() => @@ -42,13 +42,13 @@ class _ExportWalletPasswordScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 2, numLevels: 2, @@ -59,8 +59,8 @@ class _ExportWalletPasswordScreenState child: SvgPicture.asset( 'assets/svg/ic_export_seed.svg', colorFilter: const ColorFilter.mode( - AppColors.znnColor, BlendMode.srcIn), - height: 55.0, + AppColors.znnColor, BlendMode.srcIn,), + height: 55, ), ), kVerticalSpacing, @@ -74,10 +74,10 @@ class _ExportWalletPasswordScreenState style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox( - height: 50.0, + height: 50, ), Column( - children: [ + children: [ Form( key: _passwordKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -85,7 +85,7 @@ class _ExportWalletPasswordScreenState hintText: 'Password', controller: _passwordController, validator: InputValidators.validatePassword, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -97,12 +97,12 @@ class _ExportWalletPasswordScreenState child: PasswordInputField( hintText: 'Confirm password', controller: _confirmPasswordController, - validator: (value) => + validator: (String? value) => InputValidators.checkPasswordMatch( _passwordController.text, value, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -126,7 +126,7 @@ class _ExportWalletPasswordScreenState children: [ _getGoBackButton(), kSpacingBetweenActionButtons, - _getExportButton() + _getExportButton(), ], ), ], @@ -144,7 +144,7 @@ class _ExportWalletPasswordScreenState initialDirectory = (await getApplicationDocumentsDirectory()).path; } - final walletPath = await getSaveLocation( + final FileSaveLocation? walletPath = await getSaveLocation( acceptedTypeGroups: [ const XTypeGroup( label: 'file', @@ -159,12 +159,12 @@ class _ExportWalletPasswordScreenState )}.json', ); if (walletPath != null) { - KeyStoreManager keyStoreManager = KeyStoreManager( + final KeyStoreManager keyStoreManager = KeyStoreManager( walletPath: Directory( path.dirname(walletPath.path), ), ); - KeyStore keyStore = KeyStore.fromMnemonic(widget.seed); + final KeyStore keyStore = KeyStore.fromMnemonic(widget.seed); await keyStoreManager.saveKeyStore( keyStore, _passwordController.text, @@ -185,11 +185,11 @@ class _ExportWalletPasswordScreenState } void _updateExportedSeedList() { - List exportedSeeds = []; + final List exportedSeeds = []; exportedSeeds.addAll(Provider.of>>( context, listen: false, - ).value); + ).value,); exportedSeeds.add(widget.seed); Provider.of>>( context, diff --git a/lib/screens/node_management_screen.dart b/lib/screens/node_management_screen.dart index 64e474f1..56d6a4bf 100644 --- a/lib/screens/node_management_screen.dart +++ b/lib/screens/node_management_screen.dart @@ -12,14 +12,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class NodeManagementScreen extends StatefulWidget { - final VoidCallback? nodeConfirmationCallback; - - static const String route = 'node-management-screen'; const NodeManagementScreen({ this.nodeConfirmationCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback? nodeConfirmationCallback; + + static const String route = 'node-management-screen'; @override State createState() => _NodeManagementScreenState(); @@ -59,12 +59,12 @@ class _NodeManagementScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, - horizontal: 50.0, + vertical: 30, + horizontal: 50, ), child: ListView( shrinkWrap: true, - children: [ + children: [ const NotificationWidget(), Text( 'Node Management', @@ -84,7 +84,7 @@ class _NodeManagementScreenState extends State { height: kVerticalSpacing.height! * 2, ), Row( - children: [ + children: [ const Expanded( child: SizedBox(), ), @@ -92,7 +92,7 @@ class _NodeManagementScreenState extends State { flex: 2, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'Node selection', style: Theme.of(context).textTheme.bodyLarge, @@ -128,7 +128,6 @@ class _NodeManagementScreenState extends State { Widget _getAutoReceiveCheckboxContainer() { return Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Checkbox( value: _autoReceive, @@ -138,9 +137,9 @@ class _NodeManagementScreenState extends State { if (value == true) { NodeUtils.getUnreceivedTransactions().then((value) { sl().autoReceive(); - }).onError((error, stackTrace) { + }).onError((Object? error, StackTrace stackTrace) { Logger('MainAppContainer').log(Level.WARNING, - '_getAutoReceiveCheckboxContainer', error, stackTrace); + '_getAutoReceiveCheckboxContainer', error, stackTrace,); }); } else if (value == false && sl().pool.isNotEmpty) { @@ -155,7 +154,7 @@ class _NodeManagementScreenState extends State { Text( 'Automatically receive transactions', style: Theme.of(context).textTheme.headlineSmall, - ) + ), ], ); } @@ -191,10 +190,10 @@ class _NodeManagementScreenState extends State { ); } - _getConfirmNodeSelectionButton() { + Row _getConfirmNodeSelectionButton() { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ LoadingButton.settings( text: 'Continue', onPressed: _onConfirmNodeButtonPressed, @@ -212,7 +211,7 @@ class _NodeManagementScreenState extends State { try { _confirmNodeButtonKey.currentState?.animateForward(); - String url = _selectedNode == kEmbeddedNode + final String url = _selectedNode == kEmbeddedNode ? kLocalhostDefaultNodeUrl : _selectedNode!; bool isConnectionEstablished = @@ -221,10 +220,10 @@ class _NodeManagementScreenState extends State { // Check if node is already running if (!isConnectionEstablished) { // Initialize local full node - await Isolate.spawn(EmbeddedNode.runNode, [''], + await Isolate.spawn(EmbeddedNode.runNode, [''], onExit: sl(instanceName: 'embeddedStoppedPort').sendPort, - debugName: 'EmbeddedNodeIsolate'); + debugName: 'EmbeddedNodeIsolate',); kEmbeddedNodeRunning = true; // The node needs a couple of seconds to actually start await Future.delayed(kEmbeddedConnectionDelay); @@ -241,7 +240,7 @@ class _NodeManagementScreenState extends State { kSelectedNodeKey, _selectedNode, ); - kCurrentNode = _selectedNode!; + kCurrentNode = _selectedNode; await _sendChangingNodeSuccessNotification(); if (widget.nodeConfirmationCallback != null) { widget.nodeConfirmationCallback!(); @@ -257,7 +256,7 @@ class _NodeManagementScreenState extends State { 'Connection failed', ); setState(() { - _selectedNode = kCurrentNode!; + _selectedNode = kCurrentNode; }); } finally { _confirmNodeButtonKey.currentState?.animateReverse(); @@ -273,14 +272,14 @@ class _NodeManagementScreenState extends State { Widget _getAddNodeColumn() { return Column( - children: [ + children: [ Form( key: _newNodeKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( controller: _newNodeController, hintText: 'Node address with port', - onSubmitted: (value) { + onSubmitted: (String value) { if (_ifUserInputValid()) { _onAddNodePressed(); } @@ -307,11 +306,11 @@ class _NodeManagementScreenState extends State { InputValidators.node(_newNodeController.text) == null; Future _onAddNodePressed() async { - if ([...kDbNodes, ...kDefaultCommunityNodes, ...kDefaultNodes] + if ([...kDbNodes, ...kDefaultCommunityNodes, ...kDefaultNodes] .contains(_newNodeController.text)) { await NotificationUtils.sendNotificationError( 'Node ${_newNodeController.text} already exists', - 'Node already exists'); + 'Node already exists',); } else { _addNodeToDb(); } @@ -342,18 +341,18 @@ class _NodeManagementScreenState extends State { children: { ...kDefaultNodes, ...kDefaultCommunityNodes, - ...kDbNodes - }.toList().map((e) => _getNodeTile(e)).toList(), + ...kDbNodes, + }.toList().map(_getNodeTile).toList(), ); } Row _getNodeTile(String node) { return Row( - children: [ + children: [ Radio( value: node, groupValue: _selectedNode, - onChanged: (value) { + onChanged: (String? value) { setState(() { _selectedNode = value; }); @@ -363,7 +362,7 @@ class _NodeManagementScreenState extends State { child: SettingsNode( key: ValueKey(node), node: node, - onNodePressed: (value) { + onNodePressed: (String? value) { setState(() { _selectedNode = value; }); diff --git a/lib/screens/onboarding/access_wallet_screen.dart b/lib/screens/onboarding/access_wallet_screen.dart index 5cc18dd2..391bd9e0 100644 --- a/lib/screens/onboarding/access_wallet_screen.dart +++ b/lib/screens/onboarding/access_wallet_screen.dart @@ -4,9 +4,9 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class AccessWalletScreen extends StatefulWidget { - static const String route = 'access-wallet-screen'; - const AccessWalletScreen({Key? key}) : super(key: key); + const AccessWalletScreen({super.key}); + static const String route = 'access-wallet-screen'; @override State createState() => _AccessWalletScreenState(); @@ -17,9 +17,9 @@ class _AccessWalletScreenState extends State { Widget build(BuildContext context) { return Scaffold( body: Container( - padding: const EdgeInsets.all(50.0), + padding: const EdgeInsets.all(50), child: Column( - children: [ + children: [ Column( children: [ Text( @@ -32,14 +32,14 @@ class _AccessWalletScreenState extends State { style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox( - height: 50.0, + height: 50, ), ], ), Expanded( child: StandardFluidLayout( defaultCellHeight: kStaggeredNumOfColumns / 3, - children: [ + children: [ AccessWalletFluidCell( onPressed: _onCreateWalletButtonPressed, buttonIconLocation: 'assets/svg/ic_create_new.svg', diff --git a/lib/screens/onboarding/create_key_store_screen.dart b/lib/screens/onboarding/create_key_store_screen.dart index bc653974..6f50e4f4 100644 --- a/lib/screens/onboarding/create_key_store_screen.dart +++ b/lib/screens/onboarding/create_key_store_screen.dart @@ -6,16 +6,16 @@ import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class CreateKeyStoreScreen extends StatefulWidget { - final String seed; - final String password; - final int progressBarNumLevels; const CreateKeyStoreScreen( this.seed, this.password, { this.progressBarNumLevels = 5, - Key? key, - }) : super(key: key); + super.key, + }); + final String seed; + final String password; + final int progressBarNumLevels; @override State createState() => _CreateKeyStoreScreenState(); @@ -39,15 +39,15 @@ class _CreateKeyStoreScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Center( child: StreamBuilder( stream: _keyStoreFileBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return Column( - children: [ + children: [ ProgressBar( currentLevel: widget.progressBarNumLevels - 1, numLevels: widget.progressBarNumLevels, diff --git a/lib/screens/onboarding/create_ledger_screen.dart b/lib/screens/onboarding/create_ledger_screen.dart index 4e2d647d..db1467cc 100644 --- a/lib/screens/onboarding/create_ledger_screen.dart +++ b/lib/screens/onboarding/create_ledger_screen.dart @@ -7,16 +7,16 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CreateLedgerWalletScreen extends StatefulWidget { - final WalletDefinition deviceInfo; - final String password; - final int progressBarNumLevels; const CreateLedgerWalletScreen( this.deviceInfo, this.password, { this.progressBarNumLevels = 4, - Key? key, - }) : super(key: key); + super.key, + }); + final WalletDefinition deviceInfo; + final String password; + final int progressBarNumLevels; @override State createState() => @@ -42,15 +42,15 @@ class _CreateLedgerWalletScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Center( child: StreamBuilder( stream: _ledgerWalletFileBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return Column( - children: [ + children: [ ProgressBar( currentLevel: widget.progressBarNumLevels - 1, numLevels: widget.progressBarNumLevels, diff --git a/lib/screens/onboarding/hardware_wallet/hardware_wallet.dart b/lib/screens/onboarding/hardware_wallet/hardware_wallet.dart index 0fa29018..2e3ce215 100644 --- a/lib/screens/onboarding/hardware_wallet/hardware_wallet.dart +++ b/lib/screens/onboarding/hardware_wallet/hardware_wallet.dart @@ -1,4 +1,3 @@ -library hardware_wallet; -export 'hardware_wallet_password_screen.dart'; export 'hardware_wallet_device_choice_screen.dart'; +export 'hardware_wallet_password_screen.dart'; diff --git a/lib/screens/onboarding/hardware_wallet/hardware_wallet_device_choice_screen.dart b/lib/screens/onboarding/hardware_wallet/hardware_wallet_device_choice_screen.dart index 7cd3800b..6f807aec 100644 --- a/lib/screens/onboarding/hardware_wallet/hardware_wallet_device_choice_screen.dart +++ b/lib/screens/onboarding/hardware_wallet/hardware_wallet_device_choice_screen.dart @@ -4,14 +4,14 @@ import 'package:zenon_syrius_wallet_flutter/blocs/notifications_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/notification_type.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/wallet_notification.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/screens/screens.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_ledger_dart/znn_ledger_dart.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class HardwareWalletDeviceChoiceScreen extends StatefulWidget { - const HardwareWalletDeviceChoiceScreen({Key? key}) : super(key: key); + const HardwareWalletDeviceChoiceScreen({super.key}); @override State createState() => @@ -20,8 +20,8 @@ class HardwareWalletDeviceChoiceScreen extends StatefulWidget { class _HardwareWalletDeviceChoiceScreenState extends State { - final List _walletManagers = [LedgerWalletManager()]; - List _devices = []; + final List _walletManagers = [LedgerWalletManager()]; + List _devices = []; WalletDefinition? _selectedDevice; final Map> _deviceValueMap = >{}; @@ -48,19 +48,19 @@ class _HardwareWalletDeviceChoiceScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 1, numLevels: 4, ), const SizedBox( - height: 30.0, + height: 30, ), const NotificationWidget(), Text( @@ -74,7 +74,7 @@ class _HardwareWalletDeviceChoiceScreenState ), kVerticalSpacing, SizedBox( - height: 40.0, + height: 40, child: _getScanDevicesContainer(), ), kVerticalSpacing, @@ -95,17 +95,15 @@ class _HardwareWalletDeviceChoiceScreenState return Container( decoration: BoxDecoration( color: Colors.transparent, - borderRadius: const BorderRadius.all(Radius.circular(6.0)), + borderRadius: const BorderRadius.all(Radius.circular(6)), border: Border.all( color: AppColors.znnColor, - width: 1.0, - style: BorderStyle.solid, - )), + ),), child: InkWell( child: FocusableActionDetector( child: SizedBox( - height: 50.0, - width: 150.0, + height: 50, + width: 150, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -113,10 +111,10 @@ class _HardwareWalletDeviceChoiceScreenState color: Colors.transparent, child: Icon(Icons.search, color: - Theme.of(context).textTheme.headlineSmall!.color!, - size: 18.0)), + Theme.of(context).textTheme.headlineSmall!.color, + size: 18,),), const SizedBox( - width: 15.0, + width: 15, ), Text( 'Scan devices', @@ -128,27 +126,27 @@ class _HardwareWalletDeviceChoiceScreenState ), onTap: () async { await _scanDevices(); - }), + },), ); } Future _scanDevices() async { - List>> futures = _walletManagers - .map((manager) => manager.getWalletDefinitions()) + final List>> futures = _walletManagers + .map((WalletManager manager) => manager.getWalletDefinitions()) .toList(); - List> listOfDefinitions = + final List> listOfDefinitions = await Future.wait(futures); // Combine all the iterables into a single list using fold or expand // For example, using fold: - List combinedList = + final List combinedList = listOfDefinitions.fold>( [], - (previousList, element) => previousList..addAll(element), + (List previousList, Iterable element) => previousList..addAll(element), ); - for (var device in combinedList) { + for (final WalletDefinition device in combinedList) { if (!_deviceValueMap.containsKey(device.walletId)) { _deviceValueMap[device.walletId] = ValueNotifier(null); } @@ -158,7 +156,7 @@ class _HardwareWalletDeviceChoiceScreenState _devices = combinedList; _selectedDevice = null; - for (var valueNotifier in _deviceValueMap.values) { + for (final ValueNotifier valueNotifier in _deviceValueMap.values) { valueNotifier.value = null; } }); @@ -167,8 +165,8 @@ class _HardwareWalletDeviceChoiceScreenState List _getDevices() { return _devices .map( - (e) => Row( - children: [ + (WalletDefinition e) => Row( + children: [ Radio( value: e, groupValue: _selectedDevice, @@ -177,22 +175,22 @@ class _HardwareWalletDeviceChoiceScreenState Expanded( child: Container( margin: const EdgeInsets.symmetric( - vertical: 5.0, + vertical: 5, ), child: Row( - children: [ + children: [ Expanded( child: InkWell( borderRadius: BorderRadius.circular( - 10.0, + 10, ), onTap: () => _onDevicePressedCallback(e), child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 5.0, vertical: 5.0), + horizontal: 5, vertical: 5,), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( _getWalletName(e), style: Theme.of(context) @@ -208,15 +206,15 @@ class _HardwareWalletDeviceChoiceScreenState ), ValueListenableBuilder( valueListenable: _deviceValueMap[e.walletId]!, - builder: (context, value, _) => SizedBox( + builder: (BuildContext context, String? value, _) => SizedBox( height: 20, child: value == null ? const Text( - 'Select to connect the device') + 'Select to connect the device',) : Text(value, style: Theme.of(context) .textTheme - .bodyMedium), + .bodyMedium,), ), ), ], @@ -227,7 +225,7 @@ class _HardwareWalletDeviceChoiceScreenState ], ), ), - ) + ), ], ), ) @@ -235,11 +233,11 @@ class _HardwareWalletDeviceChoiceScreenState } Future _onDevicePressedCallback( - WalletDefinition? walletDefinition) async { + WalletDefinition? walletDefinition,) async { Wallet? wallet; try { - for (var walletManager in _walletManagers) { - WalletDefinition wd = walletDefinition!; + for (final WalletManager walletManager in _walletManagers) { + final WalletDefinition wd = walletDefinition!; if (await walletManager.supportsWallet(wd)) { wallet = await walletManager.getWallet(walletDefinition); break; @@ -248,9 +246,9 @@ class _HardwareWalletDeviceChoiceScreenState if (wallet == null) { throw const LedgerError.connectionError( origMessage: - 'Not connected, please connect the device and try again.'); + 'Not connected, please connect the device and try again.',); } - final walletAddress = await _getWalletAddress(wallet); + final Address walletAddress = await _getWalletAddress(wallet); setState(() { _deviceValueMap[walletDefinition!.walletId]!.value = walletAddress.toString(); @@ -269,7 +267,7 @@ class _HardwareWalletDeviceChoiceScreenState } Future
_getWalletAddress(Wallet wallet) async { - final account = await wallet.getAccount(); + final WalletAccount account = await wallet.getAccount(); if (account is LedgerWalletAccount) { await sl.get().addNotification( WalletNotification( @@ -280,9 +278,9 @@ class _HardwareWalletDeviceChoiceScreenState type: NotificationType.confirm, ), ); - return await account.getAddress(true); + return account.getAddress(true); } else { - return await account.getAddress(); + return account.getAddress(); } } diff --git a/lib/screens/onboarding/hardware_wallet/hardware_wallet_password_screen.dart b/lib/screens/onboarding/hardware_wallet/hardware_wallet_password_screen.dart index c7b2024d..566b65e7 100644 --- a/lib/screens/onboarding/hardware_wallet/hardware_wallet_password_screen.dart +++ b/lib/screens/onboarding/hardware_wallet/hardware_wallet_password_screen.dart @@ -5,9 +5,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class HardwareWalletPasswordScreen extends StatefulWidget { - final WalletDefinition deviceInfo; - const HardwareWalletPasswordScreen(this.deviceInfo, {Key? key}) : super(key: key); + const HardwareWalletPasswordScreen(this.deviceInfo, {super.key}); + final WalletDefinition deviceInfo; @override State createState() => @@ -27,38 +27,38 @@ class _HardwareWalletPasswordScreenState extends State[ Column( - children: [ + children: [ const ProgressBar( currentLevel: 2, numLevels: 4, ), const SizedBox( - height: 30.0, + height: 30, ), Text('Create a wallet password', - style: Theme.of(context).textTheme.headlineLarge), + style: Theme.of(context).textTheme.headlineLarge,), kVerticalSpacing, Text( 'This is the password that will be required to unlock the wallet', - style: Theme.of(context).textTheme.headlineMedium), + style: Theme.of(context).textTheme.headlineMedium,), const SizedBox( - height: 65.0, + height: 65, ), Column( - children: [ + children: [ Form( key: _passwordKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: PasswordInputField( controller: _passwordController, validator: InputValidators.validatePassword, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, hintText: 'Password', @@ -70,17 +70,17 @@ class _HardwareWalletPasswordScreenState extends State + validator: (String? value) => InputValidators.checkPasswordMatch( - _passwordController.text, value), - onChanged: (value) { + _passwordController.text, value,), + onChanged: (String value) { setState(() {}); }, hintText: 'Confirm password', ), ), const SizedBox( - height: 35.0, + height: 35, ), PasswordProgressBar( password: _passwordController.text, @@ -100,7 +100,7 @@ class _HardwareWalletPasswordScreenState extends State[ _getPassiveButton(), kSpacingBetweenActionButtons, - _getActionButton() + _getActionButton(), ], ), ], diff --git a/lib/screens/onboarding/import_wallet/import_wallet.dart b/lib/screens/onboarding/import_wallet/import_wallet.dart index 8783568f..4c0345cb 100644 --- a/lib/screens/onboarding/import_wallet/import_wallet.dart +++ b/lib/screens/onboarding/import_wallet/import_wallet.dart @@ -1,4 +1,3 @@ -library import_wallet; export 'import_wallet_decrypt_screen.dart'; export 'import_wallet_password_screen.dart'; diff --git a/lib/screens/onboarding/import_wallet/import_wallet_decrypt_screen.dart b/lib/screens/onboarding/import_wallet/import_wallet_decrypt_screen.dart index 32577f42..966c6b5a 100644 --- a/lib/screens/onboarding/import_wallet/import_wallet_decrypt_screen.dart +++ b/lib/screens/onboarding/import_wallet/import_wallet_decrypt_screen.dart @@ -2,15 +2,15 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/screens/screens.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ImportWalletDecryptScreen extends StatefulWidget { - final String path; - const ImportWalletDecryptScreen(this.path, {Key? key}) : super(key: key); + const ImportWalletDecryptScreen(this.path, {super.key}); + final String path; @override State createState() => @@ -31,18 +31,18 @@ class _ImportWalletDecryptScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 2, ), const SizedBox( - height: 30.0, + height: 30, ), Text( 'Unlock your Seed Vault', @@ -58,11 +58,11 @@ class _ImportWalletDecryptScreenState extends State { PasswordInputField( hintText: 'Password', controller: _passwordController, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, errorText: _passwordErrorText, - onSubmitted: (value) { + onSubmitted: (String value) { if (_passwordController.text.isNotEmpty) { _loadingButton.onPressed!(); } @@ -107,19 +107,19 @@ class _ImportWalletDecryptScreenState extends State { ); } - _getDecryptKeyStoreFileViewModel() { + ViewModelBuilder _getDecryptKeyStoreFileViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { - model.stream.listen((walletFile) { + onViewModelReady: (DecryptWalletFileBloc model) { + model.stream.listen((WalletFile? walletFile) { if (walletFile != null && walletFile is KeyStoreWalletFile) { _loadingButtonKey.currentState!.animateReverse(); setState(() { _passwordErrorText = null; }); walletFile - .access((wallet) => Future.value((wallet as KeyStore).mnemonic!)) - .then((value) => NavigationUtils.push( - context, ImportWalletPasswordScreen(value))); + .access((Wallet wallet) => Future.value((wallet as KeyStore).mnemonic!)) + .then((String value) => NavigationUtils.push( + context, ImportWalletPasswordScreen(value),),); } }, onError: (error) { _loadingButtonKey.currentState!.animateReverse(); @@ -132,13 +132,13 @@ class _ImportWalletDecryptScreenState extends State { _passwordErrorText = error.toString(); }); } - }); + },); }, - builder: (_, model, __) { + builder: (_, DecryptWalletFileBloc model, __) { _loadingButton = _getLoadingButton(model); return _getLoadingButton(model); }, - viewModelBuilder: () => DecryptWalletFileBloc(), + viewModelBuilder: DecryptWalletFileBloc.new, ); } diff --git a/lib/screens/onboarding/import_wallet/import_wallet_password_screen.dart b/lib/screens/onboarding/import_wallet/import_wallet_password_screen.dart index f46b2215..c5dea392 100644 --- a/lib/screens/onboarding/import_wallet/import_wallet_password_screen.dart +++ b/lib/screens/onboarding/import_wallet/import_wallet_password_screen.dart @@ -4,14 +4,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class ImportWalletPasswordScreen extends StatefulWidget { - final String seed; - final int progressBarNumLevels; const ImportWalletPasswordScreen( this.seed, { this.progressBarNumLevels = 5, - Key? key, - }) : super(key: key); + super.key, + }); + final String seed; + final int progressBarNumLevels; @override State createState() => @@ -32,19 +32,19 @@ class _ImportWalletPasswordScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ ProgressBar( currentLevel: widget.progressBarNumLevels - 2, numLevels: widget.progressBarNumLevels, ), const SizedBox( - height: 30.0, + height: 30, ), Text( 'Create a wallet password', @@ -56,10 +56,10 @@ class _ImportWalletPasswordScreenState style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox( - height: 100.0, + height: 100, ), Column( - children: [ + children: [ Form( key: _passwordKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -67,10 +67,10 @@ class _ImportWalletPasswordScreenState hintText: 'Password', controller: _passwordController, validator: InputValidators.validatePassword, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, - onSubmitted: (value) { + onSubmitted: (String value) { if (_arePasswordsValid()) { NavigationUtils.push( context, @@ -92,15 +92,15 @@ class _ImportWalletPasswordScreenState child: PasswordInputField( hintText: 'Confirm password', controller: _confirmPasswordController, - validator: (value) => + validator: (String? value) => InputValidators.checkPasswordMatch( _passwordController.text, value, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, - onSubmitted: (value) { + onSubmitted: (String value) { if (_arePasswordsValid()) { NavigationUtils.push( context, diff --git a/lib/screens/onboarding/import_wallet/import_wallet_seed_choice_screen.dart b/lib/screens/onboarding/import_wallet/import_wallet_seed_choice_screen.dart index e4c0037e..ff15525c 100644 --- a/lib/screens/onboarding/import_wallet/import_wallet_seed_choice_screen.dart +++ b/lib/screens/onboarding/import_wallet/import_wallet_seed_choice_screen.dart @@ -6,7 +6,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ImportWalletSeedChoiceScreen extends StatefulWidget { - const ImportWalletSeedChoiceScreen({Key? key}) : super(key: key); + const ImportWalletSeedChoiceScreen({super.key}); @override State createState() => @@ -32,20 +32,20 @@ class _ImportWalletSeedChoiceScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ ProgressBar( currentLevel: 1, // If the seed is imported from a file, an extra step to decrypt the file is needed numLevels: _walletFilePath == null ? 4 : 5, ), const SizedBox( - height: 30.0, + height: 30, ), Text( 'Import your wallet', @@ -58,7 +58,7 @@ class _ImportWalletSeedChoiceScreenState ), kVerticalSpacing, SizedBox( - height: 45.0, + height: 45, child: _getSeedChoice(), ), kVerticalSpacing, @@ -71,7 +71,7 @@ class _ImportWalletSeedChoiceScreenState children: [ _getGoBackButton(), kSpacingBetweenActionButtons, - _getContinueButton() + _getContinueButton(), ], ), ], @@ -93,7 +93,7 @@ class _ImportWalletSeedChoiceScreenState _walletFilePath = path; _seedGridKey.currentState!.continueButtonDisabled = false; }); - }), + },), ); } @@ -118,10 +118,10 @@ class _ImportWalletSeedChoiceScreenState } else { showDialog( context: context, - builder: (context) => AlertDialog( + builder: (BuildContext context) => AlertDialog( title: const Text('Importing seed'), content: const Text('Mnemonic is not valid'), - actions: [ + actions: [ TextButton( child: const Text('OK'), onPressed: () { @@ -163,7 +163,7 @@ class _ImportWalletSeedChoiceScreenState setState(() { _isSeed12Selected = false; _seedGridKey.currentState!.changedSeed( - List.generate(24, (index) => ''), + List.generate(24, (int index) => ''), ); }); }, @@ -171,7 +171,7 @@ class _ImportWalletSeedChoiceScreenState setState(() { _isSeed12Selected = true; _seedGridKey.currentState!.changedSeed( - List.generate(12, (index) => ''), + List.generate(12, (int index) => ''), ); }); }, @@ -183,11 +183,11 @@ class _ImportWalletSeedChoiceScreenState _isSeed12Selected ? List.generate( 12, - (index) => '', + (int index) => '', ) : List.generate( 24, - (index) => '', + (int index) => '', ), key: _seedGridKey, isContinueButtonDisabled: true, diff --git a/lib/screens/onboarding/new_wallet/new_wallet.dart b/lib/screens/onboarding/new_wallet/new_wallet.dart index 98471eae..90d3004b 100644 --- a/lib/screens/onboarding/new_wallet/new_wallet.dart +++ b/lib/screens/onboarding/new_wallet/new_wallet.dart @@ -1,4 +1,3 @@ -library new_wallet; export 'new_wallet_confirm_seed_screen.dart'; export 'new_wallet_password_screen.dart'; diff --git a/lib/screens/onboarding/new_wallet/new_wallet_confirm_seed_screen.dart b/lib/screens/onboarding/new_wallet/new_wallet_confirm_seed_screen.dart index 450865bc..37ec0ca7 100644 --- a/lib/screens/onboarding/new_wallet/new_wallet_confirm_seed_screen.dart +++ b/lib/screens/onboarding/new_wallet/new_wallet_confirm_seed_screen.dart @@ -6,12 +6,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class NewWalletConfirmSeedScreen extends StatefulWidget { - final List seedWords; const NewWalletConfirmSeedScreen( this.seedWords, { - Key? key, - }) : super(key: key); + super.key, + }); + final List seedWords; @override State createState() => @@ -27,15 +27,15 @@ class _NewWalletConfirmSeedScreenState late Widget _actionButton; String? _draggedValue; - final List _seedGridElements = []; - final List _randomIndexes = []; - List _foundMissingRandomElementsIndexes = []; + final List _seedGridElements = []; + final List _randomIndexes = []; + List _foundMissingRandomElementsIndexes = []; @override void initState() { super.initState(); _actionButton = _getVerifyButton(); - for (var word in widget.seedWords) { + for (final String word in widget.seedWords) { _seedGridElements.add( SeedGridElement( word: word, @@ -45,7 +45,7 @@ class _NewWalletConfirmSeedScreenState ); } _generateRandomIndexes(); - for (var index in _randomIndexes) { + for (final int index in _randomIndexes) { _seedGridElements[index].word = ''; } } @@ -55,18 +55,18 @@ class _NewWalletConfirmSeedScreenState return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 2, ), const SizedBox( - height: 30.0, + height: 30, ), Text( 'Confirm your seed', @@ -75,7 +75,7 @@ class _NewWalletConfirmSeedScreenState kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Drag & drop the words in the correct order', style: Theme.of(context).textTheme.headlineMedium, @@ -87,18 +87,17 @@ class _NewWalletConfirmSeedScreenState ], ), const SizedBox( - height: 75.0, + height: 75, ), _getSeedInputWidgetsGrid(), ], ), Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ Container( - margin: const EdgeInsets.only(left: 90.0), + margin: const EdgeInsets.only(left: 90), child: _getMissingSeedGridElements(widget.seedWords), - ) + ), ], ), Row( @@ -122,7 +121,7 @@ class _NewWalletConfirmSeedScreenState } void _generateRandomIndex() { - int randomNumber = Random().nextInt(_seedGridElements.length); + final int randomNumber = Random().nextInt(_seedGridElements.length); if (!_randomIndexes.contains(randomNumber)) { _randomIndexes.add(randomNumber); } @@ -153,7 +152,7 @@ class _NewWalletConfirmSeedScreenState } Widget _seedFieldWidget(SeedGridElement seedGridElement) { - int seedGridElementIndex = _seedGridElements.indexOf(seedGridElement); + final int seedGridElementIndex = _seedGridElements.indexOf(seedGridElement); final TextEditingController controller = TextEditingController(); controller.text = seedGridElement.word; @@ -164,8 +163,8 @@ class _NewWalletConfirmSeedScreenState } return SizedBox( - width: 200.0, - height: 30.0, + width: 200, + height: 30, child: Row( children: [ InkWell( @@ -176,7 +175,7 @@ class _NewWalletConfirmSeedScreenState }); }, child: FocusableActionDetector( - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _hoveredSeedGridIndex = seedGridElementIndex; @@ -188,18 +187,18 @@ class _NewWalletConfirmSeedScreenState } }, child: Container( - width: 30.0, - height: 30.0, + width: 30, + height: 30, decoration: BoxDecoration( border: Border.all( - width: 2.0, + width: 2, color: _hoveredSeedGridIndex == seedGridElementIndex || _randomIndexes.contains(seedGridElementIndex) ? _getColor(seedGridElement, false) : Theme.of(context).colorScheme.secondaryContainer, ), color: Theme.of(context).colorScheme.secondaryContainer, - shape: BoxShape.circle), + shape: BoxShape.circle,), child: Center( child: Text( '${seedGridElementIndex + 1}', @@ -210,11 +209,11 @@ class _NewWalletConfirmSeedScreenState ), ), const SizedBox( - width: 10.0, + width: 10, ), Expanded( child: FocusableActionDetector( - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _hoveredSeedGridIndex = seedGridElementIndex; @@ -226,7 +225,7 @@ class _NewWalletConfirmSeedScreenState } }, child: DragTarget( - builder: (BuildContext context, accepted, rejected) { + builder: (BuildContext context, List accepted, List rejected) { return TextField( enabled: false, controller: controller, @@ -240,7 +239,7 @@ class _NewWalletConfirmSeedScreenState _randomIndexes.contains(seedGridElementIndex) ? Colors.white : AppColors.znnColor, - fontSize: 12.0, + fontSize: 12, ), decoration: InputDecoration( contentPadding: EdgeInsets.all(8.0), @@ -253,20 +252,20 @@ class _NewWalletConfirmSeedScreenState disabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: _getColor(seedGridElement, true), - width: 3.0, + width: 3, ), ), hintText: '', ), ); }, - onWillAccept: (data) { + onWillAcceptWithDetails: (DragTargetDetails data) { return _randomIndexes.contains(seedGridElementIndex) || !seedGridElement.isValid; }, - onAccept: (String data) { - var element = _seedGridElements[seedGridElementIndex]; - var i = -1; + onAcceptWithDetails: (DragTargetDetails data) { + final SeedGridElement element = _seedGridElements[seedGridElementIndex]; + int i = -1; if (element.word != '') { while ((i = widget.seedWords.indexOf(element.word, i + 1)) != @@ -278,14 +277,14 @@ class _NewWalletConfirmSeedScreenState } } i = -1; - while ((i = widget.seedWords.indexOf(data, i + 1)) != -1) { + while ((i = widget.seedWords.indexOf(data.data, i + 1)) != -1) { if (!_foundMissingRandomElementsIndexes.contains(i) && _randomIndexes.contains(i)) { _foundMissingRandomElementsIndexes.add(i); break; } } - element.word = data; + element.word = data.data; setState(() { _textCursor = seedGridElementIndex; }); @@ -299,8 +298,8 @@ class _NewWalletConfirmSeedScreenState } Widget _getMissingSeedGridElements(List seedWords) { - List list = []; - for (var index in _randomIndexes) { + final List list = []; + for (final int index in _randomIndexes) { if (!_foundMissingRandomElementsIndexes.contains(index)) { list.add( Draggable( @@ -308,7 +307,7 @@ class _NewWalletConfirmSeedScreenState style: ElevatedButton.styleFrom( foregroundColor: AppColors.darkSecondary, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5), ), ), onPressed: () {}, @@ -337,7 +336,7 @@ class _NewWalletConfirmSeedScreenState .withOpacity(0.5) : Theme.of(context).colorScheme.secondaryContainer, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5), ), ), onPressed: () {}, @@ -355,26 +354,23 @@ class _NewWalletConfirmSeedScreenState } } return Wrap( - crossAxisAlignment: WrapCrossAlignment.start, - alignment: WrapAlignment.start, - direction: Axis.horizontal, - spacing: 5.0, + spacing: 5, children: list, ); } void _checkSeed() { _seedError = false; - for (var element in _seedGridElements) { - int i = _seedGridElements.indexOf(element); + for (final SeedGridElement element in _seedGridElements) { + final int i = _seedGridElements.indexOf(element); element.isValid = element.word == widget.seedWords[i]; if (!element.isValid) { _seedError = true; } } if (_seedError) { - for (var element in _seedGridElements) { - int i = _seedGridElements.indexOf(element); + for (final SeedGridElement element in _seedGridElements) { + final int i = _seedGridElements.indexOf(element); if (_randomIndexes.contains(i)) { element.isValid = false; element.word = ''; @@ -385,7 +381,7 @@ class _NewWalletConfirmSeedScreenState setState(() { _seedError = true; _foundMissingRandomElementsIndexes = _randomIndexes - .where((index) => _seedGridElements[index].isValid) + .where((int index) => _seedGridElements[index].isValid) .toList(); _actionButton = _foundMissingRandomElementsIndexes.length == kNumOfSeedWordsToBeFound @@ -401,7 +397,7 @@ class _NewWalletConfirmSeedScreenState NavigationUtils.push( context, NewWalletPasswordScreen( - _seedGridElements.map((e) => e.word).toList(), + _seedGridElements.map((SeedGridElement e) => e.word).toList(), ), ); }, @@ -425,16 +421,16 @@ class _NewWalletConfirmSeedScreenState } Widget _getSeedInputWidgetsGrid() { - int divider = widget.seedWords.length ~/ kSeedGridNumOfRows; + final int divider = widget.seedWords.length ~/ kSeedGridNumOfRows; - List columnChildren = []; + List columnChildren = []; for (int i = 0; i <= _seedGridElements.length / divider - 1; i++) { columnChildren.add( _getSeedRow( List.generate( divider, - (index) => index + (divider * i), + (int index) => index + (divider * i), ), ), ); @@ -443,8 +439,8 @@ class _NewWalletConfirmSeedScreenState columnChildren = columnChildren.zip( List.generate( kSeedGridNumOfRows - 1, - (index) => const SizedBox( - height: 10.0, + (int index) => const SizedBox( + height: 10, ), ), ); @@ -456,16 +452,16 @@ class _NewWalletConfirmSeedScreenState } Widget _getSeedRow(List rangeIndexes) { - List children = rangeIndexes.fold>( - [], - (previousValue, index) { + final List children = rangeIndexes.fold>( + [], + (List previousValue, int index) { previousValue.add(_seedFieldWidget( _seedGridElements[index], - )); + ),); if (rangeIndexes.last != index) { previousValue.add( const SizedBox( - width: 10.0, + width: 10, ), ); } diff --git a/lib/screens/onboarding/new_wallet/new_wallet_password_screen.dart b/lib/screens/onboarding/new_wallet/new_wallet_password_screen.dart index c42f7e28..9d0a0d5f 100644 --- a/lib/screens/onboarding/new_wallet/new_wallet_password_screen.dart +++ b/lib/screens/onboarding/new_wallet/new_wallet_password_screen.dart @@ -4,9 +4,9 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class NewWalletPasswordScreen extends StatefulWidget { - final List seedWords; - const NewWalletPasswordScreen(this.seedWords, {Key? key}) : super(key: key); + const NewWalletPasswordScreen(this.seedWords, {super.key}); + final List seedWords; @override State createState() => @@ -26,37 +26,37 @@ class _NewWalletPasswordScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 3, ), const SizedBox( - height: 30.0, + height: 30, ), Text('Create a wallet password', - style: Theme.of(context).textTheme.headlineLarge), + style: Theme.of(context).textTheme.headlineLarge,), kVerticalSpacing, Text( 'This is the password that will be required to unlock the wallet', - style: Theme.of(context).textTheme.headlineMedium), + style: Theme.of(context).textTheme.headlineMedium,), const SizedBox( - height: 65.0, + height: 65, ), Column( - children: [ + children: [ Form( key: _passwordKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: PasswordInputField( controller: _passwordController, validator: InputValidators.validatePassword, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, hintText: 'Password', @@ -68,17 +68,17 @@ class _NewWalletPasswordScreenState extends State { autovalidateMode: AutovalidateMode.onUserInteraction, child: PasswordInputField( controller: _confirmPasswordController, - validator: (value) => + validator: (String? value) => InputValidators.checkPasswordMatch( - _passwordController.text, value), - onChanged: (value) { + _passwordController.text, value,), + onChanged: (String value) { setState(() {}); }, hintText: 'Confirm password', ), ), const SizedBox( - height: 35.0, + height: 35, ), PasswordProgressBar( password: _passwordController.text, @@ -98,7 +98,7 @@ class _NewWalletPasswordScreenState extends State { children: [ _getPassiveButton(), kSpacingBetweenActionButtons, - _getActionButton() + _getActionButton(), ], ), ], diff --git a/lib/screens/onboarding/new_wallet/new_wallet_seed_choice_screen.dart b/lib/screens/onboarding/new_wallet/new_wallet_seed_choice_screen.dart index 6577847f..b5bfabff 100644 --- a/lib/screens/onboarding/new_wallet/new_wallet_seed_choice_screen.dart +++ b/lib/screens/onboarding/new_wallet/new_wallet_seed_choice_screen.dart @@ -8,9 +8,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class NewWalletSeedChoiceScreen extends StatefulWidget { - final bool? export; - const NewWalletSeedChoiceScreen({Key? key, this.export}) : super(key: key); + const NewWalletSeedChoiceScreen({super.key, this.export}); + final bool? export; @override State createState() => @@ -22,7 +22,8 @@ class _NewWalletSeedChoiceScreenState extends State { bool? _isSeedSecure = false; bool? _isSeedWrittenDown = false; - late List _generatedSeed24, _generatedSeed12; + late List _generatedSeed24; + late List _generatedSeed12; final GlobalKey _seedGridKey = GlobalKey(); @@ -39,18 +40,18 @@ class _NewWalletSeedChoiceScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( - children: [ + children: [ const ProgressBar( currentLevel: 1, ), const SizedBox( - height: 30.0, + height: 30, ), Text( _isSeed12Selected @@ -65,7 +66,7 @@ class _NewWalletSeedChoiceScreenState extends State { ), kVerticalSpacing, SizedBox( - height: 45.0, + height: 45, child: Visibility( visible: !_isSeedSecure!, child: _getSeedChoice(), @@ -76,14 +77,14 @@ class _NewWalletSeedChoiceScreenState extends State { ], ), SizedBox( - height: 40.0, + height: 40, child: Visibility( visible: !_isSeedSecure!, child: _getBackUpSeedContainer(), ), ), Column( - children: [ + children: [ _getConfirmSecureCheckboxContainer(), _getConfirmWrittenDownCheckbox(), ], @@ -142,22 +143,20 @@ class _NewWalletSeedChoiceScreenState extends State { Widget _getBackUpSeedContainer() { return Consumer>>( - builder: (_, exportedSeed, __) => Container( + builder: (_, ValueNotifier> exportedSeed, __) => Container( decoration: BoxDecoration( color: _isSeedExported(exportedSeed.value) ? AppColors.znnColor : Colors.transparent, - borderRadius: const BorderRadius.all(Radius.circular(6.0)), + borderRadius: const BorderRadius.all(Radius.circular(6)), border: Border.all( color: AppColors.znnColor, - width: 1.0, - style: BorderStyle.solid, - )), + ),), child: InkWell( child: FocusableActionDetector( child: SizedBox( - height: 50.0, - width: 150.0, + height: 50, + width: 150, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -167,12 +166,12 @@ class _NewWalletSeedChoiceScreenState extends State { 'assets/svg/ic_export_seed.svg', colorFilter: ColorFilter.mode( Theme.of(context).textTheme.headlineSmall!.color!, - BlendMode.srcIn), - height: 18.0, + BlendMode.srcIn,), + height: 18, ), ), const SizedBox( - width: 15.0, + width: 15, ), Text( 'Export Seed', @@ -221,7 +220,7 @@ class _NewWalletSeedChoiceScreenState extends State { Text( 'I have backed up my seed in a safe location', style: Theme.of(context).textTheme.headlineSmall, - ) + ), ], ); } diff --git a/lib/screens/onboarding/onboarding.dart b/lib/screens/onboarding/onboarding.dart index 9041a189..ee868ba3 100644 --- a/lib/screens/onboarding/onboarding.dart +++ b/lib/screens/onboarding/onboarding.dart @@ -1,8 +1,7 @@ -library onboarding; export 'access_wallet_screen.dart'; export 'create_key_store_screen.dart'; -export 'wallet_success_screen.dart'; +export 'hardware_wallet/hardware_wallet.dart'; export 'import_wallet/import_wallet.dart'; export 'new_wallet/new_wallet.dart'; -export 'hardware_wallet/hardware_wallet.dart'; +export 'wallet_success_screen.dart'; diff --git a/lib/screens/onboarding/wallet_success_screen.dart b/lib/screens/onboarding/wallet_success_screen.dart index 9f4a274c..b1341f85 100644 --- a/lib/screens/onboarding/wallet_success_screen.dart +++ b/lib/screens/onboarding/wallet_success_screen.dart @@ -5,12 +5,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class WalletSuccessScreen extends StatefulWidget { - final int progressBarNumLevels; const WalletSuccessScreen({ this.progressBarNumLevels = 5, - Key? key, - }) : super(key: key); + super.key, + }); + final int progressBarNumLevels; @override State createState() => _WalletSuccessScreenState(); @@ -22,7 +22,7 @@ class _WalletSuccessScreenState extends State { return Scaffold( body: Container( padding: const EdgeInsets.symmetric( - vertical: 30.0, + vertical: 30, ), child: _getSuccessBody(), ), @@ -33,16 +33,16 @@ class _WalletSuccessScreenState extends State { return Column( children: [ Column( - children: [ + children: [ ProgressBar( currentLevel: widget.progressBarNumLevels, numLevels: widget.progressBarNumLevels, ), const SizedBox( - height: 30.0, + height: 30, ), Text( - 'You\'re all set', + "You're all set", style: Theme.of(context).textTheme.headlineLarge, ), kVerticalSpacing, diff --git a/lib/screens/project_details_screen.dart b/lib/screens/project_details_screen.dart index fd233fa1..0cdb243b 100644 --- a/lib/screens/project_details_screen.dart +++ b/lib/screens/project_details_screen.dart @@ -7,16 +7,16 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ProjectDetailsScreen extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; - final AcceleratorProject project; - final PillarInfo? pillarInfo; const ProjectDetailsScreen({ required this.project, required this.pillarInfo, required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; + final AcceleratorProject project; + final PillarInfo? pillarInfo; @override State createState() => _ProjectDetailsScreenState(); @@ -29,17 +29,17 @@ class _ProjectDetailsScreenState extends State { body: SafeArea( child: Container( margin: const EdgeInsets.only( - left: 20.0, - right: 20.0, - bottom: 20.0, + left: 20, + right: 20, + bottom: 20, ), child: Column( - children: [ + children: [ Row( mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ IconButton( - splashRadius: 20.0, + splashRadius: 20, onPressed: () { Navigator.pop(context); }, @@ -68,7 +68,7 @@ class _ProjectDetailsScreenState extends State { RefreshProjectBloc refreshProjectViewModel, ) { return StandardFluidLayout( - children: [ + children: [ FluidCell( width: project.owner.toString() == kSelectedAddress! ? context.layout.value( @@ -115,12 +115,12 @@ class _ProjectDetailsScreenState extends State { Widget _getStreamBuilder() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (RefreshProjectBloc model) { model.refreshProject(widget.project.id); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, RefreshProjectBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -133,7 +133,7 @@ class _ProjectDetailsScreenState extends State { return const SyriusLoadingWidget(); }, ), - viewModelBuilder: () => RefreshProjectBloc(), + viewModelBuilder: RefreshProjectBloc.new, ); } } diff --git a/lib/screens/reset_wallet_screen.dart b/lib/screens/reset_wallet_screen.dart index 3604612b..83470a9c 100644 --- a/lib/screens/reset_wallet_screen.dart +++ b/lib/screens/reset_wallet_screen.dart @@ -5,7 +5,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class ResetWalletScreen extends StatefulWidget { - const ResetWalletScreen({Key? key}) : super(key: key); + const ResetWalletScreen({super.key}); @override State createState() => _ResetWalletScreenState(); @@ -20,24 +20,24 @@ class _ResetWalletScreenState extends State { Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Container( padding: const EdgeInsets.only( - bottom: 10.0, + bottom: 10, ), decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( - width: 4.0, + width: 4, color: AppColors.errorColor, ), ), child: const Padding( - padding: EdgeInsets.all(20.0), + padding: EdgeInsets.all(20), child: Icon( Feather.alert_triangle, color: AppColors.errorColor, - size: 50.0, + size: 50, ), ), ), @@ -48,7 +48,7 @@ class _ResetWalletScreenState extends State { ), kVerticalSpacing, SizedBox( - width: 500.0, + width: 500, child: Text( 'All your wallet data will be erased permanently. Make sure ' 'you have a backup of your mnemonic or Seed Vault & Seed Vault Key before you proceed ' @@ -69,29 +69,29 @@ class _ResetWalletScreenState extends State { }, outlineColor: Colors.white, text: 'Cancel', - minimumSize: const Size(100.0, 40.0), + minimumSize: const Size(100, 40), ), const SizedBox( - width: 20.0, + width: 20, ), MyOutlinedButton( outlineColor: AppColors.errorColor, onPressed: _onResetPressed, text: 'Reset', textColor: AppColors.errorColor, - minimumSize: const Size(100.0, 40.0), - ) + minimumSize: const Size(100, 40), + ), ], ), const SizedBox( - height: 30.0, + height: 30, ), ], ), ); } - void _onResetPressed() async { + Future _onResetPressed() async { NodeUtils.closeEmbeddedNode(); kLastDismissedNotification = kLastNotification; diff --git a/lib/screens/screens.dart b/lib/screens/screens.dart index f0687cce..fb963d2d 100644 --- a/lib/screens/screens.dart +++ b/lib/screens/screens.dart @@ -1,11 +1,11 @@ -library screens; export 'change_wallet_password_screen.dart'; +export 'development_intialization_screen.dart'; export 'dump_mnemonic_screen.dart'; +export 'export/export.dart'; export 'node_management_screen.dart'; +export 'onboarding/onboarding.dart'; export 'project_details_screen.dart'; export 'reset_wallet_screen.dart'; export 'splash_screen.dart'; export 'stepper_screen.dart'; -export 'export/export.dart'; -export 'onboarding/onboarding.dart'; diff --git a/lib/screens/splash_screen.dart b/lib/screens/splash_screen.dart index be2238b1..87c32ca4 100644 --- a/lib/screens/splash_screen.dart +++ b/lib/screens/splash_screen.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:logging/logging.dart'; import 'package:lottie/lottie.dart'; +import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/model.dart'; @@ -14,16 +15,16 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SplashScreen extends StatefulWidget { - static const String route = 'splash-screen'; - - final bool resetWalletFlow; - final bool deleteCacheFlow; const SplashScreen({ this.resetWalletFlow = false, this.deleteCacheFlow = false, - Key? key, - }) : super(key: key); + super.key, + }); + static const String route = 'splash-screen'; + + final bool resetWalletFlow; + final bool deleteCacheFlow; @override State createState() => _SplashScreenState(); @@ -42,12 +43,10 @@ class _SplashScreenState extends State { Widget build(BuildContext context) { return FutureBuilder( future: _composition, - builder: (context, snapshot) { - var composition = snapshot.data; + builder: (BuildContext context, AsyncSnapshot snapshot) { + final LottieComposition? composition = snapshot.data; if (composition != null) { - Future.delayed(composition.duration, () { - _splashInits(); - }); + Future.delayed(composition.duration, _splashInits); return Lottie( composition: composition, repeat: false, @@ -118,15 +117,15 @@ class _SplashScreenState extends State { await Hive.close(); await Future.forEach( kCacheBoxesToBeDeleted, - (boxName) async => await Hive.deleteBoxFromDisk(boxName), + (String boxName) async => Hive.deleteBoxFromDisk(boxName), ); await _deleteWeb3Cache(); } Future _deleteWeb3Cache() async { try { - final web3WalletService = sl(); - for (var pairing in web3WalletService.pairings.value) { + final IWeb3WalletService web3WalletService = sl(); + for (final PairingInfo pairing in web3WalletService.pairings.value) { await web3WalletService.deactivatePairing(topic: pairing.topic); } } catch (e, stackTrace) { diff --git a/lib/screens/stepper_screen.dart b/lib/screens/stepper_screen.dart index 1b3b46c2..f06122d7 100644 --- a/lib/screens/stepper_screen.dart +++ b/lib/screens/stepper_screen.dart @@ -2,23 +2,23 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class StepperScreen extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; - final Widget stepper; const StepperScreen({ required this.stepper, required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; + final Widget stepper; @override Widget build(BuildContext context) { return Scaffold( body: Container( - margin: const EdgeInsets.all(20.0), + margin: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ NotificationWidget( onSeeMorePressed: onStepperNotificationSeeMorePressed, ), @@ -27,24 +27,24 @@ class StepperScreen extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular( - 15.0, + 15, ), ), child: Stack( fit: StackFit.expand, - children: [ + children: [ stepper, Positioned( - top: 0.0, - right: 0.0, + top: 0, + right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ RawMaterialButton( constraints: const BoxConstraints.tightForFinite(), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), shape: const CircleBorder(), onPressed: () { Navigator.pop(context); diff --git a/lib/services/htlc_swaps_service.dart b/lib/services/htlc_swaps_service.dart index ce6b2f8c..7a1b40ee 100644 --- a/lib/services/htlc_swaps_service.dart +++ b/lib/services/htlc_swaps_service.dart @@ -20,16 +20,16 @@ class HtlcSwapsService { bool get isMaxSwapsReached => _htlcSwapsBox!.length >= kMaxP2pSwapsToStore; Future openBoxes(String htlcSwapsBoxSuffix, List cipherKey, - {List? newCipherKey}) async { + {List? newCipherKey,}) async { if (_htlcSwapsBox == null || !_htlcSwapsBox!.isOpen) { _htlcSwapsBox = await Hive.openBox('${kHtlcSwapsBox}_$htlcSwapsBoxSuffix', - encryptionCipher: HiveAesCipher(cipherKey)); + encryptionCipher: HiveAesCipher(cipherKey),); if (newCipherKey != null) { - final values = _htlcSwapsBox!.toMap(); + final Map values = _htlcSwapsBox!.toMap(); await _htlcSwapsBox!.deleteFromDisk(); _htlcSwapsBox = await Hive.openBox( '${kHtlcSwapsBox}_$htlcSwapsBoxSuffix', - encryptionCipher: HiveAesCipher(newCipherKey)); + encryptionCipher: HiveAesCipher(newCipherKey),); _htlcSwapsBox!.putAll(values); _htlcSwapsBox!.flush(); } @@ -39,13 +39,13 @@ class HtlcSwapsService { !_lastCheckedHtlcBlockHeightBox!.isOpen) { _lastCheckedHtlcBlockHeightBox = await Hive.openBox( kLastCheckedHtlcBlockBox, - encryptionCipher: HiveAesCipher(cipherKey)); + encryptionCipher: HiveAesCipher(cipherKey),); if (newCipherKey != null) { - final values = _lastCheckedHtlcBlockHeightBox!.toMap(); + final Map values = _lastCheckedHtlcBlockHeightBox!.toMap(); await _lastCheckedHtlcBlockHeightBox!.deleteFromDisk(); _lastCheckedHtlcBlockHeightBox = await Hive.openBox( kLastCheckedHtlcBlockBox, - encryptionCipher: HiveAesCipher(newCipherKey)); + encryptionCipher: HiveAesCipher(newCipherKey),); _lastCheckedHtlcBlockHeightBox!.putAll(values); _lastCheckedHtlcBlockHeightBox!.flush(); } @@ -70,14 +70,14 @@ class HtlcSwapsService { List getSwapsByState(List states) { return _swapsForCurrentChainId - .where((e) => states.contains(e.state)) + .where((HtlcSwap e) => states.contains(e.state)) .toList(); } HtlcSwap? getSwapByHashLock(String hashLock) { try { return _swapsForCurrentChainId - .firstWhereOrNull((e) => e.hashLock == hashLock); + .firstWhereOrNull((HtlcSwap e) => e.hashLock == hashLock); } on HiveError { return null; } @@ -86,7 +86,7 @@ class HtlcSwapsService { HtlcSwap? getSwapByHtlcId(String htlcId) { try { return _swapsForCurrentChainId.firstWhereOrNull( - (e) => e.initialHtlcId == htlcId || e.counterHtlcId == htlcId); + (HtlcSwap e) => e.initialHtlcId == htlcId || e.counterHtlcId == htlcId,); } on HiveError { return null; } @@ -94,7 +94,7 @@ class HtlcSwapsService { HtlcSwap? getSwapById(String id) { try { - return _swapsForCurrentChainId.firstWhereOrNull((e) => e.id == id); + return _swapsForCurrentChainId.firstWhereOrNull((HtlcSwap e) => e.id == id); } on HiveError { return null; } @@ -105,51 +105,51 @@ class HtlcSwapsService { .get(kLastCheckedHtlcBlockKey, defaultValue: 0); } - Future storeSwap(HtlcSwap swap) async => await _htlcSwapsBox! + Future storeSwap(HtlcSwap swap) async => _htlcSwapsBox! .put( swap.id, jsonEncode(swap.toJson()), ) - .then((_) async => await _pruneSwapsHistoryIfNeeded()); + .then((_) async => _pruneSwapsHistoryIfNeeded()); Future storeLastCheckedHtlcBlockHeight(int height) async => - await _lastCheckedHtlcBlockHeightBox! + _lastCheckedHtlcBlockHeightBox! .put(kLastCheckedHtlcBlockKey, height); Future deleteSwap(String swapId) async => - await _htlcSwapsBox!.delete(swapId); + _htlcSwapsBox!.delete(swapId); Future deleteInactiveSwaps() async => - await _htlcSwapsBox!.deleteAll(_swapsForCurrentChainId - .where((e) => [ + _htlcSwapsBox!.deleteAll(_swapsForCurrentChainId + .where((HtlcSwap e) => [ P2pSwapState.completed, P2pSwapState.unsuccessful, - P2pSwapState.error - ].contains(e.state)) - .map((e) => e.id)); + P2pSwapState.error, + ].contains(e.state),) + .map((HtlcSwap e) => e.id),); List get _swapsForCurrentChainId { return kNodeChainId != null ? _htlcSwapsBox!.values .where( - (e) => HtlcSwap.fromJson(jsonDecode(e)).chainId == kNodeChainId) + (e) => HtlcSwap.fromJson(jsonDecode(e)).chainId == kNodeChainId,) .map((e) => HtlcSwap.fromJson(jsonDecode(e))) .toList() - : []; + : []; } HtlcSwap? _getOldestPrunableSwap() { - final swaps = getAllSwaps() - .where((e) => [P2pSwapState.completed, P2pSwapState.unsuccessful] - .contains(e.state)) + final List swaps = getAllSwaps() + .where((HtlcSwap e) => [P2pSwapState.completed, P2pSwapState.unsuccessful] + .contains(e.state),) .toList(); - swaps.sort((a, b) => b.startTime.compareTo(a.startTime)); + swaps.sort((HtlcSwap a, HtlcSwap b) => b.startTime.compareTo(a.startTime)); return swaps.isNotEmpty ? swaps.last : null; } Future _pruneSwapsHistoryIfNeeded() async { if (_htlcSwapsBox!.length > kMaxP2pSwapsToStore) { - final toBePruned = _getOldestPrunableSwap(); + final HtlcSwap? toBePruned = _getOldestPrunableSwap(); if (toBePruned != null) { await deleteSwap(toBePruned.id); } diff --git a/lib/services/shared_prefs_service.dart b/lib/services/shared_prefs_service.dart index 547d2eb5..03140b9d 100644 --- a/lib/services/shared_prefs_service.dart +++ b/lib/services/shared_prefs_service.dart @@ -25,10 +25,10 @@ class SharedPrefsService { } } - Future close() async => await _sharedPrefsBox!.close(); + Future close() async => _sharedPrefsBox!.close(); Future put(String key, dynamic value) async => - await _sharedPrefsBox!.put( + _sharedPrefsBox!.put( key, value, ); diff --git a/lib/services/web3wallet_service.dart b/lib/services/web3wallet_service.dart index 5b67f2e5..6f1742bf 100644 --- a/lib/services/web3wallet_service.dart +++ b/lib/services/web3wallet_service.dart @@ -24,14 +24,14 @@ class Web3WalletService extends IWeb3WalletService { /// [SessionProposalEvent], [AuthRequest] @override ValueNotifier> pairings = - ValueNotifier>([]); + ValueNotifier>([]); @override ValueNotifier> sessions = - ValueNotifier>([]); + ValueNotifier>([]); @override - ValueNotifier> auth = ValueNotifier>([]); + ValueNotifier> auth = ValueNotifier>([]); - final List _idSessionsApproved = []; + final List _idSessionsApproved = []; @override void create() { @@ -44,8 +44,8 @@ class Web3WalletService extends IWeb3WalletService { name: 's y r i u s', description: 'A wallet for interacting with Zenon Network', url: 'https://zenon.network', - icons: [ - 'https://raw.githubusercontent.com/zenon-network/syrius/master/macos/Runner/Assets.xcassets/AppIcon.appiconset/Icon-MacOS-512x512%402x.png' + icons: [ + 'https://raw.githubusercontent.com/zenon-network/syrius/master/macos/Runner/Assets.xcassets/AppIcon.appiconset/Icon-MacOS-512x512%402x.png', ], ), ); @@ -152,7 +152,7 @@ class Web3WalletService extends IWeb3WalletService { } catch (e, s) { // Catch anything else (not just Exceptions) and log stack Logger('WalletConnectService').log(Level.INFO, - 'disconnectAllParings - Unexpected error: $e, topic $topic\n$s'); + 'disconnectAllParings - Unexpected error: $e, topic $topic\n$s',); } } @@ -186,7 +186,7 @@ class Web3WalletService extends IWeb3WalletService { for (int i = 0; i < pairings.value.length; i++) { await _wcClient!.disconnectSession( topic: pairings.value[i].topic, - reason: Errors.getSdkError(Errors.USER_DISCONNECTED)); + reason: Errors.getSdkError(Errors.USER_DISCONNECTED),); } _idSessionsApproved.clear(); } @@ -208,22 +208,22 @@ class Web3WalletService extends IWeb3WalletService { return _wcClient!.getActiveSessions(); } - void _onRelayClientConnect(var args) async { + Future _onRelayClientConnect(var args) async { Logger('WalletConnectService') .log(Level.INFO, '_onRelayClientConnect triggered', args.toString()); } - void _onRelayClientDisconnect(var args) async { + Future _onRelayClientDisconnect(var args) async { Logger('WalletConnectService') .log(Level.INFO, '_onRelayClientDisconnect triggered', args.toString()); } - void _onRelayClientError(var args) async { + Future _onRelayClientError(var args) async { Logger('WalletConnectService') .log(Level.INFO, '_onRelayClientError triggered', args.toString()); } - void _onSessionsSync(StoreSyncEvent? args) async { + Future _onSessionsSync(StoreSyncEvent? args) async { if (args != null) { Logger('WalletConnectService') .log(Level.INFO, '_onSessionsSync triggered', args.toString()); @@ -231,19 +231,19 @@ class Web3WalletService extends IWeb3WalletService { } } - void _onPairingCreate(PairingEvent? args) async { + Future _onPairingCreate(PairingEvent? args) async { Logger('WalletConnectService') .log(Level.INFO, 'onPairingCreate triggered', args.toString()); sl.get().refreshResults(); } - void _onPairingActivate(PairingActivateEvent? args) async { + Future _onPairingActivate(PairingActivateEvent? args) async { Logger('WalletConnectService') .log(Level.INFO, '_onPairingActivate triggered', args.toString()); sl.get().refreshResults(); } - void _onPairingPing(PairingEvent? args) async { + Future _onPairingPing(PairingEvent? args) async { Logger('WalletConnectService') .log(Level.INFO, '_onPairingPing triggered', args.toString()); } @@ -253,12 +253,12 @@ class Web3WalletService extends IWeb3WalletService { .log(Level.INFO, 'onPairingInvalid triggered', args.toString()); } - void _onPairingDelete(PairingEvent? args) async { + Future _onPairingDelete(PairingEvent? args) async { Logger('WalletConnectService') .log(Level.INFO, '_onPairingDelete triggered', args.toString()); } - void _onPairingsSync(StoreSyncEvent? args) async { + Future _onPairingsSync(StoreSyncEvent? args) async { if (args != null) { Logger('WalletConnectService') .log(Level.INFO, '_onPairingsSync triggered', args.toString()); @@ -266,7 +266,7 @@ class Web3WalletService extends IWeb3WalletService { } } - void _onSessionRequest(SessionRequestEvent? args) async { + Future _onSessionRequest(SessionRequestEvent? args) async { Logger('WalletConnectService') .log(Level.INFO, '_onSessionRequest triggered', args.toString()); } @@ -283,7 +283,7 @@ class Web3WalletService extends IWeb3WalletService { sl.get().refreshResults(); } - void _onSessionProposal(SessionProposalEvent? event) async { + Future _onSessionProposal(SessionProposalEvent? event) async { Logger('WalletConnectService') .log(Level.INFO, '_onSessionProposal triggered', event.toString()); @@ -291,7 +291,7 @@ class Web3WalletService extends IWeb3WalletService { Logger('WalletConnectService') .log(Level.INFO, '_onSessionProposal event', event.params.toJson()); - final dAppMetadata = event.params.proposer.metadata; + final PairingMetadata dAppMetadata = event.params.proposer.metadata; final actionWasAccepted = await showDialogWithNoAndYesOptions( context: globalNavigatorKey.currentContext!, @@ -299,14 +299,13 @@ class Web3WalletService extends IWeb3WalletService { title: 'Approve session', content: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text('Are you sure you want to ' 'connect to ${dAppMetadata.name} ?'), kVerticalSpacing, Image( image: NetworkImage(dAppMetadata.icons.first), - height: 100.0, + height: 100, fit: BoxFit.fitHeight, ), kVerticalSpacing, @@ -314,11 +313,11 @@ class Web3WalletService extends IWeb3WalletService { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text(dAppMetadata.url), LinkIcon( url: dAppMetadata.url, - ) + ), ], ), ], @@ -331,15 +330,15 @@ class Web3WalletService extends IWeb3WalletService { if (!_idSessionsApproved.contains(event.id)) { _idSessionsApproved.add(event.id); try { - ApproveResponse approveResponse = + final ApproveResponse approveResponse = await _approveSession(id: event.id); await _sendSuccessfullyApprovedSessionNotification(dAppMetadata); sessions.value.add(approveResponse.session); } catch (e, stackTrace) { await NotificationUtils.sendNotificationError( - e, 'WalletConnect session approval failed'); + e, 'WalletConnect session approval failed',); Logger('WalletConnectService').log( - Level.INFO, 'onSessionProposal approveResponse', e, stackTrace); + Level.INFO, 'onSessionProposal approveResponse', e, stackTrace,); } } } else { @@ -364,7 +363,7 @@ class Web3WalletService extends IWeb3WalletService { } Future _sendSuccessfullyApprovedSessionNotification( - PairingMetadata dAppMetadata) async { + PairingMetadata dAppMetadata,) async { await sl.get().addNotification( WalletNotification( title: 'Successfully connected to ${dAppMetadata.name}', @@ -377,20 +376,20 @@ class Web3WalletService extends IWeb3WalletService { } Future _approveSession( - {required int id, Map? namespaces}) async { + {required int id, Map? namespaces,}) async { if (!await windowManager.isFocused() || !await windowManager.isVisible()) { windowManager.show(); } namespaces = namespaces ?? - { + { 'zenon': Namespace( accounts: _getWalletAccounts(), - methods: [ + methods: [ 'znn_sign', 'znn_info', 'znn_send', ], - events: ['chainIdChange', 'addressChange'], + events: ['chainIdChange', 'addressChange'], ), }; return _wcClient!.approveSession( @@ -404,7 +403,7 @@ class Web3WalletService extends IWeb3WalletService { List _getWalletAccounts() => kAddressLabelMap.values .map( - (address) => _generateAccount(address, getChainIdentifier()), + (String address) => _generateAccount(address, getChainIdentifier()), ) .toList(); @@ -412,8 +411,8 @@ class Web3WalletService extends IWeb3WalletService { required String changeName, required String newValue, }) async { - final sessionTopics = - pairings.value.fold>([], (previousValue, pairing) { + final List sessionTopics = + pairings.value.fold>([], (List previousValue, PairingInfo pairing) { if (pairing.active) { previousValue.addAll(getSessionsForPairing(pairing.topic).keys); return previousValue; @@ -421,7 +420,7 @@ class Web3WalletService extends IWeb3WalletService { return previousValue; }); - for (String sessionTopic in sessionTopics) { + for (final String sessionTopic in sessionTopics) { _emitDAppEvent( sessionTopic: sessionTopic, changeName: changeName, diff --git a/lib/utils/account_block_utils.dart b/lib/utils/account_block_utils.dart index 72a0bf5b..aac17c4c 100644 --- a/lib/utils/account_block_utils.dart +++ b/lib/utils/account_block_utils.dart @@ -15,24 +15,24 @@ class AccountBlockUtils { Address? address, bool waitForRequiredPlasma = false, }) async { - SyncInfo syncInfo = await zenon!.stats.syncInfo(); - bool nodeIsSynced = (syncInfo.state == SyncState.syncDone || + final SyncInfo syncInfo = await zenon!.stats.syncInfo(); + final bool nodeIsSynced = syncInfo.state == SyncState.syncDone || (syncInfo.targetHeight > 0 && syncInfo.currentHeight > 0 && - (syncInfo.targetHeight - syncInfo.currentHeight) < 20)); + (syncInfo.targetHeight - syncInfo.currentHeight) < 20); if (nodeIsSynced) { // Acquire wallet lock to prevent concurrent access. - final wallet = await kWalletFile!.open(); + final Wallet wallet = await kWalletFile!.open(); try { address ??= Address.parse(kSelectedAddress!); - final walletAccount = await wallet + final WalletAccount walletAccount = await wallet .getAccount(kDefaultAddressList.indexOf(address.toString())); - bool needPlasma = await zenon!.requiresPoW( + final bool needPlasma = await zenon!.requiresPoW( transactionParams, blockSigningKey: walletAccount, ); - bool needReview = kWalletFile!.isHardwareWallet; + final bool needReview = kWalletFile!.isHardwareWallet; if (needPlasma) { await sl @@ -44,7 +44,7 @@ class AccountBlockUtils { final AccountBlockTemplate response = await zenon!.send( transactionParams, currentKeyPair: walletAccount, - generatingPowCallback: (status) async { + generatingPowCallback: (PowStatus status) async { // Wait for plasma to be generated before sending review notification if (needReview && status == PowStatus.done) { await _sendReviewNotification(transactionParams); @@ -89,14 +89,14 @@ class AccountBlockUtils { if (encodedData.length < AbiFunction.encodedSignLength) { return null; } - final eq = const ListEquality().equals; + final bool Function(List? list1, List? list2) eq = const ListEquality().equals; try { - for (final entry in abi.entries) { + for (final Entry entry in abi.entries) { if (eq(AbiFunction.extractSignature(entry.encodeSignature()), - AbiFunction.extractSignature(encodedData))) { - final decoded = + AbiFunction.extractSignature(encodedData),)) { + final List decoded = AbiFunction(entry.name!, entry.inputs!).decode(encodedData); - final Map params = {}; + final Map params = {}; for (int i = 0; i < entry.inputs!.length; i += 1) { params[entry.inputs![i].name!] = decoded[i]; } @@ -112,19 +112,19 @@ class AccountBlockUtils { // Returns a list of AccountBlocks that are newer than a given timestamp. // The list is returned in ascending order. static Future> getAccountBlocksAfterTime( - Address address, int time) async { - final List blocks = []; + Address address, int time,) async { + final List blocks = []; int pageIndex = 0; try { while (true) { - final fetched = await zenon!.ledger.getAccountBlocksByPage(address, - pageIndex: pageIndex, pageSize: 100); + final AccountBlockList fetched = await zenon!.ledger.getAccountBlocksByPage(address, + pageIndex: pageIndex, pageSize: 100,); - final lastBlockConfirmation = fetched.list!.last.confirmationDetail; + final AccountBlockConfirmationDetail? lastBlockConfirmation = fetched.list!.last.confirmationDetail; if (lastBlockConfirmation == null || lastBlockConfirmation.momentumTimestamp <= time) { - for (final block in fetched.list!) { - final confirmation = block.confirmationDetail; + for (final AccountBlock block in fetched.list!) { + final AccountBlockConfirmationDetail? confirmation = block.confirmationDetail; if (confirmation == null || confirmation.momentumTimestamp <= time) { break; @@ -149,10 +149,10 @@ class AccountBlockUtils { } static Future getTimeForAccountBlockHeight( - Address address, int height) async { + Address address, int height,) async { if (height >= 1) { try { - final block = + final AccountBlockList block = await zenon!.ledger.getAccountBlocksByHeight(address, height, 1); if (block.count != null && block.count! > 0) { return block.list?.first.confirmationDetail?.momentumTimestamp; @@ -165,7 +165,7 @@ class AccountBlockUtils { } static Future _sendReviewNotification( - AccountBlockTemplate transactionParams) async { + AccountBlockTemplate transactionParams,) async { await sl.get().addNotification( WalletNotification( title: diff --git a/lib/utils/address_utils.dart b/lib/utils/address_utils.dart index 56f3e378..107a50c2 100644 --- a/lib/utils/address_utils.dart +++ b/lib/utils/address_utils.dart @@ -6,11 +6,11 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/notification_type.dart'; import 'package:zenon_syrius_wallet_flutter/model/database/wallet_notification.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:zenon_syrius_wallet_flutter/utils/node_utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:znn_ledger_dart/znn_ledger_dart.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; @@ -22,15 +22,15 @@ class ZenonAddressUtils { kAddressLabelMap[address] ?? address; static Future generateNewAddress( - {int numAddr = 1, VoidCallback? callback}) async { - final wallet = await kWalletFile!.open(); + {int numAddr = 1, VoidCallback? callback,}) async { + final Wallet wallet = await kWalletFile!.open(); try { await Future.delayed(const Duration(milliseconds: 500)); - List listAddr = []; - int addrListLength = kDefaultAddressList.length; + final List listAddr = []; + final int addrListLength = kDefaultAddressList.length; for (int i = 0; i < numAddr; i++) { - int addrListCounter = addrListLength + i; - WalletAccount walletAccount = await wallet.getAccount(addrListCounter); + final int addrListCounter = addrListLength + i; + final WalletAccount walletAccount = await wallet.getAccount(addrListCounter); Address? address; if (walletAccount is LedgerWalletAccount) { await sl.get().addNotification( @@ -48,10 +48,10 @@ class ZenonAddressUtils { address = await walletAccount.getAddress(); } listAddr.add(address); - Box addressesBox = Hive.box(kAddressesBox); + final Box addressesBox = Hive.box(kAddressesBox); await addressesBox.add(listAddr.elementAt(i).toString()); _initAddresses(addressesBox); - Box addressLabelsBox = Hive.box(kAddressLabelsBox); + final Box addressLabelsBox = Hive.box(kAddressLabelsBox); await addressLabelsBox.put( listAddr.elementAt(i).toString(), 'Address ${kDefaultAddressList.length}', @@ -63,19 +63,19 @@ class ZenonAddressUtils { listAddr.clear(); } catch (e) { await NotificationUtils.sendNotificationError( - e, 'Error while generating new address'); + e, 'Error while generating new address',); } finally { kWalletFile!.close(); } } static Future setAddressLabels() async { - Box addressLabelsBox = await Hive.openBox(kAddressLabelsBox); + final Box addressLabelsBox = await Hive.openBox(kAddressLabelsBox); if (addressLabelsBox.isEmpty) { - for (var address in kDefaultAddressList) { + for (final String? address in kDefaultAddressList) { await addressLabelsBox.put( - address, 'Address ${kDefaultAddressList.indexOf(address) + 1}'); + address, 'Address ${kDefaultAddressList.indexOf(address) + 1}',); } } _initAddressLabels(addressLabelsBox); @@ -92,16 +92,16 @@ class ZenonAddressUtils { } static Future setAddresses(WalletFile? walletFile) async { - Box addressesBox = await Hive.openBox(kAddressesBox); + final Box addressesBox = await Hive.openBox(kAddressesBox); if (addressesBox.isEmpty) { - await walletFile!.access((wallet) async { - for (var element in (await Future.wait( + await walletFile!.access((Wallet wallet) async { + for (final String element in await Future.wait( List>.generate( kNumOfInitialAddresses, - (index) async => + (int index) async => (await (await wallet.getAccount(index)).getAddress()) - .toString()), - ))) { + .toString(),), + )) { addressesBox.add(element); } }); @@ -114,8 +114,8 @@ class ZenonAddressUtils { static void _initAddressLabels(Box box) => kAddressLabelMap = box.keys.toList().fold>( - {}, - (previousValue, key) { + {}, + (Map previousValue, key) { previousValue[key] = box.get(key); return previousValue; }, diff --git a/lib/utils/app_colors.dart b/lib/utils/app_colors.dart index 01a0440b..ea0175f3 100644 --- a/lib/utils/app_colors.dart +++ b/lib/utils/app_colors.dart @@ -1,43 +1,43 @@ import 'package:flutter/material.dart'; class AppColors { - static const znnColor = Color(0xFF4FD166); - static const qsrColor = Color(0xFF005FE3); - static const ztsColor = Color(0xFFF91690); + static const Color znnColor = Color(0xFF4FD166); + static const Color qsrColor = Color(0xFF005FE3); + static const Color ztsColor = Color(0xFFF91690); - static const errorColor = Color.fromRGBO(244, 4, 88, 1.0); + static const Color errorColor = Color.fromRGBO(244, 4, 88, 1); - static const backgroundLight = Color(0xFFEAEAEA); - static const backgroundDark = Color(0xFF1E1E1E); + static const Color backgroundLight = Color(0xFFEAEAEA); + static const Color backgroundDark = Color(0xFF1E1E1E); - static const subtitleColor = Color(0xFFB3B3B3); + static const Color subtitleColor = Color(0xFFB3B3B3); - static const maxAmountBorder = Color(0xFF474747); + static const Color maxAmountBorder = Color(0xFF474747); - static const lightSecondary = Color(0xFFB3B3B3); - static const lightSecondaryContainer = Color(0xFF545454); - static const darkSecondary = Color(0xFF3F3F3F); - static const darkSecondaryContainer = Color.fromRGBO(46, 46, 46, 1.0); + static const Color lightSecondary = Color(0xFFB3B3B3); + static const Color lightSecondaryContainer = Color(0xFF545454); + static const Color darkSecondary = Color(0xFF3F3F3F); + static const Color darkSecondaryContainer = Color.fromRGBO(46, 46, 46, 1); - static const alertNotification = Color(0xFFDAE240); + static const Color alertNotification = Color(0xFFDAE240); - static const accessWalletContainersGray = Color.fromRGBO(46, 46, 46, 1.0); - static const inactiveIconsGray = Color.fromRGBO(51, 51, 51, 1.0); + static const Color accessWalletContainersGray = Color.fromRGBO(46, 46, 46, 1); + static const Color inactiveIconsGray = Color.fromRGBO(51, 51, 51, 1); - static const darkPrimary = Color(0xFF262626); - static const darkPrimaryContainer = Color(0xFF2D2D2D); - static const lightPrimaryContainer = Color(0xFFF4FEFF); + static const Color darkPrimary = Color(0xFF262626); + static const Color darkPrimaryContainer = Color(0xFF2D2D2D); + static const Color lightPrimaryContainer = Color(0xFFF4FEFF); - static const lightDividerColor = Color.fromRGBO(193, 193, 193, 0.8); - static const darkDividerColor = Color(0xFF333333); + static const Color lightDividerColor = Color.fromRGBO(193, 193, 193, 0.8); + static const Color darkDividerColor = Color(0xFF333333); - static const lightTextFormFieldFill = Color(0xFFE4E4E4); - static const darkTextFormFieldFill = Color.fromRGBO(51, 51, 51, 1.0); + static const Color lightTextFormFieldFill = Color(0xFFE4E4E4); + static const Color darkTextFormFieldFill = Color.fromRGBO(51, 51, 51, 1); - static const darkHintTextColor = Color.fromRGBO(99, 99, 99, 1); - static const lightHintTextColor = Color.fromRGBO(179, 179, 179, 1); + static const Color darkHintTextColor = Color.fromRGBO(99, 99, 99, 1); + static const Color lightHintTextColor = Color.fromRGBO(179, 179, 179, 1); - static const seedUnderlineBorderColor = Color.fromRGBO(99, 99, 99, 1); - static const unselectedSeedChoiceColor = Color(0xFF636363); - static const selectedSeedChoiceColor = Color(0xFF292929); + static const Color seedUnderlineBorderColor = Color.fromRGBO(99, 99, 99, 1); + static const Color unselectedSeedChoiceColor = Color(0xFF636363); + static const Color selectedSeedChoiceColor = Color(0xFF292929); } diff --git a/lib/utils/app_theme.dart b/lib/utils/app_theme.dart index 784e4fa2..87b00e36 100644 --- a/lib/utils/app_theme.dart +++ b/lib/utils/app_theme.dart @@ -2,17 +2,17 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; const DividerThemeData kDefaultDividerThemeData = DividerThemeData( - thickness: 1.0, - indent: 0.0, - endIndent: 0.0, - space: 1.0, + thickness: 1, + indent: 0, + endIndent: 0, + space: 1, ); final ButtonStyle kElevatedButtonStyle = ElevatedButton.styleFrom( tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( - 6.0, + 6, ), ), minimumSize: const Size(55, 42), @@ -23,7 +23,7 @@ final ButtonStyle kOutlinedButtonStyle = OutlinedButton.styleFrom( tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( - 6.0, + 6, ), ), side: const BorderSide( @@ -33,58 +33,58 @@ final ButtonStyle kOutlinedButtonStyle = OutlinedButton.styleFrom( ); const TextStyle kDisplaySmallTextStyle = TextStyle( - fontSize: 14.0, + fontSize: 14, fontWeight: FontWeight.w400, ); const TextStyle kBodyLargeTextStyle = TextStyle( - fontSize: 14.0, + fontSize: 14, fontWeight: FontWeight.w400, ); const TextStyle kBodyMediumTextStyle = TextStyle( - fontSize: 12.0, + fontSize: 12, fontWeight: FontWeight.w400, ); const TextStyle kBodySmallTextStyle = TextStyle( - fontSize: 10.0, + fontSize: 10, fontWeight: FontWeight.w300, ); const TextStyle kHeadlineLargeTextStyle = TextStyle( - fontSize: 26.0, + fontSize: 26, fontWeight: FontWeight.w500, ); const TextStyle kHeadlineMediumTextStyle = TextStyle( - fontSize: 24.0, + fontSize: 24, fontWeight: FontWeight.w500, ); const TextStyle kHeadlineSmallTextStyle = TextStyle( - fontSize: 16.0, + fontSize: 16, fontWeight: FontWeight.w400, ); const TextStyle kOutlinedButtonTextStyle = TextStyle( - fontSize: 16.0, + fontSize: 16, fontWeight: FontWeight.w400, ); const TextStyle kTextButtonTextStyle = TextStyle( - fontSize: 10.0, + fontSize: 10, fontWeight: FontWeight.w400, ); const TextStyle kTitleMediumTextStyle = TextStyle( - fontSize: 12.0, + fontSize: 12, fontWeight: FontWeight.w400, color: AppColors.subtitleColor, ); const TextStyle kTitleSmallTextStyle = TextStyle( - fontSize: 10.0, + fontSize: 10, fontWeight: FontWeight.w400, color: AppColors.subtitleColor, ); @@ -93,11 +93,11 @@ final TextButtonThemeData kTextButtonThemeData = TextButtonThemeData( style: TextButton.styleFrom( textStyle: kTextButtonTextStyle, tapTargetSize: MaterialTapTargetSize.shrinkWrap, - minimumSize: const Size(55.0, 25.0), + minimumSize: const Size(55, 25), backgroundColor: AppColors.znnColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( - 8.0, + 8, ), ), ), @@ -105,7 +105,7 @@ final TextButtonThemeData kTextButtonThemeData = TextButtonThemeData( const TextStyle kHintTextStyle = TextStyle( fontWeight: FontWeight.w400, - fontSize: 14.0, + fontSize: 14, ); const TextStyle kTextFormFieldErrorStyle = TextStyle( @@ -113,19 +113,21 @@ const TextStyle kTextFormFieldErrorStyle = TextStyle( ); const OutlineInputBorder kOutlineInputBorder = OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(5.0)), + borderRadius: BorderRadius.all(Radius.circular(5)), ); class AppTheme { + + AppTheme._(); static final ThemeData lightTheme = ThemeData( useMaterial3: true, hoverColor: AppColors.lightTextFormFieldFill, textButtonTheme: kTextButtonThemeData, outlinedButtonTheme: OutlinedButtonThemeData( style: kOutlinedButtonStyle.copyWith( - foregroundColor: MaterialStateProperty.resolveWith( - (states) { - if (states.contains(MaterialState.disabled)) { + foregroundColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return Colors.black38; } return Colors.black; @@ -160,13 +162,13 @@ class AppTheme { errorBorder: kOutlineInputBorder.copyWith( borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), focusedErrorBorder: kOutlineInputBorder.copyWith( borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), ), @@ -200,46 +202,46 @@ class AppTheme { ), unselectedWidgetColor: AppColors.lightSecondaryContainer, switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + thumbColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), - trackColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + trackColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), ), radioTheme: RadioThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), ), checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; @@ -251,7 +253,7 @@ class AppTheme { secondary: AppColors.lightSecondary, secondaryContainer: AppColors.lightSecondaryContainer, error: AppColors.errorColor, - ).copyWith(background: AppColors.backgroundLight), + ).copyWith(surface: AppColors.backgroundLight), ); static final ThemeData darkTheme = ThemeData( @@ -260,9 +262,9 @@ class AppTheme { textButtonTheme: kTextButtonThemeData, outlinedButtonTheme: OutlinedButtonThemeData( style: kOutlinedButtonStyle.copyWith( - foregroundColor: MaterialStateProperty.resolveWith( - (states) { - if (states.contains(MaterialState.disabled)) { + foregroundColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return Colors.white38; } return Colors.white; @@ -300,13 +302,13 @@ class AppTheme { errorBorder: kOutlineInputBorder.copyWith( borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), focusedErrorBorder: kOutlineInputBorder.copyWith( borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), ), @@ -340,46 +342,46 @@ class AppTheme { ), unselectedWidgetColor: AppColors.darkSecondaryContainer, switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + thumbColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), - trackColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + trackColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), ), radioTheme: RadioThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; }), ), checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return AppColors.znnColor; } return null; @@ -391,8 +393,6 @@ class AppTheme { secondary: AppColors.darkSecondary, secondaryContainer: AppColors.darkSecondaryContainer, error: AppColors.errorColor, - ).copyWith(background: AppColors.backgroundDark), + ).copyWith(surface: AppColors.backgroundDark), ); - - AppTheme._(); } diff --git a/lib/utils/clipboard_utils.dart b/lib/utils/clipboard_utils.dart index f48f4a37..38e26565 100644 --- a/lib/utils/clipboard_utils.dart +++ b/lib/utils/clipboard_utils.dart @@ -24,12 +24,12 @@ class ClipboardUtils { text: stringValue, ), ).then((_) => - ToastUtils.showToast(context, 'Copied', color: AppColors.znnColor)); + ToastUtils.showToast(context, 'Copied', color: AppColors.znnColor),); } static void pasteToClipboard( - BuildContext context, Function(String) callback) { - Clipboard.getData('text/plain').then((value) async { + BuildContext context, Function(String) callback,) { + Clipboard.getData('text/plain').then((ClipboardData? value) async { if (value != null) { callback(value.text!); } else { diff --git a/lib/utils/color_utils.dart b/lib/utils/color_utils.dart index 08c9a27d..e9443ac2 100644 --- a/lib/utils/color_utils.dart +++ b/lib/utils/color_utils.dart @@ -15,7 +15,7 @@ class ColorUtils { } static String _getHexCodeFromTokenZts(TokenStandard tokenStandard) { - List bytes = + final List bytes = tokenStandard.getBytes().sublist(tokenStandard.getBytes().length - 3); return BytesUtils.bytesToHex(bytes); } diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 676a0238..80bedd8c 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -6,26 +6,26 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; // WalletConnect const String kWcProjectId = '6106aa8c2f308b338f31465bef999a1f'; const String kZenonNameSpace = 'zenon'; -const walletConnectDirName = 'walletconnect'; +const String walletConnectDirName = 'walletconnect'; // Dimensions -const double kAmountSuffixHeight = 25.0; -const double kAmountSuffixWidth = 40.0; -const double kAmountSuffixRadius = 5.0; -const double kContentPadding = 8.0; -const double kSeedWordCellWidth = 200.0; -const double kPasswordInputFieldWidth = 360.0; +const double kAmountSuffixHeight = 25; +const double kAmountSuffixWidth = 40; +const double kAmountSuffixRadius = 5; +const double kContentPadding = 8; +const double kSeedWordCellWidth = 200; +const double kPasswordInputFieldWidth = 360; // Size widgets -const Size kLoadingButtonMinSize = Size(120.0, 40.0); -const Size kSettingsButtonMinSize = Size(100.0, 35.0); +const Size kLoadingButtonMinSize = Size(120, 40); +const Size kSettingsButtonMinSize = Size(100, 35); const SizedBox kVerticalSpacing = SizedBox( - height: 15.0, + height: 15, ); const SizedBox kSpacingBetweenActionButtons = SizedBox( - width: 70.0, + width: 70, ); -const Size kAcceleratorProgressBarSize = Size(300.0, 10.0); +const Size kAcceleratorProgressBarSize = Size(300, 10); // Wallet version const String kWalletVersion = '0.2.2'; @@ -42,7 +42,7 @@ const String kKeyStoreBox = 'key_store_box'; const String kHtlcSwapsBox = 'htlc_swaps_box'; const String kLastCheckedHtlcBlockBox = 'last_checked_htlc_block_box'; -const List kCacheBoxesToBeDeleted = [ +const List kCacheBoxesToBeDeleted = [ kFavoriteTokensBox, kAddressesBox, kAddressLabelsBox, @@ -50,7 +50,7 @@ const List kCacheBoxesToBeDeleted = [ kRecipientAddressBox, kSharedPrefsBox, kNodesBox, - kLastCheckedHtlcBlockBox + kLastCheckedHtlcBlockBox, ]; // Wallet file name @@ -82,7 +82,7 @@ const String kP2pAtomicUnlockKey = 'p2p_atomic_unlock_key'; const String kP2pAutoReclaimKey = 'p2p_auto_reclaim_key'; const String kLastCheckedHtlcBlockKey = 'last_checked_htlc_block_key'; -const double kDefaultBorderOutlineWidth = 1.0; +const double kDefaultBorderOutlineWidth = 1; const double kStandardChartNumDays = 7; const int kAddressLabelMaxLength = 80; @@ -108,12 +108,12 @@ const int kAmountInputMaxCharacterLength = 21; const int kSecondsPerMomentum = 10; const int kMaxP2pSwapsToStore = 500; -const List kNormalUsersPlasmaRequirements = [ +const List kNormalUsersPlasmaRequirements = [ kStakePlasmaAmountNeeded, kDelegatePlasmaAmountNeeded, ]; -const List kPowerUsersPlasmaRequirements = [ +const List kPowerUsersPlasmaRequirements = [ kPillarPlasmaAmountNeeded, kSentinelPlasmaAmountNeeded, kIssueTokenPlasmaAmountNeeded, @@ -123,7 +123,7 @@ const String kEmbeddedNode = 'Embedded Node'; const String kLocalhostDefaultNodeUrl = 'ws://127.0.0.1:$kDefaultPort'; const int kDefaultPort = 35998; -const List kWalletActions = [ +const List kWalletActions = [ 'pillar', 'sentinel', 'delegation', @@ -188,7 +188,7 @@ const String kThemeModeKey = 'theme_mode_key'; const ThemeMode kDefaultThemeMode = ThemeMode.dark; const TextScaling kDefaultTextScaling = TextScaling.system; -const kBlockTypeColorMap = { +const Map kBlockTypeColorMap = { BlockTypeEnum.userReceive: AppColors.darkHintTextColor, BlockTypeEnum.userSend: AppColors.lightHintTextColor, }; @@ -201,7 +201,7 @@ const Duration kProjectVotingPeriod = Duration(days: 14); const Duration kEmbeddedConnectionDelay = Duration(seconds: 30); // Tabs -const List kTabsWithTextTitles = [ +const List kTabsWithTextTitles = [ Tabs.dashboard, Tabs.transfer, Tabs.pillars, diff --git a/lib/utils/device_utils.dart b/lib/utils/device_utils.dart index d68bfac5..f1192f7d 100644 --- a/lib/utils/device_utils.dart +++ b/lib/utils/device_utils.dart @@ -6,7 +6,7 @@ import 'package:package_info_plus/package_info_plus.dart'; class DeviceUtils { static Future> getDeviceInfo() async { - DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); if (Platform.isLinux) { return _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo); } @@ -16,7 +16,7 @@ class DeviceUtils { if (Platform.isMacOS) { return _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo); } - return {'info': 'device not supported'}; + return {'info': 'device not supported'}; } static Map _readLinuxDeviceInfo(LinuxDeviceInfo data) { @@ -58,8 +58,8 @@ class DeviceUtils { } static Future> getPackageInfo() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - return { + final PackageInfo packageInfo = await PackageInfo.fromPlatform(); + return { 'appName': packageInfo.appName, 'packageName': packageInfo.packageName, 'appVersion': packageInfo.version, @@ -68,9 +68,9 @@ class DeviceUtils { } static Future> getGitInfo() async { - final head = await rootBundle.loadString('.git/HEAD'); - final branchName = head.split('/').last; - final commitHash = await rootBundle.loadString('.git/ORIG_HEAD'); - return {'branchName': branchName, 'commitHash': commitHash}; + final String head = await rootBundle.loadString('.git/HEAD'); + final String branchName = head.split('/').last; + final String commitHash = await rootBundle.loadString('.git/ORIG_HEAD'); + return {'branchName': branchName, 'commitHash': commitHash}; } } diff --git a/lib/utils/extensions.dart b/lib/utils/extensions.dart index 9d63bf7c..b0140d64 100644 --- a/lib/utils/extensions.dart +++ b/lib/utils/extensions.dart @@ -16,12 +16,12 @@ extension StringExtensions on String { } return BigInt.parse(this + ''.padRight(decimals, '0')); } - List parts = split('.'); + final List parts = split('.'); return BigInt.parse(parts[0] + (parts[1].length > decimals ? parts[1].substring(0, decimals) - : parts[1].padRight(decimals, '0'))); + : parts[1].padRight(decimals, '0')),); } String abs() => this; @@ -48,8 +48,8 @@ extension ZipTwoLists on List { List zip(List smallerList) { return fold( [], - (previousValue, element) { - int elementIndex = indexOf(element); + (List previousValue, element) { + final int elementIndex = indexOf(element); previousValue.add(element); if (elementIndex < smallerList.length) { previousValue.add( @@ -64,7 +64,7 @@ extension ZipTwoLists on List { extension ShortString on String { String get short { - final longString = this; + final String longString = this; return '${longString.substring(0, 6)}...' '${longString.substring(longString.length - 6)}'; } @@ -73,8 +73,8 @@ extension ShortString on String { extension LedgerErrorExtensions on LedgerError { String toFriendlyString() { return when( - connectionError: (origMessage) => origMessage, - responseError: (statusWord) => _mapStatusWord(statusWord)); + connectionError: (String origMessage) => origMessage, + responseError: _mapStatusWord,); } String _mapStatusWord(StatusWord statusWord) { @@ -119,4 +119,4 @@ extension LedgerErrorExtensions on LedgerError { return 'Unknown error, please make sure the device is unlocked'; } } -} +} \ No newline at end of file diff --git a/lib/utils/file_utils.dart b/lib/utils/file_utils.dart index b9a93c84..14c7a3b5 100644 --- a/lib/utils/file_utils.dart +++ b/lib/utils/file_utils.dart @@ -3,7 +3,7 @@ import 'dart:io'; class FileUtils { static Future deleteFile(String path) async { try { - final file = File(path); + final File file = File(path); if (file.existsSync()) { await file.delete(); } else { @@ -16,7 +16,7 @@ class FileUtils { static Future deleteDirectory(String path) async { try { - final directory = Directory(path); + final Directory directory = Directory(path); if (directory.existsSync()) { await directory.delete(recursive: true); } else { diff --git a/lib/utils/format_utils.dart b/lib/utils/format_utils.dart index b1c0b9b9..e6dbae36 100644 --- a/lib/utils/format_utils.dart +++ b/lib/utils/format_utils.dart @@ -8,9 +8,9 @@ class FormatUtils { static List getAmountTextInputFormatters( String replacementString, ) => - [ + [ FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*?$'), - replacementString: replacementString), + replacementString: replacementString,), FilteringTextInputFormatter.deny( RegExp(r'^0\d+'), replacementString: replacementString, @@ -20,7 +20,7 @@ class FormatUtils { static List getPlasmaAmountTextInputFormatters( String replacementString, ) => - [ + [ FilteringTextInputFormatter.digitsOnly, FilteringTextInputFormatter.deny( RegExp(r'^0\d+'), @@ -32,17 +32,17 @@ class FormatUtils { static List decodeHexString(String input) => HEX.decode(input); static String formatDate(int timestampMillis, - {String dateFormat = kDefaultDateFormat}) { - DateTime date = DateTime.fromMillisecondsSinceEpoch(timestampMillis); + {String dateFormat = kDefaultDateFormat,}) { + final DateTime date = DateTime.fromMillisecondsSinceEpoch(timestampMillis); return DateFormat(dateFormat).format(date); } static String extractNameFromEnum(T enumValue) { - String valueName = enumValue.toString().split('.')[1]; - if (RegExp(r'^[a-z]+[A-Z]+').hasMatch(valueName)) { - List parts = valueName - .split(RegExp(r'(?<=[a-z])(?=[A-Z])')) - .map((e) => e.toLowerCase()) + final String valueName = enumValue.toString().split('.')[1]; + if (RegExp('^[a-z]+[A-Z]+').hasMatch(valueName)) { + final List parts = valueName + .split(RegExp('(?<=[a-z])(?=[A-Z])')) + .map((String e) => e.toLowerCase()) .toList(); parts.first = parts.first.capitalize(); return parts.join(' '); @@ -61,7 +61,7 @@ class FormatUtils { } static String formatData(int transactionMillis) { - int currentMillis = DateTime.now().millisecondsSinceEpoch; + final int currentMillis = DateTime.now().millisecondsSinceEpoch; if (currentMillis - transactionMillis <= const Duration(days: 1).inMilliseconds) { return formatDataShort(currentMillis - transactionMillis); @@ -70,7 +70,7 @@ class FormatUtils { } static String formatDataShort(int i) { - Duration duration = Duration(milliseconds: i); + final Duration duration = Duration(milliseconds: i); if (duration.inHours > 0) { return '${duration.inHours} h ago'; } diff --git a/lib/utils/functions.dart b/lib/utils/functions.dart index 7cb1d350..6209a165 100644 --- a/lib/utils/functions.dart +++ b/lib/utils/functions.dart @@ -5,31 +5,31 @@ import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class Signature { - String signature; - String publicKey; Signature(this.signature, this.publicKey); + String signature; + String publicKey; } Future walletSign(List message) async { - final wallet = await kWalletFile!.open(); + final Wallet wallet = await kWalletFile!.open(); try { - final walletAccount = await wallet + final WalletAccount walletAccount = await wallet .getAccount(kDefaultAddressList.indexOf(kSelectedAddress)); - List publicKey = await walletAccount.getPublicKey(); - List signature = await walletAccount.sign( + final List publicKey = await walletAccount.getPublicKey(); + final List signature = await walletAccount.sign( Uint8List.fromList( message, ), ); return Signature( - BytesUtils.bytesToHex(signature), BytesUtils.bytesToHex(publicKey)); + BytesUtils.bytesToHex(signature), BytesUtils.bytesToHex(publicKey),); } finally { kWalletFile!.close(); } } Future loadJsonFromAssets(String filePath) async { - String jsonString = await rootBundle.loadString(filePath); + final String jsonString = await rootBundle.loadString(filePath); return jsonDecode(jsonString); } \ No newline at end of file diff --git a/lib/utils/global.dart b/lib/utils/global.dart index 88930941..5b82cc6d 100644 --- a/lib/utils/global.dart +++ b/lib/utils/global.dart @@ -1,7 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:zenon_syrius_wallet_flutter/model/model.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; ValueNotifier kLastWalletConnectUriNotifier = ValueNotifier(null); @@ -20,14 +20,14 @@ bool kWalletInitCompleted = false; WalletFile? kWalletFile; -List kDbNodes = []; -List kDefaultAddressList = []; +List kDbNodes = []; +List kDefaultAddressList = []; -Map kAddressLabelMap = {}; +Map kAddressLabelMap = {}; Tabs? kCurrentPage; -final List kTabs = [...kTabsWithTextTitles, ...kTabsWithIconTitles]; +final List kTabs = [...kTabsWithTextTitles, ...kTabsWithIconTitles]; WalletNotification? kLastNotification; WalletNotification? kLastDismissedNotification; @@ -36,7 +36,7 @@ int? kNumOfPillars; bool kEmbeddedNodeRunning = false; -final List kTabsWithIconTitles = [ +final List kTabsWithIconTitles = [ if (kWcProjectId.isNotEmpty) Tabs.walletConnect, Tabs.accelerator, Tabs.help, @@ -47,15 +47,15 @@ final List kTabsWithIconTitles = [ Tabs.lock, ]; -final List kDisabledTabs = [ +final List kDisabledTabs = [ Tabs.generation, Tabs.sync, ]; -List kDefaultNodes = [ +List kDefaultNodes = [ kEmbeddedNode, kLocalhostDefaultNodeUrl, ]; // Community supplied public rpc nodes -List kDefaultCommunityNodes = []; \ No newline at end of file +List kDefaultCommunityNodes = []; \ No newline at end of file diff --git a/lib/utils/init_utils.dart b/lib/utils/init_utils.dart index 3d2ad2ec..937d7119 100644 --- a/lib/utils/init_utils.dart +++ b/lib/utils/init_utils.dart @@ -9,8 +9,8 @@ import 'package:zenon_syrius_wallet_flutter/services/shared_prefs_service.dart'; import 'package:zenon_syrius_wallet_flutter/utils/address_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/node_utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/widget_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; @@ -69,8 +69,8 @@ class InitUtils { ); static Future initWalletAfterDecryption(List cipherKey) async { - final walletVersion = Version.parse(sharedPrefsService! - .get(kWalletVersionKey, defaultValue: kWalletVersion)); + final Version walletVersion = Version.parse(sharedPrefsService! + .get(kWalletVersionKey, defaultValue: kWalletVersion),); await ZenonAddressUtils.setAddresses(kWalletFile); await ZenonAddressUtils.setAddressLabels(); await ZenonAddressUtils.setDefaultAddress(); @@ -81,7 +81,7 @@ class InitUtils { await kWalletFile!.access((Wallet wallet) async { await htlcSwapsService!.openBoxes(WalletUtils.baseAddress.toString(), (wallet as KeyStore).getKeyPair().getPrivateKey()!, - newCipherKey: cipherKey); + newCipherKey: cipherKey,); }); } else { await htlcSwapsService! @@ -92,13 +92,13 @@ class InitUtils { } static Future _openFavoriteTokensBox() async => - await Hive.openBox(kFavoriteTokensBox); + Hive.openBox(kFavoriteTokensBox); static Future _openNotificationsBox() async => - await Hive.openBox(kNotificationsBox); + Hive.openBox(kNotificationsBox); static Future _openRecipientBox() async => - await Hive.openBox(kRecipientAddressBox); + Hive.openBox(kRecipientAddressBox); static Future _setWalletVersion() async => sharedPrefsService!.put( kWalletVersionKey, diff --git a/lib/utils/input_validators.dart b/lib/utils/input_validators.dart index 2e847934..3d36e651 100644 --- a/lib/utils/input_validators.dart +++ b/lib/utils/input_validators.dart @@ -1,8 +1,8 @@ +import 'package:convert/convert.dart'; import 'package:logging/logging.dart'; import 'package:validators/validators.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; -import 'package:convert/convert.dart'; class InputValidators { static String kEVMAddressRegex = r'^(0x)([a-fA-F0-9]){40}$'; @@ -90,7 +90,7 @@ class InputValidators { } } - BigInt inputNum = value.extractDecimals(decimals); + final BigInt inputNum = value.extractDecimals(decimals); if (value.contains('.') && value.split('.')[1].length > decimals) { return 'Inputted number has too many decimals'; @@ -116,7 +116,7 @@ class InputValidators { return 'Error'; } } - return 'Value can\'t be empty'; + return "Value can't be empty"; } static String? checkAddress(String? value) { @@ -142,9 +142,9 @@ class InputValidators { if (value.length < 8) { return 'Password not strong enough'; } - String pattern = + const String pattern = r'''^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[`~!@#$%^&*()\-_=+\[\]\{\}\\|;:",<.>\/\?']).{8,}$'''; - RegExp regExp = RegExp(pattern); + final RegExp regExp = RegExp(pattern); if (regExp.hasMatch(value)) { return null; } @@ -207,7 +207,7 @@ class InputValidators { static Future checkSecret(HtlcInfo htlc, String? value) async { if (value != null) { try { - final preimageCheck = htlc.hashType == htlcHashTypeSha3 + final Hash preimageCheck = htlc.hashType == htlcHashTypeSha3 ? Hash.digest(hex.decode(value)) : Hash.fromBytes(await Crypto.sha256Bytes(hex.decode(value))); diff --git a/lib/utils/navigation_utils.dart b/lib/utils/navigation_utils.dart index da5d1bbc..59986014 100644 --- a/lib/utils/navigation_utils.dart +++ b/lib/utils/navigation_utils.dart @@ -7,10 +7,10 @@ import 'package:zenon_syrius_wallet_flutter/model/model.dart'; class NavigationUtils { static Future openUrl(String url) async { - if (!RegExp(r'^http').hasMatch(url)) { + if (!RegExp('^http').hasMatch(url)) { url = 'http://$url'; } - var uri = Uri.parse(url); + final Uri uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri); } else { @@ -47,6 +47,6 @@ class NavigationUtils { static void popRepeated(context, int times) { int count = 0; - Navigator.popUntil(context, (route) => count++ == times); + Navigator.popUntil(context, (Route route) => count++ == times); } } diff --git a/lib/utils/network_utils.dart b/lib/utils/network_utils.dart index d1413e3c..e65518a8 100644 --- a/lib/utils/network_utils.dart +++ b/lib/utils/network_utils.dart @@ -2,25 +2,24 @@ import 'dart:io'; class NetworkUtils { static Future getLocalIpAddress( - InternetAddressType internetAddressType) async { - final interfaces = await NetworkInterface.list( + InternetAddressType internetAddressType,) async { + final List interfaces = await NetworkInterface.list( type: internetAddressType, - includeLoopback: false, - includeLinkLocal: true); + includeLinkLocal: true,); try { - NetworkInterface vpnInterface = - interfaces.firstWhere((element) => element.name == 'tun0'); + final NetworkInterface vpnInterface = + interfaces.firstWhere((NetworkInterface element) => element.name == 'tun0'); return vpnInterface.addresses.first.address; } on StateError { try { - NetworkInterface interface = - interfaces.firstWhere((element) => element.name == 'wlan0'); + final NetworkInterface interface = + interfaces.firstWhere((NetworkInterface element) => element.name == 'wlan0'); return interface.addresses.first.address; } catch (e) { try { - NetworkInterface interface = interfaces.firstWhere((element) => - !(element.name == 'tun0' || element.name == 'wlan0')); + final NetworkInterface interface = interfaces.firstWhere((NetworkInterface element) => + !(element.name == 'tun0' || element.name == 'wlan0'),); return interface.addresses.first.address; } catch (e) { return e.toString(); diff --git a/lib/utils/node_utils.dart b/lib/utils/node_utils.dart index d7f9f53c..d3a1cb2c 100644 --- a/lib/utils/node_utils.dart +++ b/lib/utils/node_utils.dart @@ -18,7 +18,7 @@ int _kHeight = 0; class NodeUtils { static Future establishConnectionToNode(String url) async { - bool connectionStatus = await zenon!.wsClient.initialize( + final bool connectionStatus = await zenon!.wsClient.initialize( url, retry: false, ); @@ -28,7 +28,7 @@ class NodeUtils { static Future getNodeChainIdentifier() async { int nodeChainId = 1; try { - await zenon!.ledger.getFrontierMomentum().then((value) { + await zenon!.ledger.getFrontierMomentum().then((Momentum value) { nodeChainId = value.chainIdentifier; }); } catch (e, stackTrace) { @@ -58,7 +58,7 @@ class NodeUtils { ); // If the message is null, it means that the isolate has closed - Completer embeddedStoppedCompleter = Completer(); + final Completer embeddedStoppedCompleter = Completer(); sl(instanceName: 'embeddedStoppedStream').listen( (message) { kEmbeddedNodeRunning = false; @@ -84,7 +84,7 @@ class NodeUtils { static initWebSocketClient() async { addOnWebSocketConnectedCallback(); - var url = kCurrentNode == kEmbeddedNode + final String url = kCurrentNode == kEmbeddedNode ? kLocalhostDefaultNodeUrl : kCurrentNode ?? ''; bool connected = false; @@ -100,7 +100,7 @@ class NodeUtils { static Future addOnWebSocketConnectedCallback() async { zenon!.wsClient - .addOnConnectionEstablishedCallback((allResponseBroadcaster) async { + .addOnConnectionEstablishedCallback((Stream?> allResponseBroadcaster) async { kNodeChainId = await getNodeChainIdentifier(); await _getSubscriptionForMomentums(); await _getSubscriptionForAllAccountEvents(); @@ -108,7 +108,7 @@ class NodeUtils { sl().autoReceive(); Future.delayed(const Duration(seconds: 30)) - .then((value) async => await NotificationUtils.sendNodeSyncingNotification()); + .then((value) async => NotificationUtils.sendNodeSyncingNotification()); _initListenForUnreceivedAccountBlocks(allResponseBroadcaster); }); } @@ -116,7 +116,7 @@ class NodeUtils { static Future getUnreceivedTransactions() async { await Future.forEach( kDefaultAddressList, - (address) async => await getUnreceivedTransactionsByAddress( + (String? address) async => getUnreceivedTransactionsByAddress( Address.parse(address!), ), ); @@ -125,14 +125,14 @@ class NodeUtils { static Future getUnreceivedTransactionsByAddress( Address address, ) async { - List unreceivedBlocks = + final List unreceivedBlocks = (await zenon!.ledger.getUnreceivedBlocksByAddress( address, )) .list!; if (unreceivedBlocks.isNotEmpty) { - for (AccountBlock unreceivedBlock in unreceivedBlocks) { + for (final AccountBlock unreceivedBlock in unreceivedBlocks) { if (sharedPrefsService!.get( kAutoReceiveKey, defaultValue: kAutoReceiveDefaultValue, @@ -144,18 +144,18 @@ class NodeUtils { } static Future checkForLocalTimeDiscrepancy( - String warningMessage) async { - const maxAllowedDiscrepancy = Duration(minutes: 5); + String warningMessage,) async { + const Duration maxAllowedDiscrepancy = Duration(minutes: 5); try { - final syncInfo = await zenon!.stats.syncInfo(); - bool nodeIsSynced = (syncInfo.state == SyncState.syncDone || + final SyncInfo syncInfo = await zenon!.stats.syncInfo(); + final bool nodeIsSynced = syncInfo.state == SyncState.syncDone || (syncInfo.targetHeight > 0 && syncInfo.currentHeight > 0 && - (syncInfo.targetHeight - syncInfo.currentHeight) < 20)); + (syncInfo.targetHeight - syncInfo.currentHeight) < 20); if (nodeIsSynced) { - final frontierTime = + final int frontierTime = (await zenon!.ledger.getFrontierMomentum()).timestamp; - final timeDifference = (frontierTime - DateTimeUtils.unixTimeNow).abs(); + final int timeDifference = (frontierTime - DateTimeUtils.unixTimeNow).abs(); if (timeDifference > maxAllowedDiscrepancy.inSeconds) { await NotificationUtils.sendNotificationError( Exception('Local time discrepancy detected.'), @@ -177,16 +177,16 @@ class NodeUtils { event['method'] == 'ledger.subscription' && sharedPrefsService! .get(kAutoReceiveKey, defaultValue: kAutoReceiveDefaultValue)) { - for (var i = 0; i < event['params']['result'].length; i += 1) { - var tx = event['params']['result'][i]; + for (int i = 0; i < event['params']['result'].length; i += 1) { + final tx = event['params']['result'][i]; if (tx.containsKey('toAddress') && kDefaultAddressList.contains(tx['toAddress'])) { - var hash = Hash.parse(tx['hash']); + final Hash hash = Hash.parse(tx['hash']); sl().addHash(hash); } } - Map result = (event['params']['result'] as List).first; + final Map result = (event['params']['result'] as List).first; if (!result.containsKey('blockType') && result['height'] != null && (_kHeight == 0 || result['height'] >= _kHeight + 1)) { @@ -202,23 +202,23 @@ class NodeUtils { } static Future _getSubscriptionForMomentums() async => - await zenon!.subscribe.toMomentums(); + zenon!.subscribe.toMomentums(); static Future _getSubscriptionForAllAccountEvents() async => - await zenon!.subscribe.toAllAccountBlocks(); + zenon!.subscribe.toAllAccountBlocks(); static Future loadDbNodes() async { if (!Hive.isBoxOpen(kNodesBox)) { await Hive.openBox(kNodesBox); } - Box nodesBox = Hive.box(kNodesBox); + final Box nodesBox = Hive.box(kNodesBox); if (kDbNodes.isNotEmpty) { kDbNodes.clear(); } kDbNodes.addAll(nodesBox.values); // Handle the case in which some default nodes were deleted // so they can't be found in the cache - String? currentNode = kCurrentNode; + final String? currentNode = kCurrentNode; if (currentNode != null && !kDefaultNodes.contains(currentNode) && !kDbNodes.contains(currentNode)) { @@ -227,12 +227,12 @@ class NodeUtils { } static Future setNode() async { - String? savedNode = sharedPrefsService!.get(kSelectedNodeKey); + final String? savedNode = sharedPrefsService!.get(kSelectedNodeKey); kCurrentNode = savedNode; if (savedNode == kEmbeddedNode) { // First we need to check if the node is not already running - bool isConnectionEstablished = + final bool isConnectionEstablished = await NodeUtils.establishConnectionToNode(kLocalhostDefaultNodeUrl); if (isConnectionEstablished == false) { // Acquire WakeLock @@ -240,9 +240,9 @@ class NodeUtils { WakelockPlus.enable(); } // Initialize local full node - await Isolate.spawn(EmbeddedNode.runNode, [''], + await Isolate.spawn(EmbeddedNode.runNode, [''], onExit: - sl(instanceName: 'embeddedStoppedPort').sendPort); + sl(instanceName: 'embeddedStoppedPort').sendPort,); kEmbeddedNodeRunning = true; } diff --git a/lib/utils/notification_utils.dart b/lib/utils/notification_utils.dart index 8f81afcd..50e0ba3e 100644 --- a/lib/utils/notification_utils.dart +++ b/lib/utils/notification_utils.dart @@ -3,6 +3,7 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/model.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:znn_sdk_dart/src/model/stats.dart'; class NotificationUtils { static Future sendNotificationError( @@ -22,7 +23,7 @@ class NotificationUtils { kLastNotification?.timestamp != kLastDismissedNotification?.timestamp; static Future sendNodeSyncingNotification() async { - final syncInfo = await zenon!.stats.syncInfo(); + final SyncInfo syncInfo = await zenon!.stats.syncInfo(); if (syncInfo.targetHeight == 0 || syncInfo.currentHeight == 0 || (syncInfo.targetHeight - syncInfo.currentHeight) > 20) { diff --git a/lib/utils/notifiers/notifiers.dart b/lib/utils/notifiers/notifiers.dart index f0ac7d78..425ad121 100644 --- a/lib/utils/notifiers/notifiers.dart +++ b/lib/utils/notifiers/notifiers.dart @@ -1,4 +1,3 @@ -library notifiers; export 'app_theme_notifier.dart'; export 'default_address_notifier.dart'; diff --git a/lib/utils/notifiers/text_scaling_notifier.dart b/lib/utils/notifiers/text_scaling_notifier.dart index 4ba13161..626c6b89 100644 --- a/lib/utils/notifiers/text_scaling_notifier.dart +++ b/lib/utils/notifiers/text_scaling_notifier.dart @@ -12,22 +12,22 @@ class TextScalingNotifier extends ChangeNotifier { } } - getTextScaleFactor(BuildContext context) { + double getTextScaleFactor(BuildContext context) { switch (_currentTextScaling) { case TextScaling.system: - return MediaQuery.of(context).textScaleFactor; + return MediaQuery.of(context).textScaler.scale(1); case TextScaling.normal: - return 1.0; + return 1; case TextScaling.small: return 0.8; case TextScaling.large: return 1.5; case TextScaling.huge: - return 2.0; + return 2; case null: - return 1.0; + return 1; } } - get currentTextScaling => _currentTextScaling; + TextScaling? get currentTextScaling => _currentTextScaling; } diff --git a/lib/utils/pair.dart b/lib/utils/pair.dart index 4795d61a..86e627fb 100644 --- a/lib/utils/pair.dart +++ b/lib/utils/pair.dart @@ -1,6 +1,33 @@ -class Pair { +import 'package:equatable/equatable.dart'; + +class Pair extends Equatable{ + /// Creates a [Pair] instance + Pair(this.first, this.second); + + /// Constructor to specify deserialization methods for generic types + factory Pair.fromJson( + Map json, + T1 Function(Object? json) fromJsonT1, + T2 Function(Object? json) fromJsonT2, + ) => + Pair( + fromJsonT1(json['first']), + fromJsonT2(json['second']), + ); + final T1 first; final T2 second; - Pair(this.first, this.second); + @override + List get props => [first, second]; + + /// A function to serialize generic types + Map toJson( + Object? Function(T1 value) toJsonT1, + Object? Function(T2 value) toJsonT2, + ) => + { + 'first': toJsonT1(first), + 'second': toJsonT2(second), + }; } diff --git a/lib/utils/toast_utils.dart b/lib/utils/toast_utils.dart index e51e34bb..725c0629 100644 --- a/lib/utils/toast_utils.dart +++ b/lib/utils/toast_utils.dart @@ -7,11 +7,9 @@ class ToastUtils { static void showToast(BuildContext context, String message, {Color? color}) { if (_timer == null || !_timer!.isActive) { - final overlay = _getOverlayEntry(message, color); + final OverlayEntry overlay = _getOverlayEntry(message, color); Overlay.of(context).insert(overlay); - _timer = Timer(const Duration(seconds: 3), () { - overlay.remove(); - }); + _timer = Timer(const Duration(seconds: 3), overlay.remove); } } @@ -19,26 +17,26 @@ class ToastUtils { return OverlayEntry( builder: (_) => TweenAnimationBuilder( duration: const Duration(milliseconds: 200), - tween: Tween(begin: 0.0, end: 1.0), + tween: Tween(begin: 0, end: 1), builder: (_, double opacity, __) { return Opacity( opacity: opacity, child: Padding( - padding: const EdgeInsets.only(bottom: 50.0), + padding: const EdgeInsets.only(bottom: 50), child: Container( alignment: Alignment.bottomCenter, child: Material( - elevation: 6.0, + elevation: 6, color: color, surfaceTintColor: Colors.black, - borderRadius: BorderRadius.circular(50.0), + borderRadius: BorderRadius.circular(50), child: Padding( - padding: const EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0), + padding: const EdgeInsets.fromLTRB(20, 15, 20, 15), child: Text( message, textAlign: TextAlign.center, style: - const TextStyle(fontSize: 14.0, color: Colors.white), + const TextStyle(fontSize: 14, color: Colors.white), ), ), ), diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 1a696982..34ef0978 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -13,14 +13,14 @@ export 'format_utils.dart'; export 'global.dart'; export 'init_utils.dart'; export 'input_validators.dart'; -export 'wallet_utils.dart'; export 'navigation_utils.dart'; export 'network_utils.dart'; export 'node_utils.dart'; export 'notification_utils.dart'; +export 'notifiers/notifiers.dart'; export 'pair.dart'; export 'toast_utils.dart'; export 'utils.dart'; +export 'wallet_utils.dart'; export 'widget_utils.dart'; export 'zts_utils.dart'; -export 'notifiers/notifiers.dart'; diff --git a/lib/utils/wallet_file.dart b/lib/utils/wallet_file.dart index 9b8358b2..c65792b7 100644 --- a/lib/utils/wallet_file.dart +++ b/lib/utils/wallet_file.dart @@ -3,29 +3,31 @@ import 'dart:io'; import 'package:hex/hex.dart'; import 'package:mutex/mutex.dart'; +import 'package:path/path.dart' as path; import 'package:znn_ledger_dart/znn_ledger_dart.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; -import 'package:path/path.dart' as path; abstract class WalletFile { + + WalletFile(this._path); final String _path; static Future decrypt(String walletPath, String password) async { - final encrypted = await WalletFile.read(walletPath); + final EncryptedFile encrypted = await WalletFile.read(walletPath); final walletType = encrypted.metadata != null ? encrypted.metadata![walletTypeKey] : null; if (walletType == null || walletType == keyStoreWalletType) { - return await KeyStoreWalletFile.decrypt(walletPath, password); + return KeyStoreWalletFile.decrypt(walletPath, password); } else if (walletType == ledgerWalletType) { - return await LedgerWalletFile.decrypt(walletPath, password); + return LedgerWalletFile.decrypt(walletPath, password); } else { throw WalletException( - 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported'); + 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported',); } } static Future read(String walletPath) async { - final file = File(walletPath); + final File file = File(walletPath); if (!file.existsSync()) { throw WalletException('Given wallet path does not exist ($walletPath)'); } @@ -33,15 +35,13 @@ abstract class WalletFile { } static Future write(String walletPath, String password, List data, - {Map? metadata}) async { - final file = File(walletPath); - final encrypted = + {Map? metadata,}) async { + final File file = File(walletPath); + final EncryptedFile encrypted = await EncryptedFile.encrypt(data, password, metadata: metadata); file.writeAsString(json.encode(encrypted), mode: FileMode.writeOnly); } - WalletFile(this._path); - String get walletPath => _path; String get walletType; @@ -55,7 +55,7 @@ abstract class WalletFile { void close(); Future access(Future Function(Wallet) accessSection) async { - final wallet = await open(); + final Wallet wallet = await open(); try { return await accessSection(wallet); } finally { @@ -64,15 +64,17 @@ abstract class WalletFile { } Future changePassword( - String currentPassword, String newPassword) async { - final file = await WalletFile.read(walletPath); - final decrypted = await file.decrypt(currentPassword); + String currentPassword, String newPassword,) async { + final EncryptedFile file = await WalletFile.read(walletPath); + final List decrypted = await file.decrypt(currentPassword); await WalletFile.write(walletPath, newPassword, decrypted, - metadata: file.metadata); + metadata: file.metadata,); } } class KeyStoreWalletFile extends WalletFile { + + KeyStoreWalletFile._internal(super._path, this._walletSeed); final Mutex _lock = Mutex(); final String _walletSeed; KeyStore? _keyStore; @@ -81,29 +83,27 @@ class KeyStoreWalletFile extends WalletFile { KeyStoreManager(walletPath: znnDefaultWalletDirectory); static Future create(String mnemonic, String password, - {String? name}) async { - KeyStore wallet = KeyStore.fromMnemonic(mnemonic); - KeyStoreDefinition walletDefinition = + {String? name,}) async { + final KeyStore wallet = KeyStore.fromMnemonic(mnemonic); + final KeyStoreDefinition walletDefinition = await keyStoreWalletManager.saveKeyStore(wallet, password, name: name); return KeyStoreWalletFile._internal( - walletDefinition.walletId, wallet.entropy); + walletDefinition.walletId, wallet.entropy,); } static Future decrypt( - String walletPath, String password) async { - final encrypted = await WalletFile.read(walletPath); + String walletPath, String password,) async { + final EncryptedFile encrypted = await WalletFile.read(walletPath); if (encrypted.metadata != null && encrypted.metadata![walletTypeKey] != null && encrypted.metadata![walletTypeKey] != keyStoreWalletType) { throw WalletException( - 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported'); + 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported',); } - final decrypted = await encrypted.decrypt(password); + final List decrypted = await encrypted.decrypt(password); return KeyStoreWalletFile._internal(walletPath, HEX.encode(decrypted)); } - KeyStoreWalletFile._internal(super._path, this._walletSeed); - @override String get walletType => keyStoreWalletType; @@ -126,12 +126,14 @@ class KeyStoreWalletFile extends WalletFile { } @override - void close() async { + Future close() async { if (_lock.isLocked) _lock.release(); } } class LedgerWalletFile extends WalletFile { + + LedgerWalletFile._internal(super._path, this._walletName); final Mutex _lock = Mutex(); final String _walletName; LedgerWallet? _wallet; @@ -139,7 +141,7 @@ class LedgerWalletFile extends WalletFile { static final LedgerWalletManager ledgerWalletManager = LedgerWalletManager(); static Future _connect(String walletIdOrName) async { - for (var walletDefinition + for (final WalletDefinition walletDefinition in await ledgerWalletManager.getWalletDefinitions()) { if (walletDefinition.walletId == walletIdOrName || walletDefinition.walletName == walletIdOrName) { @@ -149,21 +151,21 @@ class LedgerWalletFile extends WalletFile { } throw const LedgerError.connectionError( origMessage: - 'Cannot find the hardware device, please connect/unlock the device on which the wallet is initialized'); + 'Cannot find the hardware device, please connect/unlock the device on which the wallet is initialized',); } static Future create(String walletId, String password, - {String? walletName}) async { - LedgerWallet wallet = await _connect(walletId); + {String? walletName,}) async { + final LedgerWallet wallet = await _connect(walletId); try { - final baseAddress = (await (await wallet.getAccount()).getAddress()); + final Address baseAddress = await (await wallet.getAccount()).getAddress(); walletName ??= baseAddress.toString(); - final walletPath = path.join(znnDefaultWalletDirectory.path, walletName); + final String walletPath = path.join(znnDefaultWalletDirectory.path, walletName); await WalletFile.write(walletPath, password, utf8.encode(walletName), - metadata: { + metadata: { baseAddressKey: baseAddress.toString(), - walletTypeKey: ledgerWalletType - }); + walletTypeKey: ledgerWalletType, + },); return LedgerWalletFile._internal(walletPath, walletName); } finally { await wallet.disconnect(); @@ -171,19 +173,17 @@ class LedgerWalletFile extends WalletFile { } static Future decrypt( - String walletPath, String password) async { - final encrypted = await WalletFile.read(walletPath); + String walletPath, String password,) async { + final EncryptedFile encrypted = await WalletFile.read(walletPath); if (encrypted.metadata == null || encrypted.metadata![walletTypeKey] != ledgerWalletType) { throw WalletException( - 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported'); + 'Wallet type (${encrypted.metadata![walletTypeKey]}) is not supported',); } - final decrypted = await encrypted.decrypt(password); + final List decrypted = await encrypted.decrypt(password); return LedgerWalletFile._internal(walletPath, utf8.decode(decrypted)); } - LedgerWalletFile._internal(super._path, this._walletName); - @override String get walletType => ledgerWalletType; @@ -206,7 +206,7 @@ class LedgerWalletFile extends WalletFile { } @override - void close() async { + Future close() async { if (_wallet != null) { try { await _wallet!.disconnect(); diff --git a/lib/utils/wallet_utils.dart b/lib/utils/wallet_utils.dart index d6f7f0c1..5feadd8b 100644 --- a/lib/utils/wallet_utils.dart +++ b/lib/utils/wallet_utils.dart @@ -1,18 +1,18 @@ import 'package:hive/hive.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_file.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class WalletUtils { - static get baseAddress { + static Address get baseAddress { return Address.parse(kDefaultAddressList.first!); } static Future decryptWalletFile( - String walletPath, String password) async { - return await WalletFile.decrypt(walletPath, password); + String walletPath, String password,) async { + return WalletFile.decrypt(walletPath, password); } static Future createLedgerWalletFile( @@ -21,7 +21,7 @@ class WalletUtils { String? walletName, }) async { kWalletFile = await LedgerWalletFile.create(walletId, password, - walletName: walletName); + walletName: walletName,); kWalletPath = kWalletFile!.walletPath; await _storeWalletPath(kWalletFile!.walletPath); } @@ -38,17 +38,17 @@ class WalletUtils { } static Future _storeWalletPath(String? walletPath) async { - Box keyStoreBox = await Hive.openBox(kKeyStoreBox); + final Box keyStoreBox = await Hive.openBox(kKeyStoreBox); await keyStoreBox.put(0, walletPath); } static Future setWalletPath() async { if (kWalletPath == null) { - Box keyStoreBox = await Hive.openBox(kKeyStoreBox); + final Box keyStoreBox = await Hive.openBox(kKeyStoreBox); if (keyStoreBox.isEmpty) { // Here we check if the key store path is saved in another place // and we copy that value, if it exists - String? keyStorePath = sharedPrefsService!.get(kEntropyFilePathKey); + final String? keyStorePath = sharedPrefsService!.get(kEntropyFilePathKey); if (keyStorePath != null) { keyStoreBox.add(keyStorePath); kWalletPath = keyStoreBox.values.first; diff --git a/lib/utils/widget_utils.dart b/lib/utils/widget_utils.dart index 6fb3c377..0e7e8061 100644 --- a/lib/utils/widget_utils.dart +++ b/lib/utils/widget_utils.dart @@ -11,12 +11,12 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class WidgetUtils { static void setThemeMode(BuildContext context) { - AppThemeNotifier appThemeNotifier = Provider.of( + final AppThemeNotifier appThemeNotifier = Provider.of( context, listen: false, ); - ThemeMode savedThemeMode = ThemeMode.values.firstWhere( - (element) => element.toString() == sharedPrefsService!.get(kThemeModeKey), + final ThemeMode savedThemeMode = ThemeMode.values.firstWhere( + (ThemeMode element) => element.toString() == sharedPrefsService!.get(kThemeModeKey), orElse: () => kDefaultThemeMode, ); if (appThemeNotifier.currentThemeMode != savedThemeMode) { @@ -25,13 +25,13 @@ class WidgetUtils { } static void setTextScale(BuildContext context) { - TextScalingNotifier textScalingNotifier = Provider.of( + final TextScalingNotifier textScalingNotifier = Provider.of( context, listen: false, ); - TextScaling savedTextScaling = TextScaling.values.firstWhere( - (element) => + final TextScaling savedTextScaling = TextScaling.values.firstWhere( + (TextScaling element) => element.toString() == sharedPrefsService!.get(kTextScalingKey), orElse: () => kDefaultTextScaling, ); @@ -47,7 +47,7 @@ class WidgetUtils { Address? address, BuildContext context, ) { - TextStyle? textStyle = address != null && address.isEmbedded() + final TextStyle? textStyle = address != null && address.isEmbedded() ? Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.znnColor, fontWeight: FontWeight.bold, diff --git a/lib/utils/zts_utils.dart b/lib/utils/zts_utils.dart index 2e027256..22cf0ba7 100644 --- a/lib/utils/zts_utils.dart +++ b/lib/utils/zts_utils.dart @@ -4,7 +4,7 @@ import 'package:hive/hive.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; -final List kDualCoin = [ +final List kDualCoin = [ kZnnCoin, kQsrCoin, ]; @@ -36,15 +36,15 @@ final Token kQsrCoin = Token( true, ); -final Map kCoinIdColor = { +final Map kCoinIdColor = { kZnnCoin.tokenStandard: AppColors.znnColor, kQsrCoin.tokenStandard: AppColors.qsrColor, }; bool isTrustedToken(String tokenStandard) { - return [ + return [ znnTokenStandard, qsrTokenStandard, - ...Hive.box(kFavoriteTokensBox).values + ...Hive.box(kFavoriteTokensBox).values, ].contains(tokenStandard); } diff --git a/lib/widgets/charts/pillar_rewards_chart.dart b/lib/widgets/charts/pillar_rewards_chart.dart index 200fc20e..871eadf0 100644 --- a/lib/widgets/charts/pillar_rewards_chart.dart +++ b/lib/widgets/charts/pillar_rewards_chart.dart @@ -1,19 +1,18 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PillarRewardsChart extends StatefulWidget { - final RewardHistoryList? rewardsHistory; const PillarRewardsChart( this.rewardsHistory, { - Key? key, - }) : super(key: key); + super.key, + }); + final RewardHistoryList? rewardsHistory; @override State createState() => PillarRewardsChartState(); @@ -23,9 +22,6 @@ class PillarRewardsChartState extends State { @override Widget build(BuildContext context) { return StandardChart( - yValuesInterval: _getMaxValueOfZnnRewards() > kNumOfChartLeftSideTitles - ? _getMaxValueOfZnnRewards() / kNumOfChartLeftSideTitles - : null, maxY: _getMaxValueOfZnnRewards() < 1.0 ? _getMaxValueOfZnnRewards().toDouble() : _getMaxValueOfZnnRewards().ceilToDouble(), @@ -43,13 +39,13 @@ class PillarRewardsChartState extends State { List _getRewardsSpots() => List.generate( widget.rewardsHistory!.list.length, - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getRewardsByIndex(index).toDouble(), ), ); - List _linesBarData() => [ + List _linesBarData() => [ StandardLineChartBarData( color: AppColors.znnColor, spots: _getRewardsSpots(), @@ -66,7 +62,7 @@ class PillarRewardsChartState extends State { num _getMaxValueOfZnnRewards() { BigInt? max = widget.rewardsHistory!.list.first.znnAmount; - for (var element in widget.rewardsHistory!.list) { + for (final RewardHistoryEntry element in widget.rewardsHistory!.list) { if (element.znnAmount > max!) { max = element.znnAmount; } diff --git a/lib/widgets/charts/sentinel_rewards_chart.dart b/lib/widgets/charts/sentinel_rewards_chart.dart index 51d42034..0cd6a2a5 100644 --- a/lib/widgets/charts/sentinel_rewards_chart.dart +++ b/lib/widgets/charts/sentinel_rewards_chart.dart @@ -3,19 +3,18 @@ import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SentinelRewardsChart extends StatefulWidget { - final RewardHistoryList? rewardsHistory; const SentinelRewardsChart( this.rewardsHistory, { - Key? key, - }) : super(key: key); + super.key, + }); + final RewardHistoryList? rewardsHistory; @override State createState() { @@ -27,9 +26,6 @@ class _SentinelRewardsChart extends State { @override Widget build(BuildContext context) { return StandardChart( - yValuesInterval: _getMaxValueOfRewards() > kNumOfChartLeftSideTitles - ? _getMaxValueOfRewards() / kNumOfChartLeftSideTitles - : null, maxY: _getMaxValueOfRewards() < 1.0 ? _getMaxValueOfRewards().toDouble() : _getMaxValueOfRewards().ceilToDouble(), @@ -46,7 +42,7 @@ class _SentinelRewardsChart extends State { List _getZnnRewardsSpots() => List.generate( widget.rewardsHistory!.list.length, - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getRewardsByIndex(index, kZnnCoin.tokenStandard).toDouble(), ), @@ -54,13 +50,13 @@ class _SentinelRewardsChart extends State { List _getQsrRewardsSpots() => List.generate( widget.rewardsHistory!.list.length, - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getRewardsByIndex(index, kQsrCoin.tokenStandard).toDouble(), ), ); - List _linesBarData() => [ + List _linesBarData() => [ StandardLineChartBarData( color: AppColors.znnColor, spots: _getZnnRewardsSpots(), @@ -90,12 +86,12 @@ class _SentinelRewardsChart extends State { } num _getMaxValueOfRewards() { - num maxZnn = _getMaxValueOfZnnRewards() + final num maxZnn = _getMaxValueOfZnnRewards() .addDecimals( coinDecimals, ) .toNum(); - num maxQsr = _getMaxValueOfQsrRewards() + final num maxQsr = _getMaxValueOfQsrRewards() .addDecimals( coinDecimals, ) @@ -105,7 +101,7 @@ class _SentinelRewardsChart extends State { BigInt _getMaxValueOfZnnRewards() { BigInt max = widget.rewardsHistory!.list.first.znnAmount; - for (var element in widget.rewardsHistory!.list) { + for (final RewardHistoryEntry element in widget.rewardsHistory!.list) { if (element.znnAmount > max) { max = element.znnAmount; } @@ -115,7 +111,7 @@ class _SentinelRewardsChart extends State { BigInt _getMaxValueOfQsrRewards() { BigInt max = widget.rewardsHistory!.list.first.qsrAmount; - for (var element in widget.rewardsHistory!.list) { + for (final RewardHistoryEntry element in widget.rewardsHistory!.list) { if (element.qsrAmount > max) { max = element.qsrAmount; } diff --git a/lib/widgets/charts/staking_rewards_chart.dart b/lib/widgets/charts/staking_rewards_chart.dart index 8daf8b76..5ca0bd64 100644 --- a/lib/widgets/charts/staking_rewards_chart.dart +++ b/lib/widgets/charts/staking_rewards_chart.dart @@ -1,19 +1,18 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StakingRewardsChart extends StatefulWidget { - final RewardHistoryList? rewardsHistory; const StakingRewardsChart( this.rewardsHistory, { - Key? key, - }) : super(key: key); + super.key, + }); + final RewardHistoryList? rewardsHistory; @override State createState() => _StakingRewardsChart(); @@ -23,9 +22,6 @@ class _StakingRewardsChart extends State { @override Widget build(BuildContext context) { return StandardChart( - yValuesInterval: _getMaxValueOfQsrRewards() > kNumOfChartLeftSideTitles - ? _getMaxValueOfQsrRewards() / kNumOfChartLeftSideTitles - : null, maxY: _getMaxValueOfQsrRewards() < 1.0 ? _getMaxValueOfQsrRewards().toDouble() : _getMaxValueOfQsrRewards().ceilToDouble(), @@ -43,13 +39,13 @@ class _StakingRewardsChart extends State { List _getRewardsSpots() => List.generate( widget.rewardsHistory!.list.length, - (index) => FlSpot( + (int index) => FlSpot( index.toDouble(), _getRewardsByIndex(index).toDouble(), ), ); - _linesBarData() => [ + List _linesBarData() => [ StandardLineChartBarData( color: AppColors.qsrColor, spots: _getRewardsSpots(), @@ -66,7 +62,7 @@ class _StakingRewardsChart extends State { num _getMaxValueOfQsrRewards() { BigInt max = widget.rewardsHistory!.list.first.qsrAmount; - for (var element in widget.rewardsHistory!.list) { + for (final RewardHistoryEntry element in widget.rewardsHistory!.list) { if (element.qsrAmount > max) { max = element.qsrAmount; } diff --git a/lib/widgets/main_app_container.dart b/lib/widgets/main_app_container.dart index e7e93d36..85d62ec4 100644 --- a/lib/widgets/main_app_container.dart +++ b/lib/widgets/main_app_container.dart @@ -6,6 +6,7 @@ import 'package:clipboard_watcher/clipboard_watcher.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:logging/logging.dart'; @@ -17,6 +18,7 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/handlers/htlc_swaps_handler.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/model/model.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/clipboard_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; @@ -50,15 +52,15 @@ enum Tabs { } class MainAppContainer extends StatefulWidget { + const MainAppContainer({ + super.key, + this.redirectedFromWalletSuccess = false, + }); + final bool redirectedFromWalletSuccess; static const String route = 'main-app-container'; - const MainAppContainer({ - Key? key, - this.redirectedFromWalletSuccess = false, - }) : super(key: key); - @override State createState() => _MainAppContainerState(); } @@ -76,12 +78,14 @@ class _MainAppContainerState extends State TransferTabChild? _transferTabChild; bool _initialUriIsHandled = false; - final NodeSyncStatusBloc _netSyncStatusBloc = NodeSyncStatusBloc(); - final _appLinks = AppLinks(); + final AppLinks _appLinks = AppLinks(); final FocusNode _focusNode = FocusNode( skipTraversal: true, canRequestFocus: false, ); + final NodeSyncStatusCubit _nodeSyncStatusCubit = NodeSyncStatusCubit( + zenon: zenon!, + ); @override void initState() { @@ -90,8 +94,6 @@ class _MainAppContainerState extends State ClipboardUtils.toggleClipboardWatcherStatus(); - _netSyncStatusBloc.getDataPeriodically(); - _transferTabChild = TransferTabChild(); _initTabController(); _animationController = AnimationController( @@ -99,7 +101,7 @@ class _MainAppContainerState extends State duration: const Duration(milliseconds: 500), ); _animationController.repeat(reverse: true); - _animation = Tween(begin: 1.0, end: 3.0).animate(_animationController); + _animation = Tween(begin: 1, end: 3).animate(_animationController); kCurrentPage = kWalletInitCompleted ? Tabs.dashboard : Tabs.lock; _initLockBlock(); _handleIncomingLinks(); @@ -111,14 +113,15 @@ class _MainAppContainerState extends State @override Widget build(BuildContext context) { return Consumer( - builder: (context, textScalingNotifier, child) => MediaQuery( + builder: (BuildContext context, TextScalingNotifier textScalingNotifier, Widget? child) => MediaQuery( data: MediaQuery.of(context).copyWith( - textScaleFactor: textScalingNotifier.getTextScaleFactor(context), + textScaler: TextScaler.linear( + textScalingNotifier.getTextScaleFactor(context),), ), child: Scaffold( body: Container( margin: const EdgeInsets.all( - 20.0, + 20, ), child: Column( children: [ @@ -142,7 +145,7 @@ class _MainAppContainerState extends State Expanded( child: ClipRRect( borderRadius: BorderRadius.circular( - 15.0, + 15, ), child: Container( child: _getCurrentPageContainer(), @@ -158,52 +161,52 @@ class _MainAppContainerState extends State } Widget _getDesktopNavigationContainer() { - Color borderColor = NotificationUtils.shouldShowNotification() + final Color borderColor = NotificationUtils.shouldShowNotification() ? kLastNotification!.getColor() : Colors.transparent; return AnimatedBuilder( animation: _animationController, - builder: (context, widget) { + builder: (BuildContext context, Widget? widget) { return Row( - children: [ + children: [ Expanded( child: Container( alignment: Alignment.center, decoration: BoxDecoration( borderRadius: const BorderRadius.all( Radius.circular( - 15.0, + 15, ), ), boxShadow: (borderColor != Colors.transparent) - ? [ + ? [ BoxShadow( color: borderColor, blurRadius: _animation.value, spreadRadius: _animation.value, - ) + ), ] - : [ + : [ const BoxShadow( color: Colors.transparent, - ) + ), ], ), child: Material( color: Theme.of(context).colorScheme.primary, borderRadius: const BorderRadius.all( Radius.circular( - 15.0, + 15, ), ), child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 12.0, + horizontal: 12, ), child: Focus( focusNode: _focusNode, - onKeyEvent: (focusNode, KeyEvent event) { + onKeyEvent: (FocusNode focusNode, KeyEvent event) { if ((event.physicalKey == PhysicalKeyboardKey.tab || event.physicalKey == PhysicalKeyboardKey.enter || @@ -223,7 +226,7 @@ class _MainAppContainerState extends State .textTheme .headlineSmall! .copyWith( - fontSize: 15.0, + fontSize: 15, ), labelColor: Theme.of(context).textTheme.headlineSmall!.color, @@ -233,7 +236,7 @@ class _MainAppContainerState extends State } }, labelPadding: const EdgeInsets.symmetric( - vertical: 5.0, + vertical: 5, ), indicator: UnderlineTabIndicator( borderSide: BorderSide( @@ -242,10 +245,10 @@ class _MainAppContainerState extends State : _isIconTabSelected() ? Colors.transparent : AppColors.znnColor, - width: 2.0, + width: 2, ), ), - dividerHeight: 0.0, + dividerHeight: 0, controller: _tabController, tabs: _getTabs(), ), @@ -261,7 +264,7 @@ class _MainAppContainerState extends State ); } - void _onNavigateToLock() async { + Future _onNavigateToLock() async { if (kWalletFile != null) kWalletFile!.close(); kWalletFile = null; _navigateToLockTimer?.cancel(); @@ -279,10 +282,11 @@ class _MainAppContainerState extends State List _getTextTabs() { return kTabsWithTextTitles .map( - (e) => e == Tabs.p2pSwap + (Tabs e) => e == Tabs.p2pSwap ? const Tab(text: 'P2P Swap') : Tab( - text: FormatUtils.extractNameFromEnum(e).capitalize()), + text: FormatUtils.extractNameFromEnum(e).capitalize(), + ), ) .toList(); } @@ -293,18 +297,20 @@ class _MainAppContainerState extends State Tab( child: SvgPicture.asset( 'assets/svg/walletconnect-logo.svg', - width: 24.0, + width: 24, fit: BoxFit.fitWidth, colorFilter: _isTabSelected(Tabs.walletConnect) ? const ColorFilter.mode(AppColors.znnColor, BlendMode.srcIn) : ColorFilter.mode( - Theme.of(context).iconTheme.color!, BlendMode.srcIn), + Theme.of(context).iconTheme.color!, + BlendMode.srcIn, + ), ), ), Tab( child: Icon( MaterialCommunityIcons.rocket, - size: 24.0, + size: 24, color: _isTabSelected(Tabs.accelerator) ? AppColors.znnColor : Theme.of(context).iconTheme.color, @@ -313,7 +319,7 @@ class _MainAppContainerState extends State Tab( child: Icon( Icons.info, - size: 24.0, + size: 24, color: _isTabSelected(Tabs.help) ? AppColors.znnColor : Theme.of(context).iconTheme.color, @@ -322,7 +328,7 @@ class _MainAppContainerState extends State Tab( child: Icon( Icons.notifications, - size: 24.0, + size: 24, color: _isTabSelected(Tabs.notifications) ? AppColors.znnColor : Theme.of(context).iconTheme.color, @@ -331,7 +337,7 @@ class _MainAppContainerState extends State Tab( child: Icon( Icons.settings, - size: 24.0, + size: 24, color: _isTabSelected(Tabs.settings) ? AppColors.znnColor : Theme.of(context).iconTheme.color, @@ -341,52 +347,40 @@ class _MainAppContainerState extends State child: _getGenerationStatus(), ), Tab( - child: _getSyncStatus(), + child: BlocProvider.value( + value: _nodeSyncStatusCubit, + child: const NodeSyncStatusIcon(), + ), ), Tab( child: _isTabSelected(Tabs.lock) ? Icon( Icons.lock, - size: 24.0, + size: 24, color: _isTabSelected(Tabs.lock) ? AppColors.znnColor : Theme.of(context).iconTheme.color, ) : Icon( MaterialCommunityIcons.lock_open_variant, - size: 24.0, + size: 24, color: Theme.of(context).iconTheme.color, ), ), ]; } - Widget _getSyncStatus() { - return StreamBuilder( - stream: _netSyncStatusBloc.stream, - builder: (_, snapshot) { - if (snapshot.hasError) { - return _getSyncingStatusIcon(SyncState.unknown); - } else if (snapshot.hasData) { - return _getSyncingStatusIcon(snapshot.data!.state, snapshot.data); - } else { - return _getSyncingStatusIcon(SyncState.unknown); - } - }, - ); - } - Widget _getGenerationStatus() { return StreamBuilder( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData && snapshot.data == PowStatus.generating) { return Tooltip( message: 'Generating Plasma', child: Lottie.asset( 'assets/lottie/ic_anim_plasma_generation.json', fit: BoxFit.contain, - width: 30.0, + width: 30, repeat: true, ), ); @@ -402,148 +396,11 @@ class _MainAppContainerState extends State ); } - Widget _getSyncingStatusIcon(SyncState syncState, [SyncInfo? syncInfo]) { - String message = 'Connected and synced'; - - if (syncState != SyncState.notEnoughPeers && - syncState != SyncState.syncDone && - syncState != SyncState.syncing && - syncState != SyncState.unknown) { - syncState = SyncState.unknown; - } - - if (syncState == SyncState.unknown) { - message = 'Not ready'; - return Tooltip( - message: message, - child: Icon( - Icons.sync_disabled, - size: 24.0, - color: _getSyncIconColor(syncState), - )); - } else if (syncState == SyncState.syncing) { - if (syncInfo != null) { - if (syncInfo.targetHeight > 0 && - syncInfo.currentHeight > 0 && - (syncInfo.targetHeight - syncInfo.currentHeight) < 3) { - message = 'Connected and synced'; - syncState = SyncState.syncDone; - return Tooltip( - message: message, - child: Icon( - Icons.radio_button_unchecked, - size: 24.0, - color: _getSyncIconColor(syncState), - )); - } else if (syncInfo.targetHeight == 0 || syncInfo.currentHeight == 0) { - message = 'Started syncing with the network, please wait'; - syncState = SyncState.syncing; - return Tooltip( - message: message, - child: Icon(Icons.sync, - size: 24.0, color: _getSyncIconColor(syncState))); - } else { - message = - 'Sync progress: momentum ${syncInfo.currentHeight} of ${syncInfo.targetHeight}'; - return Tooltip( - message: message, - child: SizedBox( - height: 18.0, - width: 18.0, - child: Center( - child: CircularProgressIndicator( - backgroundColor: Theme.of(context).iconTheme.color, - color: _getSyncIconColor(syncState), - value: syncInfo.currentHeight / syncInfo.targetHeight, - strokeWidth: 3.0, - )), - ), - ); - } - } else { - message = 'Syncing momentums'; - return Tooltip( - message: message, - child: Icon(Icons.sync, - size: 24.0, color: _getSyncIconColor(syncState))); - } - } else if (syncState == SyncState.notEnoughPeers) { - if (syncInfo != null) { - if (syncInfo.targetHeight > 0 && - syncInfo.currentHeight > 0 && - (syncInfo.targetHeight - syncInfo.currentHeight) < 20) { - message = 'Connecting to peers'; - syncState = SyncState.syncing; - return Tooltip( - message: message, - child: SizedBox( - height: 18.0, - width: 18.0, - child: Center( - child: CircularProgressIndicator( - backgroundColor: Theme.of(context).iconTheme.color, - color: _getSyncIconColor(syncState), - value: syncInfo.currentHeight / syncInfo.targetHeight, - strokeWidth: 3.0, - )))); - } else if (syncInfo.targetHeight == 0 || syncInfo.currentHeight == 0) { - message = 'Connecting to peers, please wait'; - syncState = SyncState.syncing; - return Tooltip( - message: message, - child: Icon(Icons.sync, - size: 24.0, color: _getSyncIconColor(syncState))); - } else { - message = - 'Sync progress: momentum ${syncInfo.currentHeight} of ${syncInfo.targetHeight}'; - syncState = SyncState.syncing; - return Tooltip( - message: message, - child: SizedBox( - height: 18.0, - width: 18.0, - child: Center( - child: CircularProgressIndicator( - backgroundColor: Theme.of(context).iconTheme.color, - color: _getSyncIconColor(syncState), - value: syncInfo.currentHeight / syncInfo.targetHeight, - strokeWidth: 3.0, - )))); - } - } else { - message = 'Connecting to peers'; - syncState = SyncState.syncing; - return Tooltip( - message: message, - child: Icon(Icons.sync_problem, - size: 24.0, color: _getSyncIconColor(syncState))); - } - } else { - message = 'Connected and synced'; - syncState = SyncState.syncDone; - } - - return Tooltip( - message: message, - child: SizedBox( - height: 18.0, - width: 18.0, - child: Center( - child: CircularProgressIndicator( - backgroundColor: Theme.of(context).iconTheme.color, - color: _getSyncIconColor(syncState), - value: 1, - strokeWidth: 2.0, - )), - ), - ); - } - Widget _getCurrentPageContainer() { return TabBarView( physics: const NeverScrollableScrollPhysics(), controller: _tabController, - children: [ + children: [ DashboardTabChild(changePage: _navigateTo), _transferTabChild!, PillarsTabChild( @@ -599,9 +456,8 @@ class _MainAppContainerState extends State @override void dispose() { windowManager.removeListener(this); - + _nodeSyncStatusCubit.close(); _animationController.dispose(); - _netSyncStatusBloc.dispose(); _navigateToLockTimer?.cancel(); _lockBlockStreamSubscription.cancel(); _incomingLinkSubscription.cancel(); @@ -616,7 +472,6 @@ class _MainAppContainerState extends State details: 'Auto-lock interval changed successfully to ' '$kAutoLockWalletMinutes minutes.', timestamp: DateTime.now().millisecondsSinceEpoch, - id: null, type: NotificationType.autoLockIntervalChanged, ), ); @@ -624,6 +479,7 @@ class _MainAppContainerState extends State } void _afterAppInitCallback() { + _nodeSyncStatusCubit.fetchDataPeriodically(); _navigateToLockTimer = _createAutoLockTimer(); if (kLastWalletConnectUriNotifier.value != null) { _tabController!.animateTo(_getTabChildIndex(Tabs.walletConnect)); @@ -635,7 +491,7 @@ class _MainAppContainerState extends State } void _listenToAutoReceiveTxWorkerNotifications() { - sl().stream.listen((event) { + sl().stream.listen((WalletNotification event) { sl().addNotification(event); }); } @@ -649,19 +505,6 @@ class _MainAppContainerState extends State int _getTabChildIndex(Tabs page) => kTabs.indexOf(page); - Color? _getSyncIconColor(SyncState syncState) { - if (syncState == SyncState.syncDone) { - return AppColors.znnColor; - } - if (syncState == SyncState.unknown) { - return Theme.of(context).iconTheme.color; - } - if (syncState == SyncState.syncing) { - return Colors.orange; - } - return AppColors.errorColor; - } - void _navigateTo( Tabs page, { bool redirectWithSendContainerLarge = false, @@ -692,7 +535,7 @@ class _MainAppContainerState extends State if (kDisabledTabs.contains( kTabs[_tabController!.index], )) { - int index = _tabController!.previousIndex; + final int index = _tabController!.previousIndex; setState(() { _tabController!.index = index; }); @@ -705,16 +548,14 @@ class _MainAppContainerState extends State void _initLockBlock() { _lockBloc = Provider.of(context, listen: false); - _lockBlockStreamSubscription = _lockBloc.stream.listen((event) { + _lockBlockStreamSubscription = _lockBloc.stream.listen((LockEvent event) { switch (event) { case LockEvent.countDown: if (kCurrentPage != Tabs.lock) { _navigateToLockTimer = _createAutoLockTimer(); } - break; case LockEvent.navigateToDashboard: _tabController!.animateTo(_getTabChildIndex(Tabs.dashboard)); - break; case LockEvent.navigateToLock: if (Navigator.of(context).canPop()) { Navigator.popUntil( @@ -726,16 +567,13 @@ class _MainAppContainerState extends State _tabController!.animateTo( _getTabChildIndex(Tabs.lock), ); - break; case LockEvent.resetTimer: if (_navigateToLockTimer != null && _navigateToLockTimer!.isActive) { _navigateToLockTimer?.cancel(); _navigateToLockTimer = _createAutoLockTimer(); } - break; case LockEvent.navigateToPreviousTab: _tabController!.animateTo(_tabController!.previousIndex); - break; } }); if (widget.redirectedFromWalletSuccess) { @@ -744,281 +582,282 @@ class _MainAppContainerState extends State } Timer _createAutoLockTimer() { - return Timer.periodic(Duration(minutes: kAutoLockWalletMinutes!), (timer) { + return Timer.periodic(Duration(minutes: kAutoLockWalletMinutes!), (Timer timer) { if (!sl().hasActiveIncomingSwaps) { _lockBloc.addEvent(LockEvent.navigateToLock); } }); } - void _handleIncomingLinks() async { + Future _handleIncomingLinks() async { if (!kIsWeb && !Platform.isLinux) { - _incomingLinkSubscription = - _appLinks.uriLinkStream.listen((Uri? uri) async { - if (!await windowManager.isFocused() || - !await windowManager.isVisible()) { - windowManager.show(); - } + _incomingLinkSubscription = _appLinks.uriLinkStream.listen( + (Uri? uri) async { + if (!await windowManager.isFocused() || + !await windowManager.isVisible()) { + windowManager.show(); + } - if (uri != null) { - String uriRaw = uri.toString(); + if (uri != null) { + String uriRaw = uri.toString(); - Logger('MainAppContainer') - .log(Level.INFO, '_handleIncomingLinks $uriRaw'); + Logger('MainAppContainer') + .log(Level.INFO, '_handleIncomingLinks $uriRaw'); - if (context.mounted) { - if (uriRaw.contains('wc')) { - if (Platform.isWindows) { - uriRaw = uriRaw.replaceAll('/?', '?'); + if (context.mounted) { + if (uriRaw.contains('wc')) { + if (Platform.isWindows) { + uriRaw = uriRaw.replaceAll('/?', '?'); + } + final String wcUri = Uri.decodeFull(uriRaw.split('wc?uri=').last); + if (WalletConnectUri.tryParse(wcUri) != null) { + await _updateWalletConnectUri(wcUri); + } + return; } - String wcUri = Uri.decodeFull(uriRaw.split('wc?uri=').last); - if (WalletConnectUri.tryParse(wcUri) != null) { - await _updateWalletConnectUri(wcUri); + + // Deep link query parameters + String queryAddress = ''; + String queryAmount = ''; // with decimals + int queryDuration = 0; // in months + String queryZTS = ''; + String queryPillarName = ''; + Token? token; + + if (uri.hasQuery) { + uri.queryParametersAll.forEach((String key, List value) async { + if (key == 'amount') { + queryAmount = value.first; + } else if (key == 'zts') { + queryZTS = value.first; + } else if (key == 'address') { + queryAddress = value.first; + } else if (key == 'duration') { + queryDuration = int.parse(value.first); + } else if (key == 'pillar') { + queryPillarName = value.first; + } + }); } - return; - } - // Deep link query parameters - String queryAddress = ''; - String queryAmount = ''; // with decimals - int queryDuration = 0; // in months - String queryZTS = ''; - String queryPillarName = ''; - Token? token; - - if (uri.hasQuery) { - uri.queryParametersAll.forEach((key, value) async { - if (key == 'amount') { - queryAmount = value.first; - } else if (key == 'zts') { - queryZTS = value.first; - } else if (key == 'address') { - queryAddress = value.first; - } else if (key == 'duration') { - queryDuration = int.parse(value.first); - } else if (key == 'pillar') { - queryPillarName = value.first; + if (queryZTS.isNotEmpty) { + if (queryZTS == 'znn' || queryZTS == 'ZNN') { + token = kZnnCoin; + } else if (queryZTS == 'qsr' || queryZTS == 'QSR') { + token = kQsrCoin; + } else { + token = await zenon!.embedded.token + .getByZts(TokenStandard.parse(queryZTS)); } - }); - } - - if (queryZTS.isNotEmpty) { - if (queryZTS == 'znn' || queryZTS == 'ZNN') { - token = kZnnCoin; - } else if (queryZTS == 'qsr' || queryZTS == 'QSR') { - token = kQsrCoin; - } else { - token = await zenon!.embedded.token - .getByZts(TokenStandard.parse(queryZTS)); } - } - final sendPaymentBloc = SendPaymentBloc(); - final stakingOptionsBloc = StakingOptionsBloc(); - final delegateButtonBloc = DelegateButtonBloc(); - final plasmaOptionsBloc = PlasmaOptionsBloc(); + final SendPaymentBloc sendPaymentBloc = SendPaymentBloc(); + final StakingOptionsBloc stakingOptionsBloc = StakingOptionsBloc(); + final DelegateButtonBloc delegateButtonBloc = DelegateButtonBloc(); + final PlasmaOptionsBloc plasmaOptionsBloc = PlasmaOptionsBloc(); + + if (context.mounted) { + switch (uri.host) { + case 'transfer': + await sl().addNotification( + WalletNotification( + title: 'Transfer action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, + ), + ); - if (context.mounted) { - switch (uri.host) { - case 'transfer': - await sl().addNotification( - WalletNotification( - title: 'Transfer action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.transfer); + + if (token != null) { + showDialogWithNoAndYesOptions( + context: context, + title: 'Transfer action', + isBarrierDismissible: true, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Are you sure you want transfer $queryAmount ${token.symbol} from $kSelectedAddress to $queryAddress?', + ), + ], + ), + onYesButtonPressed: () { + sendPaymentBloc.sendTransfer( + fromAddress: kSelectedAddress, + toAddress: queryAddress, + amount: + queryAmount.extractDecimals(token!.decimals), + token: token, + ); + }, + onNoButtonPressed: () {}, + ); + } + } - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.transfer); + case 'stake': + await sl().addNotification( + WalletNotification( + title: 'Stake action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, + ), + ); + + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.staking); - if (token != null) { showDialogWithNoAndYesOptions( context: context, - title: 'Transfer action', + title: 'Stake ${kZnnCoin.symbol} action', isBarrierDismissible: true, content: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text( - 'Are you sure you want transfer $queryAmount ${token.symbol} from $kSelectedAddress to $queryAddress?'), + 'Are you sure you want stake $queryAmount ${kZnnCoin.symbol} for $queryDuration month(s)?', + ), ], ), onYesButtonPressed: () { - sendPaymentBloc.sendTransfer( - fromAddress: kSelectedAddress, - toAddress: queryAddress, - amount: - queryAmount.extractDecimals(token!.decimals), - data: null, - token: token, + stakingOptionsBloc.stakeForQsr( + Duration(seconds: queryDuration * stakeTimeUnitSec), + queryAmount.extractDecimals(kZnnCoin.decimals), ); }, onNoButtonPressed: () {}, ); } - } - break; - - case 'stake': - await sl().addNotification( - WalletNotification( - title: 'Stake action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); - - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.staking); - - showDialogWithNoAndYesOptions( - context: context, - title: 'Stake ${kZnnCoin.symbol} action', - isBarrierDismissible: true, - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'Are you sure you want stake $queryAmount ${kZnnCoin.symbol} for $queryDuration month(s)?'), - ], + + case 'delegate': + await sl().addNotification( + WalletNotification( + title: 'Delegate action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, ), - onYesButtonPressed: () { - stakingOptionsBloc.stakeForQsr( - Duration(seconds: queryDuration * stakeTimeUnitSec), - queryAmount.extractDecimals(kZnnCoin.decimals)); - }, - onNoButtonPressed: () {}, ); - } - break; - - case 'delegate': - await sl().addNotification( - WalletNotification( - title: 'Delegate action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); - - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.pillars); - - showDialogWithNoAndYesOptions( - context: context, - title: 'Delegate ${kZnnCoin.symbol} action', - isBarrierDismissible: true, - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'Are you sure you want delegate the ${kZnnCoin.symbol} from $kSelectedAddress to Pillar $queryPillarName?'), - ], + + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.pillars); + + showDialogWithNoAndYesOptions( + context: context, + title: 'Delegate ${kZnnCoin.symbol} action', + isBarrierDismissible: true, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Are you sure you want delegate the ${kZnnCoin.symbol} from $kSelectedAddress to Pillar $queryPillarName?', + ), + ], + ), + onYesButtonPressed: () { + delegateButtonBloc.delegateToPillar(queryPillarName); + }, + onNoButtonPressed: () {}, + ); + } + + case 'fuse': + await sl().addNotification( + WalletNotification( + title: 'Fuse ${kQsrCoin.symbol} action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, ), - onYesButtonPressed: () { - delegateButtonBloc.delegateToPillar(queryPillarName); - }, - onNoButtonPressed: () {}, ); - } - break; - - case 'fuse': - await sl().addNotification( - WalletNotification( - title: 'Fuse ${kQsrCoin.symbol} action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); - - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.plasma); - - showDialogWithNoAndYesOptions( - context: context, - title: 'Fuse ${kQsrCoin.symbol} action', - isBarrierDismissible: true, - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'Are you sure you want fuse $queryAmount ${kQsrCoin.symbol} for address $queryAddress?'), - ], + + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.plasma); + + showDialogWithNoAndYesOptions( + context: context, + title: 'Fuse ${kQsrCoin.symbol} action', + isBarrierDismissible: true, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Are you sure you want fuse $queryAmount ${kQsrCoin.symbol} for address $queryAddress?', + ), + ], + ), + onYesButtonPressed: () { + plasmaOptionsBloc.generatePlasma( + queryAddress, + queryAmount.extractDecimals(kZnnCoin.decimals), + ); + }, + onNoButtonPressed: () {}, + ); + } + + case 'sentinel': + await sl().addNotification( + WalletNotification( + title: 'Deploy Sentinel action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, ), - onYesButtonPressed: () { - plasmaOptionsBloc.generatePlasma(queryAddress, - queryAmount.extractDecimals(kZnnCoin.decimals)); - }, - onNoButtonPressed: () {}, ); - } - break; - - case 'sentinel': - await sl().addNotification( - WalletNotification( - title: 'Deploy Sentinel action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.sentinels); - } - break; - - case 'pillar': - await sl().addNotification( - WalletNotification( - title: 'Deploy Pillar action detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.sentinels); + } - if (kCurrentPage != Tabs.lock) { - _navigateTo(Tabs.pillars); - } - break; - - default: - await sl().addNotification( - WalletNotification( - title: 'Incoming link detected', - timestamp: DateTime.now().millisecondsSinceEpoch, - details: 'Deep link: $uriRaw', - type: NotificationType.paymentReceived, - ), - ); - break; + case 'pillar': + await sl().addNotification( + WalletNotification( + title: 'Deploy Pillar action detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, + ), + ); + + if (kCurrentPage != Tabs.lock) { + _navigateTo(Tabs.pillars); + } + + default: + await sl().addNotification( + WalletNotification( + title: 'Incoming link detected', + timestamp: DateTime.now().millisecondsSinceEpoch, + details: 'Deep link: $uriRaw', + type: NotificationType.paymentReceived, + ), + ); + break; + } } + return; } - return; } - } - }, onDone: () { - Logger('MainAppContainer') - .log(Level.INFO, '_handleIncomingLinks', 'done'); - }, onError: (Object err) async { - await NotificationUtils.sendNotificationError( - err, 'Handle incoming link failed'); - Logger('MainAppContainer') - .log(Level.WARNING, '_handleIncomingLinks', err); - if (!mounted) return; - }); + }, + onDone: () { + Logger('MainAppContainer') + .log(Level.INFO, '_handleIncomingLinks', 'done'); + }, + onError: (Object err) async { + await NotificationUtils.sendNotificationError( + err, + 'Handle incoming link failed', + ); + Logger('MainAppContainer') + .log(Level.WARNING, '_handleIncomingLinks', err); + if (!mounted) return; + }, + ); } } @@ -1026,27 +865,34 @@ class _MainAppContainerState extends State if (!_initialUriIsHandled) { _initialUriIsHandled = true; try { - final uri = await _appLinks.getInitialLink(); + final Uri? uri = await _appLinks.getInitialLink(); if (uri != null) { Logger('MainAppContainer').log(Level.INFO, '_handleInitialUri $uri'); } if (!mounted) return; } on PlatformException catch (e, stackTrace) { - Logger('MainAppContainer').log(Level.WARNING, - '_handleInitialUri PlatformException', e, stackTrace); + Logger('MainAppContainer').log( + Level.WARNING, + '_handleInitialUri PlatformException', + e, + stackTrace, + ); } on FormatException catch (e, stackTrace) { Logger('MainAppContainer').log( - Level.WARNING, '_handleInitialUri FormatException', e, stackTrace); + Level.WARNING, + '_handleInitialUri FormatException', + e, + stackTrace, + ); if (!mounted) return; } } } @override - void onClipboardChanged() async { - ClipboardData? newClipboardData = - await Clipboard.getData(Clipboard.kTextPlain); - final text = newClipboardData?.text ?? ''; + Future onClipboardChanged() async { + final ClipboardData? newClipboardData = await Clipboard.getData(Clipboard.kTextPlain); + final String text = newClipboardData?.text ?? ''; if (text.isNotEmpty && WalletConnectUri.tryParse(text) != null) { // This check is needed because onClipboardChanged is called twice sometimes if (kLastWalletConnectUriNotifier.value != text) { diff --git a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donation_stepper.dart b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donation_stepper.dart index 9d512f7d..3361c090 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donation_stepper.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donation_stepper.dart @@ -4,9 +4,9 @@ import 'package:stacked/stacked.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/custom_material_stepper.dart' as custom_material_stepper; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; enum AcceleratorDonationStep { @@ -16,7 +16,7 @@ enum AcceleratorDonationStep { } class AcceleratorDonationStepper extends StatefulWidget { - const AcceleratorDonationStepper({Key? key}) : super(key: key); + const AcceleratorDonationStepper({super.key}); @override State createState() => @@ -50,7 +50,7 @@ class _AcceleratorDonationStepperState Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -70,21 +70,21 @@ class _AcceleratorDonationStepperState Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), ], ), Visibility( visible: _lastCompletedStep == AcceleratorDonationStep.values.last, child: Positioned( - bottom: 20.0, - right: 0.0, - left: 0.0, + bottom: 20, + right: 0, + left: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton.icon( label: 'Make another donation', onPressed: () { @@ -94,10 +94,9 @@ class _AcceleratorDonationStepperState }); }, iconData: Icons.refresh, - context: context, ), const SizedBox( - width: 75.0, + width: 75, ), StepperButton( text: 'Return to project list', @@ -112,10 +111,10 @@ class _AcceleratorDonationStepperState Visibility( visible: _lastCompletedStep == AcceleratorDonationStep.values.last, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_zts.json', @@ -139,7 +138,7 @@ class _AcceleratorDonationStepperState child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Donation address', stepContent: _getDonationAddressStepContent(accountInfo), @@ -176,13 +175,13 @@ class _AcceleratorDonationStepperState } String _getDonationDetailsStepSubtitle() { - String znnPrefix = _znnAmountController.text.isNotEmpty + final String znnPrefix = _znnAmountController.text.isNotEmpty ? '${_znnAmountController.text} ${kZnnCoin.symbol}' : ''; - String qsrSuffix = _qsrAmountController.text.isNotEmpty + final String qsrSuffix = _qsrAmountController.text.isNotEmpty ? '${_qsrAmountController.text} ${kQsrCoin.symbol}' : ''; - String splitter = znnPrefix.isNotEmpty && qsrSuffix.isNotEmpty ? ' ● ' : ''; + final String splitter = znnPrefix.isNotEmpty && qsrSuffix.isNotEmpty ? ' ● ' : ''; return znnPrefix + splitter + qsrSuffix; } @@ -190,18 +189,18 @@ class _AcceleratorDonationStepperState Widget _getDonationAddressStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ DisabledAddressField(_addressController), - Row(children: [ + Row(children: [ StepperUtils.getBalanceWidget(kZnnCoin, accountInfo), StepperUtils.getBalanceWidget(kQsrCoin, accountInfo), - ]), + ],), const DottedBorderInfoWidget( text: 'All donated funds go directly into the Accelerator address', ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { Navigator.pop(context); @@ -209,7 +208,7 @@ class _AcceleratorDonationStepperState text: 'Cancel', ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( onPressed: accountInfo.znn()! > BigInt.zero || @@ -233,9 +232,9 @@ class _AcceleratorDonationStepperState Widget _getDonationDetailsStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const Row( - children: [ + children: [ Text('Total donation budget'), StandardTooltipIcon( 'Your donation matters', @@ -253,7 +252,7 @@ class _AcceleratorDonationStepperState suffixIcon: AmountSuffixWidgets( kZnnCoin, onMaxPressed: () { - BigInt maxZnn = accountInfo.getBalance( + final BigInt maxZnn = accountInfo.getBalance( kZnnCoin.tokenStandard, ); if (_znnAmountController.text.isEmpty || @@ -266,7 +265,7 @@ class _AcceleratorDonationStepperState } }, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, accountInfo.znn()!, coinDecimals, @@ -274,7 +273,7 @@ class _AcceleratorDonationStepperState canBeEqualToMin: true, canBeBlank: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( @@ -292,7 +291,7 @@ class _AcceleratorDonationStepperState suffixIcon: AmountSuffixWidgets( kQsrCoin, onMaxPressed: () { - BigInt maxQsr = accountInfo.getBalance( + final BigInt maxQsr = accountInfo.getBalance( kQsrCoin.tokenStandard, ); if (_qsrAmountController.text.isEmpty || @@ -305,7 +304,7 @@ class _AcceleratorDonationStepperState } }, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, accountInfo.qsr()!, coinDecimals, @@ -313,7 +312,7 @@ class _AcceleratorDonationStepperState canBeEqualToMin: true, canBeBlank: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( @@ -323,7 +322,7 @@ class _AcceleratorDonationStepperState ), StepperUtils.getBalanceWidget(kQsrCoin, accountInfo), Row( - children: [ + children: [ StepperButton( text: 'Cancel', onPressed: () { @@ -331,7 +330,7 @@ class _AcceleratorDonationStepperState }, ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( text: 'Continue', @@ -398,13 +397,13 @@ class _AcceleratorDonationStepperState Widget _getSubmitDonationStepContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const DottedBorderInfoWidget( text: 'Thank you for supporting the Accelerator', ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -415,7 +414,7 @@ class _AcceleratorDonationStepperState text: 'Go back', ), const SizedBox( - width: 15.0, + width: 15, ), _getSubmitDonationViewModel(), ], @@ -440,9 +439,9 @@ class _AcceleratorDonationStepperState Widget _getSubmitDonationViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SubmitDonationBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _submitButtonKey.currentState?.animateReverse(); setState(() { @@ -459,8 +458,8 @@ class _AcceleratorDonationStepperState }, ); }, - builder: (_, model, __) => _getSubmitDonationButton(model), - viewModelBuilder: () => SubmitDonationBloc(), + builder: (_, SubmitDonationBloc model, __) => _getSubmitDonationButton(model), + viewModelBuilder: SubmitDonationBloc.new, ); } diff --git a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donations.dart b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donations.dart index 9791a7eb..4cb444bf 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donations.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_donations.dart @@ -5,12 +5,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class AcceleratorDonations extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const AcceleratorDonations({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override Widget build(BuildContext context) { @@ -24,18 +24,18 @@ class AcceleratorDonations extends StatelessWidget { Widget _getWidgetBody(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ const Icon( MaterialCommunityIcons.ufo_outline, - size: 75.0, + size: 75, color: AppColors.znnColor, ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ SizedBox( - width: 200.0, + width: 200, child: Text( 'Fuel for the Mothership', style: Theme.of(context).textTheme.headlineSmall, @@ -47,7 +47,7 @@ class AcceleratorDonations extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: const AcceleratorDonationStepper(), onStepperNotificationSeeMorePressed: onStepperNotificationSeeMorePressed, diff --git a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list.dart b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list.dart index 3d52dae1..f17f45f0 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list.dart @@ -10,18 +10,18 @@ enum AcceleratorProjectsFilterTag { } class AcceleratorProjectList extends StatefulWidget { - final PillarInfo? pillarInfo; - final List acceleratorProjects; - final Project? projects; - final VoidCallback onStepperNotificationSeeMorePressed; const AcceleratorProjectList( this.pillarInfo, this.acceleratorProjects, { required this.onStepperNotificationSeeMorePressed, this.projects, - Key? key, - }) : super(key: key); + super.key, + }); + final PillarInfo? pillarInfo; + final List acceleratorProjects; + final Project? projects; + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _AcceleratorProjectListState(); @@ -31,7 +31,7 @@ class _AcceleratorProjectListState extends State { final TextEditingController _searchKeyWordController = TextEditingController(); - final List _selectedProjectsFilterTag = []; + final List _selectedProjectsFilterTag = []; final ScrollController _scrollController = ScrollController(); @@ -40,18 +40,18 @@ class _AcceleratorProjectListState extends State { @override Widget build(BuildContext context) { return Container( - margin: const EdgeInsets.all(15.0), + margin: const EdgeInsets.all(15), child: Column( - children: [ + children: [ _getSearchInputField(), const SizedBox( - height: 10.0, + height: 10, ), if (widget.acceleratorProjects.first is Project) _getProjectsFilterTags(), if (widget.acceleratorProjects.first is Project) const SizedBox( - height: 10.0, + height: 10, ), Expanded( child: Scrollbar( @@ -59,13 +59,13 @@ class _AcceleratorProjectListState extends State { thumbVisibility: true, child: ListView.separated( separatorBuilder: (_, __) => const SizedBox( - height: 15.0, + height: 15, ), controller: _scrollController, shrinkWrap: true, itemCount: _filterBaseProjects(widget.acceleratorProjects).length, - itemBuilder: (context, index) => AcceleratorProjectListItem( + itemBuilder: (BuildContext context, int index) => AcceleratorProjectListItem( key: ValueKey( _filterBaseProjects(widget.acceleratorProjects) .elementAt(index) @@ -96,7 +96,7 @@ class _AcceleratorProjectListState extends State { Icons.search, color: Colors.green, ), - onChanged: (value) { + onChanged: (String value) { setState(() { _searchKeyWord = value; }); @@ -105,13 +105,13 @@ class _AcceleratorProjectListState extends State { } Set _filterBaseProjects( - List acceleratorProjects) { - var filteredBaseProjects = + List acceleratorProjects,) { + Set filteredBaseProjects = _filterBaseProjectsBySearchKeyWord(acceleratorProjects); if (widget.acceleratorProjects.first is Project && _selectedProjectsFilterTag.isNotEmpty) { filteredBaseProjects = _filterProjectsByFilterTags( - filteredBaseProjects.map((e) => e as Project).toList(), + filteredBaseProjects.map((AcceleratorProject e) => e as Project).toList(), ); } return filteredBaseProjects; @@ -120,10 +120,10 @@ class _AcceleratorProjectListState extends State { Set _filterBaseProjectsBySearchKeyWord( List acceleratorProjects, ) { - var filteredBaseProjects = {}; + final Set filteredBaseProjects = {}; filteredBaseProjects.addAll( acceleratorProjects.where( - (element) => element.id.toString().toLowerCase().contains( + (AcceleratorProject element) => element.id.toString().toLowerCase().contains( _searchKeyWord.toLowerCase(), ), ), @@ -131,7 +131,7 @@ class _AcceleratorProjectListState extends State { if (acceleratorProjects.first is Project) { filteredBaseProjects.addAll( acceleratorProjects.where( - (element) => + (AcceleratorProject element) => (element as Project).owner.toString().toLowerCase().contains( _searchKeyWord.toLowerCase(), ), @@ -140,21 +140,21 @@ class _AcceleratorProjectListState extends State { } filteredBaseProjects.addAll( acceleratorProjects.where( - (element) => element.name.toLowerCase().contains( + (AcceleratorProject element) => element.name.toLowerCase().contains( _searchKeyWord.toLowerCase(), ), ), ); filteredBaseProjects.addAll( acceleratorProjects.where( - (element) => element.description.toLowerCase().contains( + (AcceleratorProject element) => element.description.toLowerCase().contains( _searchKeyWord.toLowerCase(), ), ), ); filteredBaseProjects.addAll( acceleratorProjects.where( - (element) => element.url.toLowerCase().contains( + (AcceleratorProject element) => element.url.toLowerCase().contains( _searchKeyWord.toLowerCase(), ), ), @@ -164,7 +164,7 @@ class _AcceleratorProjectListState extends State { Widget _getProjectsFilterTags() { return Row( - children: [ + children: [ _getProjectsFilterTag(AcceleratorProjectsFilterTag.myProjects), _getProjectsFilterTag(AcceleratorProjectsFilterTag.onlyAccepted), if (widget.pillarInfo != null) @@ -176,7 +176,7 @@ class _AcceleratorProjectListState extends State { Widget _getProjectsFilterTag(AcceleratorProjectsFilterTag filterTag) { return TagWidget( text: FormatUtils.extractNameFromEnum( - filterTag), + filterTag,), hexColorCode: Theme.of(context) .colorScheme .primaryContainer @@ -199,22 +199,22 @@ class _AcceleratorProjectListState extends State { } Set _filterProjectsByFilterTags(List projects) { - var filteredBaseProjects = const Iterable.empty(); + Iterable filteredBaseProjects = const Iterable.empty(); if (_selectedProjectsFilterTag .contains(AcceleratorProjectsFilterTag.myProjects)) { filteredBaseProjects = projects.where( - (project) => project.owner.toString() == kSelectedAddress, + (Project project) => project.owner.toString() == kSelectedAddress, ); } if (_selectedProjectsFilterTag .contains(AcceleratorProjectsFilterTag.onlyAccepted)) { if (filteredBaseProjects.isNotEmpty) { filteredBaseProjects = filteredBaseProjects.where( - (project) => project.status == AcceleratorProjectStatus.active, + (Project project) => project.status == AcceleratorProjectStatus.active, ); } else { filteredBaseProjects = projects.where( - (project) => project.status == AcceleratorProjectStatus.active, + (Project project) => project.status == AcceleratorProjectStatus.active, ); } } @@ -222,11 +222,11 @@ class _AcceleratorProjectListState extends State { .contains(AcceleratorProjectsFilterTag.votingOpened)) { if (filteredBaseProjects.isNotEmpty) { filteredBaseProjects = filteredBaseProjects.where( - (project) => project.status == AcceleratorProjectStatus.voting, + (Project project) => project.status == AcceleratorProjectStatus.voting, ); } else { filteredBaseProjects = projects.where( - (project) => project.status == AcceleratorProjectStatus.voting, + (Project project) => project.status == AcceleratorProjectStatus.voting, ); } } diff --git a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list_item.dart b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list_item.dart index 52e038c5..b8b4611c 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list_item.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_project_list_item.dart @@ -8,18 +8,16 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AcceleratorProjectListItem extends StatefulWidget { - final AcceleratorProject acceleratorProject; - final PillarInfo? pillarInfo; - final Project? project; - final VoidCallback onStepperNotificationSeeMorePressed; const AcceleratorProjectListItem({ - Key? key, - required this.acceleratorProject, + required this.acceleratorProject, required this.onStepperNotificationSeeMorePressed, super.key, this.pillarInfo, this.project, - required this.onStepperNotificationSeeMorePressed, - }) : super(key: key); + }); + final AcceleratorProject acceleratorProject; + final PillarInfo? pillarInfo; + final Project? project; + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => @@ -38,7 +36,7 @@ class _AcceleratorProjectListItemState Navigator.push( context, MaterialPageRoute( - builder: (context) => ProjectDetailsScreen( + builder: (BuildContext context) => ProjectDetailsScreen( pillarInfo: widget.pillarInfo, project: widget.acceleratorProject, onStepperNotificationSeeMorePressed: @@ -50,20 +48,20 @@ class _AcceleratorProjectListItemState : null, child: Container( padding: const EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 10.0, + horizontal: 20, + vertical: 10, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular( - 10.0, + 10, ), color: Theme.of(context).colorScheme.primaryContainer, ), child: Column( - children: [ + children: [ _getProjectTitle(context), const SizedBox( - height: 10.0, + height: 10, ), AcceleratorProjectDetails( owner: widget.acceleratorProject is Project @@ -72,18 +70,18 @@ class _AcceleratorProjectListItemState hash: widget.acceleratorProject.id, creationTimestamp: widget.acceleratorProject.creationTimestamp, acceleratorProjectStatus: widget.acceleratorProject.status, - isPhase: widget.acceleratorProject is Phase + isPhase: widget.acceleratorProject is Phase, ), const SizedBox( - height: 10.0, + height: 10, ), _getProjectDescription(context), const SizedBox( - height: 10.0, + height: 10, ), _getProjectStatuses(context), const SizedBox( - height: 10.0, + height: 10, ), _getProjectVoteBreakdownViewModel(context), ], @@ -100,7 +98,7 @@ class _AcceleratorProjectListItemState ) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Visibility( visible: voteBreakdown.total > 0, child: _getVotingResults(context, voteBreakdown), @@ -116,7 +114,7 @@ class _AcceleratorProjectListItemState Widget _getProjectTitle(BuildContext context) { return Row( - children: [ + children: [ Text( widget.acceleratorProject.name, style: Theme.of(context).textTheme.headlineSmall, @@ -127,7 +125,7 @@ class _AcceleratorProjectListItemState Widget _getProjectDescription(BuildContext context) { return Row( - children: [ + children: [ Expanded( child: Text( widget.acceleratorProject.description, @@ -139,7 +137,7 @@ class _AcceleratorProjectListItemState } Widget _getProjectStatuses(BuildContext context) { - List tags = [ + final List tags = [ _getProjectStatusTag(), ]; @@ -172,8 +170,8 @@ class _AcceleratorProjectListItemState children: tags.zip( List.generate( tags.length - 1, - (index) => const SizedBox( - width: 5.0, + (int index) => const SizedBox( + width: 5, ), ), ), @@ -241,30 +239,30 @@ class _AcceleratorProjectListItemState BuildContext context, VoteBreakdown voteBreakdown, ) { - int yesVotes = voteBreakdown.yes; - int noVotes = voteBreakdown.no; - int quorum = voteBreakdown.total; - int quorumNeeded = (kNumOfPillars! * 0.33).ceil(); - int votesToAchieveQuorum = quorumNeeded - quorum; - int pillarsThatCanStillVote = kNumOfPillars! - + final int yesVotes = voteBreakdown.yes; + final int noVotes = voteBreakdown.no; + final int quorum = voteBreakdown.total; + final int quorumNeeded = (kNumOfPillars! * 0.33).ceil(); + final int votesToAchieveQuorum = quorumNeeded - quorum; + final int pillarsThatCanStillVote = kNumOfPillars! - quorum - (votesToAchieveQuorum > 0 ? votesToAchieveQuorum : 0); return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const Row( - children: [ + children: [ Text('Voting results'), ], ), kVerticalSpacing, Row( - children: [ + children: [ AcceleratorProgressBar( context: context, child: Row( - children: [ + children: [ AcceleratorProgressBarSpan( value: yesVotes / (yesVotes + noVotes), color: AppColors.znnColor, @@ -279,7 +277,7 @@ class _AcceleratorProjectListItemState ), ), const SizedBox( - width: 10.0, + width: 10, ), Tooltip( message: yesVotes > noVotes @@ -290,20 +288,20 @@ class _AcceleratorProjectListItemState color: yesVotes > noVotes ? AppColors.znnColor : Theme.of(context).colorScheme.secondary, - size: 15.0, + size: 15, ), ), ], ), const SizedBox( - height: 10.0, + height: 10, ), Row( - children: [ + children: [ AcceleratorProgressBar( context: context, child: Row( - children: [ + children: [ AcceleratorProgressBarSpan( value: quorum / kNumOfPillars!, color: AppColors.qsrColor, @@ -323,9 +321,9 @@ class _AcceleratorProjectListItemState '$pillarsThatCanStillVote Pillars that can still cast a vote', ), ], - )), + ),), const SizedBox( - width: 10.0, + width: 10, ), Tooltip( message: quorum >= quorumNeeded @@ -336,7 +334,7 @@ class _AcceleratorProjectListItemState color: quorum >= quorumNeeded ? AppColors.znnColor : Theme.of(context).colorScheme.secondary, - size: 15.0, + size: 15, ), ), ], @@ -348,8 +346,8 @@ class _AcceleratorProjectListItemState Widget _getOpenLinkIcon(BuildContext context) { return RawMaterialButton( constraints: const BoxConstraints( - minWidth: 50.0, - minHeight: 50.0, + minWidth: 50, + minHeight: 50, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), @@ -357,8 +355,8 @@ class _AcceleratorProjectListItemState child: Tooltip( message: 'Visit ${widget.acceleratorProject.url}', child: Container( - height: 50.0, - width: 50.0, + height: 50, + width: 50, padding: const EdgeInsets.all(4), decoration: const BoxDecoration( shape: BoxShape.circle, @@ -366,7 +364,7 @@ class _AcceleratorProjectListItemState ), child: const Icon( Icons.open_in_new, - size: 25.0, + size: 25, color: AppColors.znnColor, ), ), @@ -380,7 +378,7 @@ class _AcceleratorProjectListItemState ProjectVoteBreakdownBloc projectVoteBreakdownViewModel, ) { return Row( - children: [ + children: [ if (pillarVoteList != null && ((widget.acceleratorProject is Phase && (widget.acceleratorProject as Phase).status == @@ -392,15 +390,15 @@ class _AcceleratorProjectListItemState pillarVoteList, projectVoteBreakdownViewModel, ), - if ([ + if ([ AcceleratorProjectStatus.voting, AcceleratorProjectStatus.active, AcceleratorProjectStatus.paid, ].contains(widget.acceleratorProject.status)) Row( - children: [ + children: [ const SizedBox( - width: 10.0, + width: 10, ), _getOpenLinkIcon(context), ], @@ -410,13 +408,13 @@ class _AcceleratorProjectListItemState AcceleratorProjectStatus.voting && widget.project!.owner.toString() == kSelectedAddress) Row( - children: [ + children: [ const SizedBox( - width: 10.0, + width: 10, ), _getUpdatePhaseIcon(context), ], - ) + ), ], ); } @@ -427,81 +425,81 @@ class _AcceleratorProjectListItemState List pillarVoteList, ) { return Row( - children: [ + children: [ Tooltip( message: 'No', child: RawMaterialButton( constraints: const BoxConstraints( - minWidth: 50.0, - minHeight: 50.0, + minWidth: 50, + minHeight: 50, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), onPressed: () { model.voteProject( - widget.acceleratorProject.id, AcceleratorProjectVote.no); + widget.acceleratorProject.id, AcceleratorProjectVote.no,); }, child: Container( - height: 50.0, - width: 50.0, + height: 50, + width: 50, decoration: BoxDecoration( shape: BoxShape.circle, color: _ifOptionVotedByUser( - pillarVoteList, AcceleratorProjectVote.no) + pillarVoteList, AcceleratorProjectVote.no,) ? AppColors.errorColor : Theme.of(context).colorScheme.secondary, ), child: Icon( Icons.close_rounded, - size: 35.0, + size: 35, color: Theme.of(context).colorScheme.primary, ), ), ), ), const SizedBox( - width: 10.0, + width: 10, ), Tooltip( message: 'Yes', child: RawMaterialButton( constraints: const BoxConstraints( - minWidth: 50.0, - minHeight: 50.0, + minWidth: 50, + minHeight: 50, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), onPressed: () { model.voteProject( - widget.acceleratorProject.id, AcceleratorProjectVote.yes); + widget.acceleratorProject.id, AcceleratorProjectVote.yes,); }, child: Container( - height: 50.0, - width: 50.0, + height: 50, + width: 50, decoration: BoxDecoration( shape: BoxShape.circle, color: _ifOptionVotedByUser( - pillarVoteList, AcceleratorProjectVote.yes) + pillarVoteList, AcceleratorProjectVote.yes,) ? AppColors.znnColor : Theme.of(context).colorScheme.secondary, ), child: Icon( Icons.check_rounded, - size: 35.0, + size: 35, color: Theme.of(context).colorScheme.primary, ), ), ), ), const SizedBox( - width: 10.0, + width: 10, ), Tooltip( message: 'Abstain', child: RawMaterialButton( constraints: const BoxConstraints( - minWidth: 50.0, - minHeight: 50.0, + minWidth: 50, + minHeight: 50, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), @@ -512,8 +510,8 @@ class _AcceleratorProjectListItemState ); }, child: Container( - height: 50.0, - width: 50.0, + height: 50, + width: 50, decoration: BoxDecoration( shape: BoxShape.circle, color: _ifOptionVotedByUser( @@ -525,7 +523,7 @@ class _AcceleratorProjectListItemState ), child: Icon( Icons.stop, - size: 35.0, + size: 35, color: Theme.of(context).colorScheme.primary, ), ), @@ -540,8 +538,8 @@ class _AcceleratorProjectListItemState message: 'Update phase', child: RawMaterialButton( constraints: const BoxConstraints( - minWidth: 50.0, - minHeight: 50.0, + minWidth: 50, + minHeight: 50, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), @@ -549,7 +547,7 @@ class _AcceleratorProjectListItemState Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: UpdatePhaseStepper( widget.acceleratorProject as Phase, widget.project!, @@ -561,8 +559,8 @@ class _AcceleratorProjectListItemState ); }, child: Container( - height: 50.0, - width: 50.0, + height: 50, + width: 50, padding: const EdgeInsets.all(4), decoration: const BoxDecoration( shape: BoxShape.circle, @@ -570,7 +568,7 @@ class _AcceleratorProjectListItemState ), child: const Icon( Icons.edit, - size: 25.0, + size: 25, color: AppColors.znnColor, ), ), @@ -584,8 +582,8 @@ class _AcceleratorProjectListItemState ProjectVoteBreakdownBloc projectVoteBreakdownViewModel, ) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { - model.stream.listen((event) { + onViewModelReady: (VoteProjectBloc model) { + model.stream.listen((AccountBlockTemplate? event) { if (event != null) { projectVoteBreakdownViewModel.getVoteBreakdown( widget.pillarInfo?.name, @@ -597,11 +595,11 @@ class _AcceleratorProjectListItemState error, 'Error while voting project', ); - }); + },); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, VoteProjectBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getVotingIcons(context, model, pillarVoteList); } @@ -612,27 +610,27 @@ class _AcceleratorProjectListItemState return const SyriusLoadingWidget(); } return _getVotingIcons(context, model, pillarVoteList); - }), - viewModelBuilder: () => VoteProjectBloc(), + },), + viewModelBuilder: VoteProjectBloc.new, ); } Widget _getProjectVoteBreakdownViewModel(BuildContext context) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (ProjectVoteBreakdownBloc model) { model.getVoteBreakdown( - widget.pillarInfo?.name, widget.acceleratorProject.id); - model.stream.listen((event) {}, onError: (error) async { + widget.pillarInfo?.name, widget.acceleratorProject.id,); + model.stream.listen((Pair?>? event) {}, onError: (error) async { await NotificationUtils.sendNotificationError( error, 'Error while trying to get the vote breakdown', ); - }); + },); }, - builder: (_, model, __) => + builder: (_, ProjectVoteBreakdownBloc model, __) => StreamBuilder?>?>( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?>?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -650,15 +648,15 @@ class _AcceleratorProjectListItemState return const SyriusLoadingWidget(); }, ), - viewModelBuilder: () => ProjectVoteBreakdownBloc(), + viewModelBuilder: ProjectVoteBreakdownBloc.new, ); } bool _ifOptionVotedByUser( - List pillarVoteList, AcceleratorProjectVote vote) { + List pillarVoteList, AcceleratorProjectVote vote,) { try { - PillarVote? pillarVote = pillarVoteList.firstWhere( - (pillarVote) => pillarVote?.name == widget.pillarInfo!.name, + final PillarVote? pillarVote = pillarVoteList.firstWhere( + (PillarVote? pillarVote) => pillarVote?.name == widget.pillarInfo!.name, ); return pillarVote!.vote == vote.index; } catch (e) { diff --git a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_stats.dart b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_stats.dart index 477c7632..0211d8db 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/accelerator_stats.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/accelerator_stats.dart @@ -7,7 +7,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AcceleratorStats extends StatefulWidget { - const AcceleratorStats({Key? key}) : super(key: key); + const AcceleratorStats({super.key}); @override State createState() => _AcceleratorStatsState(); @@ -37,7 +37,7 @@ class _AcceleratorStatsState extends State { Widget _getWidgetBodyFutureBuilder(BuildContext context) { return StreamBuilder( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -55,13 +55,13 @@ class _AcceleratorStatsState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ SizedBox( - width: 150.0, + width: 150, child: _getPieChart(accountInfo), ), SizedBox( - width: 200.0, + width: 200, child: _getPieChartLegend(context, accountInfo), ), ], @@ -72,7 +72,7 @@ class _AcceleratorStatsState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ ChartLegend( dotColor: AppColors.znnColor, mainText: 'Available', @@ -83,9 +83,9 @@ class _AcceleratorStatsState extends State { ) .addDecimals(coinDecimals), tokenSymbol: kZnnCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', - style: Theme.of(context).textTheme.titleMedium!, + style: Theme.of(context).textTheme.titleMedium, ), ), ), @@ -100,9 +100,9 @@ class _AcceleratorStatsState extends State { ) .addDecimals(coinDecimals), tokenSymbol: kQsrCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', - style: Theme.of(context).textTheme.titleMedium!, + style: Theme.of(context).textTheme.titleMedium, ), ), ), @@ -112,12 +112,12 @@ class _AcceleratorStatsState extends State { Widget _getPieChart(AccountInfo accountInfo) { return AspectRatio( - aspectRatio: 1.0, + aspectRatio: 1, child: StandardPieChart( sections: showingSections(accountInfo), - centerSpaceRadius: 0.0, - sectionsSpace: 4.0, - onChartSectionTouched: (pieTouchedSection) { + centerSpaceRadius: 0, + sectionsSpace: 4, + onChartSectionTouched: (PieTouchedSection? pieTouchedSection) { setState(() { _touchedSectionTitle = pieTouchedSection?.touchedSection?.title; }); @@ -127,7 +127,7 @@ class _AcceleratorStatsState extends State { } List showingSections(AccountInfo accountInfo) { - return [ + return [ if (accountInfo.findTokenByTokenStandard(kZnnCoin.tokenStandard) != null) _getPieCharSectionsData(kZnnCoin, accountInfo), if (accountInfo.findTokenByTokenStandard(kQsrCoin.tokenStandard) != null) @@ -139,19 +139,19 @@ class _AcceleratorStatsState extends State { Token token, AccountInfo accountInfo, ) { - BigInt value = token.tokenStandard == kZnnCoin.tokenStandard + final BigInt value = token.tokenStandard == kZnnCoin.tokenStandard ? accountInfo.znn()! : accountInfo.qsr()!; - BigInt sumValues = accountInfo.znn()! + accountInfo.qsr()!; + final BigInt sumValues = accountInfo.znn()! + accountInfo.qsr()!; - final isTouched = token.symbol == _touchedSectionTitle; + final bool isTouched = token.symbol == _touchedSectionTitle; final double opacity = isTouched ? 1.0 : 0.5; return PieChartSectionData( color: ColorUtils.getTokenColor(token.tokenStandard).withOpacity(opacity), value: value / sumValues, title: accountInfo.findTokenByTokenStandard(token.tokenStandard)!.symbol, - radius: 60.0, + radius: 60, titleStyle: Theme.of(context).textTheme.bodyLarge, ); } diff --git a/lib/widgets/modular_widgets/accelerator_widgets/create_phase.dart b/lib/widgets/modular_widgets/accelerator_widgets/create_phase.dart index 44754889..c829088c 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/create_phase.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/create_phase.dart @@ -6,14 +6,14 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CreatePhase extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; - final Project project; const CreatePhase({ required this.onStepperNotificationSeeMorePressed, required this.project, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; + final Project project; @override Widget build(BuildContext context) { @@ -29,18 +29,18 @@ class CreatePhase extends StatelessWidget { Widget _getWidgetBody(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ + children: [ const Icon( MaterialCommunityIcons.creation, - size: 100.0, + size: 100, color: AppColors.znnColor, ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ SizedBox( - width: 200.0, + width: 200, child: Text( 'Start the project by creating a phase to unlock funds', style: Theme.of(context).textTheme.headlineSmall, @@ -53,7 +53,7 @@ class CreatePhase extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: PhaseCreationStepper(project), onStepperNotificationSeeMorePressed: onStepperNotificationSeeMorePressed, diff --git a/lib/widgets/modular_widgets/accelerator_widgets/create_project.dart b/lib/widgets/modular_widgets/accelerator_widgets/create_project.dart index e7a150f0..e1932d3e 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/create_project.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/create_project.dart @@ -5,12 +5,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class CreateProject extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const CreateProject({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override Widget build(BuildContext context) { @@ -24,18 +24,18 @@ class CreateProject extends StatelessWidget { Widget _getWidgetBody(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ + children: [ const Icon( MaterialCommunityIcons.alien, - size: 75.0, + size: 75, color: AppColors.znnColor, ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ SizedBox( - width: 200.0, + width: 200, child: Text( 'Join the Aliens building the future on Network of Momentum', style: Theme.of(context).textTheme.headlineSmall, @@ -47,7 +47,7 @@ class CreateProject extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: const ProjectCreationStepper(), onStepperNotificationSeeMorePressed: onStepperNotificationSeeMorePressed, diff --git a/lib/widgets/modular_widgets/accelerator_widgets/phase_creation_stepper.dart b/lib/widgets/modular_widgets/accelerator_widgets/phase_creation_stepper.dart index 7056ab5b..ac5df330 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/phase_creation_stepper.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/phase_creation_stepper.dart @@ -15,9 +15,9 @@ enum PhaseCreationStep { } class PhaseCreationStepper extends StatefulWidget { - final Project project; - const PhaseCreationStepper(this.project, {Key? key}) : super(key: key); + const PhaseCreationStepper(this.project, {super.key}); + final Project project; @override State createState() => _PhaseCreationStepperState(); @@ -53,7 +53,7 @@ class _PhaseCreationStepperState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -73,21 +73,21 @@ class _PhaseCreationStepperState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), ], ), Visibility( visible: _lastCompletedStep == PhaseCreationStep.values.last, child: Positioned( - bottom: 20.0, - right: 0.0, - left: 0.0, + bottom: 20, + right: 0, + left: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton.icon( label: 'Create another phase', onPressed: () { @@ -98,10 +98,9 @@ class _PhaseCreationStepperState extends State { }); }, iconData: Icons.refresh, - context: context, ), const SizedBox( - width: 75.0, + width: 75, ), StepperButton( text: 'View phases', @@ -116,10 +115,10 @@ class _PhaseCreationStepperState extends State { Visibility( visible: _lastCompletedStep == PhaseCreationStep.values.last, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_zts.json', @@ -143,7 +142,7 @@ class _PhaseCreationStepperState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Phase details', stepContent: _getPhaseDetailsStepContent(accountInfo), @@ -174,12 +173,12 @@ class _PhaseCreationStepperState extends State { Widget _getPhaseDetailsStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text('This phase belongs to Project ID ' '${widget.project.id.toShortString()}'), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _phaseNameKey, @@ -187,7 +186,7 @@ class _PhaseCreationStepperState extends State { child: InputField( controller: _phaseNameController, hintText: 'Phase name', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectName, @@ -196,13 +195,13 @@ class _PhaseCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _phaseDescriptionKey, @@ -210,7 +209,7 @@ class _PhaseCreationStepperState extends State { child: InputField( controller: _phaseDescriptionController, hintText: 'Phase description', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectDescription, @@ -219,13 +218,13 @@ class _PhaseCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _phaseUrlKey, @@ -233,7 +232,7 @@ class _PhaseCreationStepperState extends State { child: InputField( controller: _phaseUrlController, hintText: 'Phase URL', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: InputValidators.checkUrl, @@ -248,7 +247,7 @@ class _PhaseCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Text( 'Total phase budget', style: Theme.of(context).textTheme.bodyLarge, @@ -261,7 +260,7 @@ class _PhaseCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _phaseZnnAmountKey, @@ -282,14 +281,14 @@ class _PhaseCreationStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _phaseZnnAmountController.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, widget.project.getRemainingZnnFunds(), coinDecimals, BigInt.zero, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -297,13 +296,13 @@ class _PhaseCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _phaseQsrAmountKey, @@ -324,14 +323,14 @@ class _PhaseCreationStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _phaseQsrAmountController.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, widget.project.getRemainingQsrFunds(), coinDecimals, BigInt.zero, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -339,13 +338,13 @@ class _PhaseCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( text: 'Cancel', onPressed: () { @@ -353,7 +352,7 @@ class _PhaseCreationStepperState extends State { }, ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( text: 'Continue', @@ -373,19 +372,19 @@ class _PhaseCreationStepperState extends State { } Widget _getSubmitPhaseStepContent() { - BigInt remainingZnnBudget = widget.project.getRemainingZnnFunds() - + final BigInt remainingZnnBudget = widget.project.getRemainingZnnFunds() - (_phaseZnnAmountController.text.isNotEmpty ? _phaseZnnAmountController.text.extractDecimals(coinDecimals) : BigInt.zero); - BigInt remainingQsrBudget = widget.project.getRemainingQsrFunds() - + final BigInt remainingQsrBudget = widget.project.getRemainingQsrFunds() - (_phaseQsrAmountController.text.isNotEmpty ? _phaseQsrAmountController.text.extractDecimals(coinDecimals) : BigInt.zero); return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ DottedBorderInfoWidget( text: 'Remaining budget for the next phases is ' '${remainingZnnBudget.addDecimals(coinDecimals)} ${kZnnCoin.symbol} and ' @@ -393,7 +392,7 @@ class _PhaseCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -404,7 +403,7 @@ class _PhaseCreationStepperState extends State { text: 'Go back', ), const SizedBox( - width: 15.0, + width: 15, ), _getCreatePhaseViewModel(), ], @@ -437,9 +436,9 @@ class _PhaseCreationStepperState extends State { Widget _getCreatePhaseViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (CreatePhaseBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _submitButtonKey.currentState?.animateReverse(); setState(() { @@ -456,8 +455,8 @@ class _PhaseCreationStepperState extends State { }, ); }, - builder: (_, model, __) => _getSubmitButton(model), - viewModelBuilder: () => CreatePhaseBloc(), + builder: (_, CreatePhaseBloc model, __) => _getSubmitButton(model), + viewModelBuilder: CreatePhaseBloc.new, ); } diff --git a/lib/widgets/modular_widgets/accelerator_widgets/phase_list.dart b/lib/widgets/modular_widgets/accelerator_widgets/phase_list.dart index 27b6a8ca..28c9c393 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/phase_list.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/phase_list.dart @@ -3,18 +3,18 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PhaseList extends StatelessWidget { - final PillarInfo? pillarInfo; - final Project project; - final VoidCallback onRefreshButtonPressed; - final VoidCallback onStepperNotificationSeeMorePressed; const PhaseList( this.pillarInfo, this.project, this.onRefreshButtonPressed, { required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final PillarInfo? pillarInfo; + final Project project; + final VoidCallback onRefreshButtonPressed; + final VoidCallback onStepperNotificationSeeMorePressed; @override Widget build(BuildContext context) { diff --git a/lib/widgets/modular_widgets/accelerator_widgets/project_creation_stepper.dart b/lib/widgets/modular_widgets/accelerator_widgets/project_creation_stepper.dart index db1094cc..f476a67f 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/project_creation_stepper.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/project_creation_stepper.dart @@ -4,10 +4,10 @@ import 'package:stacked/stacked.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/custom_material_stepper.dart' as custom_material_stepper; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; enum ProjectCreationStep { projectCreation, @@ -16,7 +16,7 @@ enum ProjectCreationStep { } class ProjectCreationStepper extends StatefulWidget { - const ProjectCreationStepper({Key? key}) : super(key: key); + const ProjectCreationStepper({super.key}); @override State createState() => _ProjectCreationStepperState(); @@ -52,7 +52,7 @@ class _ProjectCreationStepperState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -72,21 +72,21 @@ class _ProjectCreationStepperState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), ], ), Visibility( visible: _lastCompletedStep == ProjectCreationStep.values.last, child: Positioned( - bottom: 20.0, - right: 0.0, - left: 0.0, + bottom: 20, + right: 0, + left: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton.icon( label: 'Create another project', onPressed: () { @@ -97,10 +97,9 @@ class _ProjectCreationStepperState extends State { }); }, iconData: Icons.refresh, - context: context, ), const SizedBox( - width: 75.0, + width: 75, ), StepperButton( text: 'View projects', @@ -115,10 +114,10 @@ class _ProjectCreationStepperState extends State { Visibility( visible: _lastCompletedStep == ProjectCreationStep.values.last, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_zts.json', @@ -155,7 +154,7 @@ class _ProjectCreationStepperState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Project creation', stepContent: _getProjectCreationStepContent(accountInfo), @@ -196,7 +195,7 @@ class _ProjectCreationStepperState extends State { Widget _getProjectCreationStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const Text('This will be your project owner address'), kVerticalSpacing, DisabledAddressField(_addressController), @@ -207,7 +206,7 @@ class _ProjectCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { Navigator.pop(context); @@ -215,7 +214,7 @@ class _ProjectCreationStepperState extends State { text: 'Cancel', ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( onPressed: accountInfo.getBalance( @@ -241,9 +240,9 @@ class _ProjectCreationStepperState extends State { Widget _getProjectDetailsStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: Form( key: _projectNameKey, @@ -251,7 +250,7 @@ class _ProjectCreationStepperState extends State { child: InputField( controller: _projectNameController, hintText: 'Project name', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectName, @@ -260,13 +259,13 @@ class _ProjectCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _projectDescriptionKey, @@ -274,7 +273,7 @@ class _ProjectCreationStepperState extends State { child: InputField( controller: _projectDescriptionController, hintText: 'Project description', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectDescription, @@ -283,13 +282,13 @@ class _ProjectCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _projectUrlKey, @@ -297,7 +296,7 @@ class _ProjectCreationStepperState extends State { child: InputField( controller: _projectUrlController, hintText: 'Project URL', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: InputValidators.checkUrl, @@ -312,7 +311,7 @@ class _ProjectCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Text( 'Total project budget', style: Theme.of(context).textTheme.bodyLarge, @@ -325,7 +324,7 @@ class _ProjectCreationStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _projectZnnKey, @@ -339,7 +338,7 @@ class _ProjectCreationStepperState extends State { suffixIcon: AmountSuffixWidgets( kZnnCoin, onMaxPressed: () { - BigInt maxZnn = kZnnProjectMaximumFunds; + final BigInt maxZnn = kZnnProjectMaximumFunds; if (_projectZnnAmountController.text.isEmpty || _projectZnnAmountController.text .extractDecimals(coinDecimals) < @@ -351,14 +350,14 @@ class _ProjectCreationStepperState extends State { } }, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, kZnnProjectMaximumFunds, kZnnCoin.decimals, kZnnProjectMinimumFunds, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -366,13 +365,13 @@ class _ProjectCreationStepperState extends State { ), // Empty space so that all the right edges will align const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _projectQsrKey, @@ -386,7 +385,7 @@ class _ProjectCreationStepperState extends State { suffixIcon: AmountSuffixWidgets( kQsrCoin, onMaxPressed: () { - BigInt maxQsr = kQsrProjectMaximumFunds; + final BigInt maxQsr = kQsrProjectMaximumFunds; if (_projectQsrAmountController.text.isEmpty || _projectQsrAmountController.text .extractDecimals(coinDecimals) < @@ -398,27 +397,27 @@ class _ProjectCreationStepperState extends State { } }, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, kQsrProjectMaximumFunds, kQsrCoin.decimals, kQsrProjectMinimumFunds, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), ), ), const SizedBox( - width: 23.0, + width: 23, ), ], ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( text: 'Cancel', onPressed: () { @@ -426,7 +425,7 @@ class _ProjectCreationStepperState extends State { }, ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( text: 'Continue', @@ -448,14 +447,14 @@ class _ProjectCreationStepperState extends State { Widget _getSubmitProjectStepContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ DottedBorderInfoWidget( text: 'Consume ${projectCreationFeeInZnn.addDecimals(coinDecimals)} ${kZnnCoin.symbol} to submit the project', ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -466,7 +465,7 @@ class _ProjectCreationStepperState extends State { text: 'Go back', ), const SizedBox( - width: 15.0, + width: 15, ), _getSubmitProjectViewModel(), ], @@ -477,9 +476,9 @@ class _ProjectCreationStepperState extends State { Widget _getSubmitProjectViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (CreateProjectBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _submitButtonKey.currentState?.animateReverse(); setState(() { @@ -496,8 +495,8 @@ class _ProjectCreationStepperState extends State { }, ); }, - builder: (_, model, __) => _getSubmitProjectButton(model), - viewModelBuilder: () => CreateProjectBloc(), + builder: (_, CreateProjectBloc model, __) => _getSubmitProjectButton(model), + viewModelBuilder: CreateProjectBloc.new, ); } diff --git a/lib/widgets/modular_widgets/accelerator_widgets/project_list.dart b/lib/widgets/modular_widgets/accelerator_widgets/project_list.dart index ede6c039..6c01254c 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/project_list.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/project_list.dart @@ -17,14 +17,14 @@ enum AccProjectsFilterTag { } class AccProjectList extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; - final PillarInfo? pillarInfo; const AccProjectList({ required this.onStepperNotificationSeeMorePressed, required this.pillarInfo, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; + final PillarInfo? pillarInfo; @override State createState() => _AccProjectListState(); @@ -58,14 +58,14 @@ class _AccProjectListState extends State { const Duration(seconds: 1), ) .distinct() - .listen((text) { + .listen((String text) { _bloc.onSearchInputChangedSink.add(text); }); - _pagingController.addPageRequestListener((pageKey) { + _pagingController.addPageRequestListener((int pageKey) { _bloc.onPageRequestSink.add(pageKey); }); _blocListingStateSubscription = _bloc.onNewListingState.listen( - (listingState) { + (InfiniteScrollBlocListingState listingState) { _pagingController.value = PagingState( nextPageKey: listingState.nextPageKey, error: listingState.error, @@ -79,7 +79,7 @@ class _AccProjectListState extends State { Widget build(BuildContext context) { return CardScaffold( title: 'Project List', - childBuilder: () => _getInfiniteScrollList(), + childBuilder: _getInfiniteScrollList, onRefreshPressed: () { _searchKeyWordController.clear(); _bloc.refreshResults(); @@ -90,20 +90,20 @@ class _AccProjectListState extends State { Widget _getInfiniteScrollList() { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( - children: [ + children: [ _getSearchInputField(), kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ _getProjectsFilterTags(), InkWell( onTap: _sortProjectListByLastUpdate, child: Icon( Entypo.select_arrows, - size: 15.0, + size: 15, color: Theme.of(context).iconTheme.color, ), ), @@ -118,10 +118,10 @@ class _AccProjectListState extends State { scrollController: _scrollController, pagingController: _pagingController, separatorBuilder: (_, __) => const SizedBox( - height: 15.0, + height: 15, ), builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (_, project, __) => AcceleratorProjectListItem( + itemBuilder: (_, Project project, __) => AcceleratorProjectListItem( key: ValueKey( project.id.toString(), ), @@ -163,13 +163,13 @@ class _AccProjectListState extends State { } Row _getProjectsFilterTags() { - List children = []; + final List children = []; - for (var tag in AccProjectsFilterTag.values) { + for (final AccProjectsFilterTag tag in AccProjectsFilterTag.values) { if (widget.pillarInfo == null) { - if ([ + if ([ AccProjectsFilterTag.needsVoting, - AccProjectsFilterTag.alreadyVoted + AccProjectsFilterTag.alreadyVoted, ].contains(tag)) { continue; } @@ -182,7 +182,7 @@ class _AccProjectListState extends State { ); } - _getProjectsFilterTag(AccProjectsFilterTag filterTag) { + TagWidget _getProjectsFilterTag(AccProjectsFilterTag filterTag) { return TagWidget( text: FormatUtils.extractNameFromEnum(filterTag), hexColorCode: Theme.of(context) @@ -226,9 +226,9 @@ class _AccProjectListState extends State { _pagingController.itemList!.isNotEmpty) { _sortAscending ? _pagingController.itemList!.sort( - (a, b) => a.lastUpdateTimestamp.compareTo(b.lastUpdateTimestamp)) + (Project a, Project b) => a.lastUpdateTimestamp.compareTo(b.lastUpdateTimestamp),) : _pagingController.itemList!.sort( - (a, b) => b.lastUpdateTimestamp.compareTo(a.lastUpdateTimestamp)); + (Project a, Project b) => b.lastUpdateTimestamp.compareTo(a.lastUpdateTimestamp),); setState(() { _sortAscending = !_sortAscending; }); diff --git a/lib/widgets/modular_widgets/accelerator_widgets/projects_stats.dart b/lib/widgets/modular_widgets/accelerator_widgets/projects_stats.dart index 9481379a..bcef90e4 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/projects_stats.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/projects_stats.dart @@ -5,9 +5,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ProjectsStats extends StatelessWidget { - final Project project; - const ProjectsStats(this.project, {Key? key}) : super(key: key); + const ProjectsStats(this.project, {super.key}); + final Project project; @override Widget build(BuildContext context) { @@ -20,24 +20,24 @@ class ProjectsStats extends StatelessWidget { Widget _getWidgetBody(BuildContext context) { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( - children: [ + children: [ Row( - children: [ + children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( project.name, ), const SizedBox( - height: 5.0, + height: 5, ), AcceleratorProjectDetails( owner: project.owner, hash: project.id, - creationTimestamp: project.creationTimestamp + creationTimestamp: project.creationTimestamp, ), ], ), @@ -46,17 +46,17 @@ class ProjectsStats extends StatelessWidget { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ Visibility( child: Expanded( child: Row( - children: [ + children: [ Expanded( flex: 2, child: _getChart(_getZnnChartSections(context)), ), const SizedBox( - width: 15.0, + width: 15, ), Expanded( flex: 3, @@ -69,13 +69,13 @@ class ProjectsStats extends StatelessWidget { Visibility( child: Expanded( child: Row( - children: [ + children: [ Expanded( flex: 2, child: _getChart(_getQsrChartSections(context)), ), const SizedBox( - width: 15.0, + width: 15, ), Expanded( flex: 3, @@ -95,11 +95,11 @@ class ProjectsStats extends StatelessWidget { Widget _getChart(List sections) { return Container( constraints: const BoxConstraints( - maxWidth: 150.0, - maxHeight: 150.0, + maxWidth: 150, + maxHeight: 150, ), child: AspectRatio( - aspectRatio: 1.0, + aspectRatio: 1, child: StandardPieChart( sections: sections, ), @@ -113,14 +113,14 @@ class ProjectsStats extends StatelessWidget { ) { return PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, color: color, value: value, ); } List _getZnnChartSections(BuildContext context) { - return [ + return [ _getBalanceChartSection( AppColors.znnColor, project.znnFundsNeeded == BigInt.zero @@ -137,7 +137,7 @@ class ProjectsStats extends StatelessWidget { } List _getQsrChartSections(BuildContext context) { - return [ + return [ _getBalanceChartSection( AppColors.qsrColor, project.qsrFundsNeeded == BigInt.zero @@ -157,7 +157,7 @@ class ProjectsStats extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ child, ], ); @@ -165,18 +165,18 @@ class ProjectsStats extends StatelessWidget { Widget _getZnnProjectLegends(BuildContext context) { return SizedBox( - height: 100.0, + height: 100, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ ChartLegend( dotColor: AppColors.znnColor, mainText: 'Received', detailsWidget: FormattedAmountWithTooltip( amount: project.getPaidZnnFunds().addDecimals(coinDecimals), tokenSymbol: kZnnCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), @@ -188,7 +188,7 @@ class ProjectsStats extends StatelessWidget { detailsWidget: FormattedAmountWithTooltip( amount: project.getRemainingZnnFunds().addDecimals(coinDecimals), tokenSymbol: kZnnCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), @@ -200,7 +200,7 @@ class ProjectsStats extends StatelessWidget { detailsWidget: FormattedAmountWithTooltip( amount: project.getTotalZnnFunds().addDecimals(coinDecimals), tokenSymbol: kZnnCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), @@ -213,18 +213,18 @@ class ProjectsStats extends StatelessWidget { Widget _getQsrProjectLegends(BuildContext context) { return SizedBox( - height: 100.0, + height: 100, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ ChartLegend( dotColor: AppColors.qsrColor, mainText: 'Received', detailsWidget: FormattedAmountWithTooltip( amount: project.getPaidQsrFunds().addDecimals(coinDecimals), tokenSymbol: kQsrCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), @@ -236,7 +236,7 @@ class ProjectsStats extends StatelessWidget { detailsWidget: FormattedAmountWithTooltip( amount: project.getRemainingQsrFunds().addDecimals(coinDecimals), tokenSymbol: kQsrCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), @@ -248,7 +248,7 @@ class ProjectsStats extends StatelessWidget { detailsWidget: FormattedAmountWithTooltip( amount: project.getTotalQsrFunds().addDecimals(coinDecimals), tokenSymbol: kQsrCoin.symbol, - builder: (amount, tokenSymbol) => Text( + builder: (String amount, String tokenSymbol) => Text( '$amount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium, ), diff --git a/lib/widgets/modular_widgets/accelerator_widgets/update_phase_stepper.dart b/lib/widgets/modular_widgets/accelerator_widgets/update_phase_stepper.dart index c419575d..d60edab3 100644 --- a/lib/widgets/modular_widgets/accelerator_widgets/update_phase_stepper.dart +++ b/lib/widgets/modular_widgets/accelerator_widgets/update_phase_stepper.dart @@ -15,14 +15,14 @@ enum UpdatePhaseStep { } class UpdatePhaseStepper extends StatefulWidget { - final Phase phase; - final Project project; const UpdatePhaseStepper( this.phase, this.project, { - Key? key, - }) : super(key: key); + super.key, + }); + final Phase phase; + final Project project; @override State createState() => _UpdatePhaseStepperState(); @@ -67,7 +67,7 @@ class _UpdatePhaseStepperState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -87,21 +87,21 @@ class _UpdatePhaseStepperState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), ], ), Visibility( visible: _lastCompletedStep == UpdatePhaseStep.updatePhase, child: Positioned( - bottom: 20.0, - right: 0.0, - left: 0.0, + bottom: 20, + right: 0, + left: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton( text: 'View Phases', onPressed: () { @@ -115,10 +115,10 @@ class _UpdatePhaseStepperState extends State { Visibility( visible: _lastCompletedStep == UpdatePhaseStep.updatePhase, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_zts.json', @@ -142,7 +142,7 @@ class _UpdatePhaseStepperState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Phase details', stepContent: _getPhaseDetailsStepContent(accountInfo), @@ -165,7 +165,7 @@ class _UpdatePhaseStepperState extends State { } custom_material_stepper.StepState _getStepState(UpdatePhaseStep step) { - int stepIndex = step.index; + final int stepIndex = step.index; return stepIndex <= (_lastCompletedStep?.index ?? -1) ? custom_material_stepper.StepState.complete : custom_material_stepper.StepState.indexed; @@ -174,9 +174,9 @@ class _UpdatePhaseStepperState extends State { Widget _getPhaseDetailsStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: Text( 'This phase belongs to Project ID ' @@ -193,7 +193,7 @@ class _UpdatePhaseStepperState extends State { child: InputField( controller: _phaseNameController, hintText: 'Phase name', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectName, @@ -206,7 +206,7 @@ class _UpdatePhaseStepperState extends State { child: InputField( controller: _phaseDescriptionController, hintText: 'Phase description', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: Validations.projectDescription, @@ -219,7 +219,7 @@ class _UpdatePhaseStepperState extends State { child: InputField( controller: _phaseUrlController, hintText: 'Phase URL', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, validator: InputValidators.checkUrl, @@ -250,14 +250,14 @@ class _UpdatePhaseStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _phaseZnnAmountController.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, widget.project.getRemainingZnnFunds(), kZnnCoin.decimals, BigInt.zero, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -282,21 +282,21 @@ class _UpdatePhaseStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _phaseQsrAmountController.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, widget.project.getRemainingQsrFunds(), kQsrCoin.decimals, BigInt.zero, canBeEqualToMin: true, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( text: 'Cancel', onPressed: () { @@ -304,7 +304,7 @@ class _UpdatePhaseStepperState extends State { }, ), const SizedBox( - width: 15.0, + width: 15, ), StepperButton( text: 'Continue', @@ -326,13 +326,13 @@ class _UpdatePhaseStepperState extends State { Widget _getUpdatePhaseStepContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const DottedBorderInfoWidget( text: 'Updating this phase will reset all current votes', ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -343,7 +343,7 @@ class _UpdatePhaseStepperState extends State { text: 'Go back', ), const SizedBox( - width: 15.0, + width: 15, ), _getUpdatePhaseViewModel(), ], @@ -392,9 +392,9 @@ class _UpdatePhaseStepperState extends State { Widget _getUpdatePhaseViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (UpdatePhaseBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { setState(() { _lastCompletedStep = UpdatePhaseStep.updatePhase; @@ -409,9 +409,9 @@ class _UpdatePhaseStepperState extends State { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, UpdatePhaseBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getUpdatePhaseButton(model); } @@ -424,7 +424,7 @@ class _UpdatePhaseStepperState extends State { return _getUpdatePhaseButton(model); }, ), - viewModelBuilder: () => UpdatePhaseBloc(), + viewModelBuilder: UpdatePhaseBloc.new, ); } diff --git a/lib/widgets/modular_widgets/dashboard_widgets/balance.dart b/lib/widgets/modular_widgets/dashboard_widgets/balance.dart deleted file mode 100644 index c57b391c..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/balance.dart +++ /dev/null @@ -1,228 +0,0 @@ -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:fl_chart/fl_chart.dart'; -import 'package:flutter/material.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Balance'; -final String _kWidgetDescription = 'This card displays the current ' - '${kZnnCoin.symbol} and ${kQsrCoin.symbol} amounts for the selected address'; - -class BalanceWidget extends StatefulWidget { - const BalanceWidget({ - Key? key, - }) : super(key: key); - - @override - State createState() => _BalanceWidgetState(); -} - -class _BalanceWidgetState extends State { - String? _touchedTokenStandard; - Color? _backgroundAddressColor; - Color? _colorAddressPrefixSuffix; - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _colorAddressPrefixSuffix ??= Theme.of(context).hintColor; - _backgroundAddressColor ??= Theme.of(context).colorScheme.background; - } - - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => BalanceDashboardBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold( - description: _kWidgetDescription, - childStream: model.stream, - onCompletedStatusCallback: (data) => _widgetBody(data), - title: _kWidgetTitle, - ), - ); - } - - Widget _widgetBody(AccountInfo accountInfo) { - return Column( - children: [ - kVerticalSpacing, - Expanded( - child: Stack( - alignment: Alignment.center, - children: [ - AspectRatio( - aspectRatio: 1.0, - child: StandardPieChart( - sectionsSpace: 0.0, - sections: _getChartSection(accountInfo), - onChartSectionTouched: (pieChartSection) { - setState(() { - _touchedTokenStandard = - pieChartSection?.touchedSection?.title; - }); - }), - ), - _touchedTokenStandard != null - ? _getBalance(accountInfo) - : Container(), - ], - ), - ), - FocusableActionDetector( - onShowHoverHighlight: (x) { - if (x) { - setState(() { - _colorAddressPrefixSuffix = AppColors.znnColor; - }); - } else { - setState(() { - _colorAddressPrefixSuffix = Theme.of(context).hintColor; - }); - } - }, - child: Container( - decoration: BoxDecoration( - color: _backgroundAddressColor, - border: Border.all(color: _backgroundAddressColor!), - borderRadius: BorderRadius.circular(15.0), - ), - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 8.0, - ), - margin: const EdgeInsets.only( - bottom: 12.0, - top: 12.0, - ), - child: AutoSizeText.rich( - TextSpan( - children: [ - TextSpan( - text: kSelectedAddress!.substring(0, 3), - style: TextStyle(color: _colorAddressPrefixSuffix), - ), - TextSpan( - text: kSelectedAddress!.substring( - 3, - kSelectedAddress!.length - 6, - ), - style: TextStyle( - color: Theme.of(context).hintColor, - ), - ), - TextSpan( - text: kSelectedAddress!.substring( - kSelectedAddress!.length - 6, - kSelectedAddress!.length, - ), - style: TextStyle( - color: _colorAddressPrefixSuffix, - ), - ), - ], - ), - ), - ), - ), - const Divider(), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Expanded( - child: _getCoinBalanceInfo(kZnnCoin, accountInfo), - ), - Expanded( - child: _getCoinBalanceInfo(kQsrCoin, accountInfo), - ), - ], - ), - ), - ], - ); - } - - FormattedAmountWithTooltip _getCoinBalanceInfo( - Token coin, - AccountInfo accountInfo, - ) { - return FormattedAmountWithTooltip( - amount: accountInfo - .getBalance( - coin.tokenStandard, - ) - .addDecimals(coin.decimals), - tokenSymbol: coin.symbol, - builder: (amount, tokenSymbol) => AmountInfoColumn( - context: context, - amount: amount, - tokenSymbol: tokenSymbol, - ), - ); - } - - List _getChartSection(AccountInfo accountInfo) { - List sections = []; - if (accountInfo.znn()! > BigInt.zero) { - sections.add( - _getBalanceChartSection( - accountInfo.findTokenByTokenStandard(kZnnCoin.tokenStandard)!, - accountInfo, - ), - ); - } - if (accountInfo.qsr()! > BigInt.zero) { - sections.add( - _getBalanceChartSection( - accountInfo.findTokenByTokenStandard(kQsrCoin.tokenStandard)!, - accountInfo, - ), - ); - } - - return sections; - } - - Widget _getBalance(AccountInfo accountInfo) { - TokenStandard tokenStandard = TokenStandard.parse(_touchedTokenStandard!); - - return SizedBox( - width: 120.0, - child: AutoSizeText( - '${accountInfo.getBalance( - tokenStandard, - ).addDecimals(coinDecimals)} ${_touchedTokenStandard == kZnnCoin.tokenStandard.toString() ? kZnnCoin.symbol : kQsrCoin.symbol}', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.headlineMedium!.copyWith( - color: ColorUtils.getTokenColor(tokenStandard), - fontWeight: FontWeight.bold, - ), - ), - ); - } - - PieChartSectionData _getBalanceChartSection( - Token token, - AccountInfo accountInfo, - ) { - final isTouched = token.symbol == _touchedTokenStandard; - final double opacity = isTouched ? 1.0 : 0.7; - - double value = accountInfo.getBalance(token.tokenStandard) / - (accountInfo.znn()! + accountInfo.qsr()!); - - return PieChartSectionData( - title: token.tokenStandard.toString(), - showTitle: false, - radius: 7.0, - color: ColorUtils.getTokenColor(token.tokenStandard).withOpacity(opacity), - value: value, - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/dashboard_widgets.dart b/lib/widgets/modular_widgets/dashboard_widgets/dashboard_widgets.dart index d6c30b75..1288765e 100644 --- a/lib/widgets/modular_widgets/dashboard_widgets/dashboard_widgets.dart +++ b/lib/widgets/modular_widgets/dashboard_widgets/dashboard_widgets.dart @@ -1,10 +1 @@ -export 'balance.dart'; -export 'delegation_stats.dart'; -export 'dual_coin_stats.dart'; -export 'pillars.dart'; export 'plasma_stats.dart'; -export 'realtime_statistics.dart'; -export 'sentinels.dart'; -export 'staking.dart'; -export 'total_hourly_transactions.dart'; -export 'transfer.dart'; diff --git a/lib/widgets/modular_widgets/dashboard_widgets/delegation_stats.dart b/lib/widgets/modular_widgets/dashboard_widgets/delegation_stats.dart deleted file mode 100644 index b9448b24..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/delegation_stats.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_vector_icons/flutter_vector_icons.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Delegation Stats'; -final String _kWidgetDescription = 'This card displays the amount of ' - '${kZnnCoin.symbol} and the name of the Pillar that you delegated to'; - -class DelegationStats extends StatefulWidget { - const DelegationStats({Key? key}) : super(key: key); - - @override - State createState() => _DelegationStatsState(); -} - -class _DelegationStatsState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => DelegationBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold( - childStream: model.stream, - onCompletedStatusCallback: (data) => _getWidgetBody(data), - title: _kWidgetTitle, - description: _kWidgetDescription, - ), - ); - } - - Widget _getWidgetBody(DelegationInfo delegationInfo) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: const EdgeInsets.all(8.0), - width: 36.0, - height: 36.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: delegationInfo.status == 1 - ? AppColors.znnColor - : AppColors.errorColor, - ), - ), - child: Icon( - SimpleLineIcons.trophy, - size: 12.0, - color: Theme.of(context).textTheme.bodyLarge!.color, - ), - ), - Container(width: 16.0), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - delegationInfo.name.toString(), - style: Theme.of(context).textTheme.bodyMedium, - ), - Text( - '${delegationInfo.weight.addDecimals(coinDecimals)} ${kZnnCoin.symbol}', - style: Theme.of(context).textTheme.titleMedium, - ), - ], - ), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/dual_coin_stats.dart b/lib/widgets/modular_widgets/dashboard_widgets/dual_coin_stats.dart deleted file mode 100644 index a4f827fb..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/dual_coin_stats.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:fl_chart/fl_chart.dart'; -import 'package:flutter/material.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/color_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Dual Coin Stats'; -final String _kWidgetDescription = 'This card displays the circulating ' - '${kZnnCoin.symbol} and ${kQsrCoin.symbol} supply from the network'; - -class DualCoinStats extends StatefulWidget { - const DualCoinStats({ - Key? key, - }) : super(key: key); - - @override - State createState() => _DualCoinStatsState(); -} - -class _DualCoinStatsState extends State - with SingleTickerProviderStateMixin { - int? _touchedIndex; - - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => DualCoinStatsBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold>( - description: _kWidgetDescription, - childStream: model.stream, - onCompletedStatusCallback: (data) => _getWidgetBody(data), - title: _kWidgetTitle, - ), - ); - } - - Widget _getWidgetBody(List tokenList) { - return Column( - children: [ - Expanded( - child: AspectRatio( - aspectRatio: 1.0, - child: StandardPieChart( - sectionsSpace: 4.0, - centerSpaceRadius: 0.0, - sections: showingSections(tokenList), - onChartSectionTouched: (pieTouchedSection) { - setState(() { - _touchedIndex = pieTouchedSection?.touchedSectionIndex; - }); - }, - ), - ), - ), - const Divider(), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Expanded( - child: _getTokenSupplyInfoWidget(tokenList[0]!), - ), - Expanded( - child: _getTokenSupplyInfoWidget(tokenList[1]!), - ), - ], - ), - ), - ], - ); - } - - FormattedAmountWithTooltip _getTokenSupplyInfoWidget(Token token) { - return FormattedAmountWithTooltip( - amount: token.totalSupply.addDecimals( - token.decimals, - ), - tokenSymbol: token.symbol, - builder: (amount, symbol) => AmountInfoColumn( - amount: amount, - tokenSymbol: symbol, - context: context, - ), - ); - } - - List showingSections(List tokenList) { - BigInt totalSupply = tokenList.fold( - BigInt.zero, - (previousValue, element) => previousValue + element!.totalSupply, - ); - return List.generate( - tokenList.length, - (i) { - Token currentTokenInfo = tokenList[i]!; - final isTouched = i == _touchedIndex; - final double opacity = isTouched ? 1.0 : 0.5; - return PieChartSectionData( - color: ColorUtils.getTokenColor(currentTokenInfo.tokenStandard) - .withOpacity(opacity), - value: currentTokenInfo.totalSupply / totalSupply, - title: currentTokenInfo.symbol, - radius: 60.0, - titleStyle: Theme.of(context).textTheme.titleSmall!.copyWith( - color: Colors.white, - ), - ); - }, - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/pillars.dart b/lib/widgets/modular_widgets/dashboard_widgets/pillars.dart deleted file mode 100644 index feda883b..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/pillars.dart +++ /dev/null @@ -1,63 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; - -const String _kWidgetTitle = 'Pillars'; -const String _kWidgetDescription = 'This card displays the number of active ' - 'Pillars in the network'; - -class Pillars extends StatefulWidget { - const Pillars({ - Key? key, - }) : super(key: key); - - @override - State createState() => _PillarsState(); -} - -class _PillarsState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => PillarsBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold( - childStream: model.stream, - onCompletedStatusCallback: (data) => _widgetBody(data), - title: _kWidgetTitle, - description: _kWidgetDescription, - ), - ); - } - - _widgetBody(int numOfPillars) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset( - 'assets/svg/ic_pillars_dashboard.svg', - width: 65.0, - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - NumberAnimation( - end: numOfPillars, - isInt: true, - style: Theme.of(context).textTheme.headlineMedium, - ), - Text( - 'Active Pillars', - style: Theme.of(context).textTheme.titleMedium, - ), - ], - ), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/plasma_stats.dart b/lib/widgets/modular_widgets/dashboard_widgets/plasma_stats.dart index 98e6281e..f23078b9 100644 --- a/lib/widgets/modular_widgets/dashboard_widgets/plasma_stats.dart +++ b/lib/widgets/modular_widgets/dashboard_widgets/plasma_stats.dart @@ -25,19 +25,19 @@ final String _kWidgetDescription = 'This card displays information about ' enum PlasmaStatsWidgetVersion { dashboardTab, plasmaTab } class PlasmaStats extends StatefulWidget { - final PlasmaStatsWidgetVersion version; const PlasmaStats({ this.version = PlasmaStatsWidgetVersion.dashboardTab, - Key? key, - }) : super(key: key); + super.key, + }); + final PlasmaStatsWidgetVersion version; @override State createState() => _PlasmaStatsState(); } class _PlasmaStatsState extends State { - final List _addresses = []; + final List _addresses = []; bool _sortAscending = true; @@ -54,7 +54,7 @@ class _PlasmaStatsState extends State { title: kPlasmaStatsWidgetTitle, description: _kWidgetDescription, childStream: sl.get().stream, - onCompletedStatusCallback: (data) => _getTable(data), + onCompletedStatusCallback: _getTable, onRefreshPressed: widget.version == PlasmaStatsWidgetVersion.plasmaTab ? () => sl.get().getPlasmas() : null, @@ -68,7 +68,7 @@ class _PlasmaStatsState extends State { : null, items: plasmaInfoStats, headerColumns: widget.version == PlasmaStatsWidgetVersion.plasmaTab - ? [ + ? [ CustomHeaderColumn( columnName: 'Address', onSortArrowsPressed: _onSortArrowsPressed, @@ -80,20 +80,16 @@ class _PlasmaStatsState extends State { ), ] : null, - generateRowCells: (plasmaStatsWrapper, isSelected) { - return [ - widget.version == PlasmaStatsWidgetVersion.plasmaTab - ? isSelected + generateRowCells: (PlasmaInfoWrapper plasmaStatsWrapper, bool isSelected) { + return [ + if (widget.version == PlasmaStatsWidgetVersion.plasmaTab) isSelected ? CustomTableCell.tooltipWithMarquee( Address.parse(plasmaStatsWrapper.address), - flex: 1, ) : CustomTableCell.tooltipWithText( context, Address.parse(plasmaStatsWrapper.address), - flex: 1, - ) - : isSelected + ) else isSelected ? CustomTableCell.tooltipWithMarquee( Address.parse(plasmaStatsWrapper.address), flex: 2, @@ -124,14 +120,13 @@ class _PlasmaStatsState extends State { switch (columnName) { case 'Address': _sortAscending - ? _addresses.sort((a, b) => a.compareTo(b)) - : _addresses.sort((a, b) => b.compareTo(a)); - break; + ? _addresses.sort((String a, String b) => a.compareTo(b)) + : _addresses.sort((String a, String b) => b.compareTo(a)); default: _sortAscending - ? _addresses.sort((a, b) => a.compareTo(b)) - : _addresses.sort((a, b) => b.compareTo(a)); + ? _addresses.sort((String a, String b) => a.compareTo(b)) + : _addresses.sort((String a, String b) => b.compareTo(a)); break; } diff --git a/lib/widgets/modular_widgets/dashboard_widgets/realtime_statistics.dart b/lib/widgets/modular_widgets/dashboard_widgets/realtime_statistics.dart deleted file mode 100644 index 98b7b755..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/realtime_statistics.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/color_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/zts_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Realtime Stats'; -final String _kWidgetDescription = - 'This card displays the number of ${kZnnCoin.symbol} and ' - '${kQsrCoin.symbol} transactions. For example, a delegation is considered a ' - '${kZnnCoin.symbol} transaction from the network\'s perspective. Every interaction ' - 'with the network embedded contracts is internally considered a transaction'; - -class RealtimeStatistics extends StatefulWidget { - const RealtimeStatistics({Key? key}) : super(key: key); - - @override - State createState() => _RealtimeStatisticsState(); -} - -class _RealtimeStatisticsState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => RealtimeStatisticsBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold>( - childStream: model.stream, - title: _kWidgetTitle, - description: _kWidgetDescription, - onCompletedStatusCallback: (data) => _widgetBody(data), - ), - ); - } - - Widget _widgetBody(List list) { - return Padding( - padding: const EdgeInsets.all(16.0), - child: Column(children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ChartLegend( - dotColor: ColorUtils.getTokenColor(kQsrCoin.tokenStandard), - mainText: '${kQsrCoin.symbol} ' - 'transactions', - ), - const SizedBox( - width: 10.0, - ), - ChartLegend( - dotColor: ColorUtils.getTokenColor(kZnnCoin.tokenStandard), - mainText: '${kZnnCoin.symbol} ' - 'transactions', - ), - ], - ), - Expanded(child: RealtimeTxsChart(list)), - ]), - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/sentinels.dart b/lib/widgets/modular_widgets/dashboard_widgets/sentinels.dart deleted file mode 100644 index 6e85ee4c..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/sentinels.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Sentinels'; -const String _kWidgetDescription = 'This card displays the number of active ' - 'Sentinels in the network'; - -class Sentinels extends StatefulWidget { - const Sentinels({Key? key}) : super(key: key); - - @override - State createState() => _SentinelsState(); -} - -class _SentinelsState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => SentinelsBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold>( - childStream: model.stream, - onCompletedStatusCallback: (data) => _getWidgetBody(data), - title: _kWidgetTitle, - description: _kWidgetDescription, - ), - ); - } - - Widget _getWidgetBody(List sentinelsByCycle) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(12.0), - child: SvgPicture.asset( - 'assets/svg/ic_sentinels_dashboard.svg', - width: 42.0, - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - NumberAnimation( - end: sentinelsByCycle.length, - isInt: true, - style: Theme.of(context).textTheme.headlineMedium, - ), - Text( - 'Active Sentinels', - style: Theme.of(context).textTheme.titleMedium, - ), - ], - ), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/staking.dart b/lib/widgets/modular_widgets/dashboard_widgets/staking.dart deleted file mode 100644 index ca29739b..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/staking.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_vector_icons/flutter_vector_icons.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; -import 'package:znn_sdk_dart/znn_sdk_dart.dart'; - -const String _kWidgetTitle = 'Staking Stats'; -final String _kWidgetDescription = 'This card displays the number of staking ' - 'entries and the total ${kZnnCoin.symbol} that you are currently staking'; - -class Staking extends StatefulWidget { - const Staking({Key? key}) : super(key: key); - - @override - State createState() => _StakingState(); -} - -class _StakingState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => StakingBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold( - childStream: model.stream, - onCompletedStatusCallback: (data) => _widgetBody(data), - title: _kWidgetTitle, - description: _kWidgetDescription, - ), - ); - } - - Widget _widgetBody(StakingStatsModel stake) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: const EdgeInsets.all(8.0), - width: 36.0, - height: 36.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: AppColors.znnColor, - ), - ), - child: Icon( - SimpleLineIcons.energy, - size: 12.0, - color: Theme.of(context).textTheme.bodyLarge!.color, - ), - ), - Container(width: 16.0), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - NumberAnimation( - end: stake.numActiveStakingEntries, - isInt: true, - style: Theme.of(context).textTheme.headlineMedium, - ), - Text( - '${stake.totalZnnStakingAmount.addDecimals(coinDecimals)} ${kZnnCoin.symbol}', - style: Theme.of(context).textTheme.titleMedium, - ), - ], - ), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/total_hourly_transactions.dart b/lib/widgets/modular_widgets/dashboard_widgets/total_hourly_transactions.dart deleted file mode 100644 index b04a20c5..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/total_hourly_transactions.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; - -const String _kWidgetTitle = 'Transactions'; -const String _kWidgetDescription = 'This card displays the total number of ' - 'transactions settled in the last hour across the network'; - -class TotalHourlyTransactions extends StatefulWidget { - const TotalHourlyTransactions({Key? key}) : super(key: key); - - @override - State createState() => - _TotalHourlyTransactionsState(); -} - -class _TotalHourlyTransactionsState extends State { - @override - Widget build(BuildContext context) { - return ViewModelBuilder.reactive( - viewModelBuilder: () => TotalHourlyTransactionsBloc(), - onViewModelReady: (model) { - model.getDataPeriodically(); - }, - builder: (_, model, __) => CardScaffold>( - childStream: model.stream, - onCompletedStatusCallback: (data) => _getWidgetBody(data), - title: _kWidgetTitle, - description: _kWidgetDescription, - ), - ); - } - - Widget _getWidgetBody(Map widgetData) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - NumberAnimation( - end: widgetData['numAccountBlocks'], - isInt: true, - style: Theme.of(context).textTheme.headlineLarge!.copyWith( - fontSize: 30.0, - ), - ), - kVerticalSpacing, - const Text('transactions in the last hour'), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/dashboard_widgets/transfer.dart b/lib/widgets/modular_widgets/dashboard_widgets/transfer.dart deleted file mode 100644 index 8f502110..00000000 --- a/lib/widgets/modular_widgets/dashboard_widgets/transfer.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_vector_icons/flutter_vector_icons.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; - -const String _kWidgetTitle = 'Transfer'; -const String _kWidgetDescription = - 'Redirects you to the Transfer tab where you ' - 'can manage sending and receiving funds'; - -class Transfer extends StatefulWidget { - final Function( - Tabs, { - bool redirectWithSendContainerLarge, - bool redirectWithReceiveContainerLarge, - })? changePage; - - const Transfer({ - Key? key, - this.changePage, - }) : super(key: key); - - @override - State createState() => _TransferState(); -} - -class _TransferState extends State { - @override - Widget build(BuildContext context) { - return CardScaffold( - title: _kWidgetTitle, - description: _kWidgetDescription, - childBuilder: () => _getTransferButtons(), - ); - } - - Column _getTransferButtons() { - return Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - IconButton( - splashRadius: 30.0, - onPressed: () { - widget.changePage!(Tabs.transfer, - redirectWithSendContainerLarge: true); - }, - icon: const Icon( - SimpleLineIcons.arrow_up_circle, - ), - color: AppColors.darkHintTextColor, - iconSize: 48.0, - ), - const TransferIconLegend( - legendText: '● Send', - ), - IconButton( - splashRadius: 30.0, - onPressed: () { - widget.changePage!(Tabs.transfer, - redirectWithReceiveContainerLarge: true); - }, - icon: const Icon( - SimpleLineIcons.arrow_down_circle, - ), - iconSize: 48.0, - color: AppColors.lightHintTextColor, - ), - const TransferIconLegend( - legendText: '● Receive', - ), - ], - ); - } -} diff --git a/lib/widgets/modular_widgets/help_widgets/about_card.dart b/lib/widgets/modular_widgets/help_widgets/about_card.dart index 2f850b99..c5c56582 100644 --- a/lib/widgets/modular_widgets/help_widgets/about_card.dart +++ b/lib/widgets/modular_widgets/help_widgets/about_card.dart @@ -10,7 +10,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AboutCard extends StatefulWidget { - const AboutCard({Key? key}) : super(key: key); + const AboutCard({super.key}); @override State createState() { @@ -32,14 +32,14 @@ class AboutCardState extends State { return CardScaffold( title: 'About', description: 'Detailed information about wallet components', - childBuilder: () => _getStreamBuilder(), + childBuilder: _getStreamBuilder, ); } Widget _getNewBody(GeneralStats generalStats) { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel( 'Syrius wallet version', _getGenericTextExpandedChild(kWalletVersion), @@ -47,7 +47,7 @@ class AboutCardState extends State { CustomExpandablePanel( 'Zenon Node chain identifier', _getGenericTextExpandedChild( - generalStats.frontierMomentum.chainIdentifier.toString()), + generalStats.frontierMomentum.chainIdentifier.toString(),), ), CustomExpandablePanel( 'Client chain identifier', @@ -108,22 +108,22 @@ class AboutCardState extends State { CustomExpandablePanel( 'Zenon main data path', _getGenericOpenButtonExpandedChild( - znnDefaultPaths.main.absolute.path), + znnDefaultPaths.main.absolute.path,), ), CustomExpandablePanel( 'Syrius cache path', _getGenericOpenButtonExpandedChild( - znnDefaultPaths.cache.absolute.path), + znnDefaultPaths.cache.absolute.path,), ), CustomExpandablePanel( 'Syrius wallet path', _getGenericOpenButtonExpandedChild( - znnDefaultPaths.wallet.absolute.path), + znnDefaultPaths.wallet.absolute.path,), ), CustomExpandablePanel( 'Syrius wallet type', _getGenericOpenButtonExpandedChild( - kWalletFile!.walletType), + kWalletFile!.walletType,), ), CustomExpandablePanel( 'Client hostname', @@ -150,17 +150,17 @@ class AboutCardState extends State { } Widget _getGenericTextExpandedChild(String expandedText) { - return Row(children: [ + return Row(children: [ CustomTableCell.withMarquee( - expandedText.toString(), - ) - ]); + expandedText, + ), + ],); } Widget _getGenericLinkButtonExpandedChild(String url) { - return Row(children: [ + return Row(children: [ CustomTableCell.withMarquee( - url.toString(), + url, ), IconButton( splashRadius: 16, @@ -173,13 +173,13 @@ class AboutCardState extends State { color: AppColors.znnColor, ), ), - ]); + ],); } Widget _getGenericOpenButtonExpandedChild(String expandedText) { - return Row(children: [ + return Row(children: [ CustomTableCell.withMarquee( - expandedText.toString(), + expandedText, ), IconButton( splashRadius: 16, @@ -192,13 +192,13 @@ class AboutCardState extends State { color: AppColors.znnColor, ), ), - ]); + ],); } Widget _getStreamBuilder() { return StreamBuilder( stream: _generalStatsBloc!.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return _getNewBody(snapshot.data!); } else if (snapshot.hasError) { diff --git a/lib/widgets/modular_widgets/help_widgets/community_card.dart b/lib/widgets/modular_widgets/help_widgets/community_card.dart index 360246b5..0a70b352 100644 --- a/lib/widgets/modular_widgets/help_widgets/community_card.dart +++ b/lib/widgets/modular_widgets/help_widgets/community_card.dart @@ -5,7 +5,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class CommunityCard extends StatelessWidget { - const CommunityCard({Key? key}) : super(key: key); + const CommunityCard({super.key}); @override Widget build(BuildContext context) { @@ -21,7 +21,7 @@ class CommunityCard extends StatelessWidget { return ListView( physics: const ClampingScrollPhysics(), shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel( 'Websites', _getWebsitesExpandableChild(context), @@ -46,7 +46,7 @@ class CommunityCard extends StatelessWidget { return ListView( physics: const ClampingScrollPhysics(), shrinkWrap: true, - children: [ + children: [ _getListViewChild( iconData: MaterialCommunityIcons.home, title: 'Zenon Network', @@ -85,7 +85,7 @@ class CommunityCard extends StatelessWidget { return ListView( physics: const ClampingScrollPhysics(), shrinkWrap: true, - children: [ + children: [ _getListViewChild( iconData: Icons.explore, title: 'Zenon Explorer', @@ -97,7 +97,7 @@ class CommunityCard extends StatelessWidget { title: 'Zenon Hub Explorer', url: kHubCommunityExplorer, context: context, - ) + ), ], ); } @@ -106,7 +106,7 @@ class CommunityCard extends StatelessWidget { return ListView( physics: const ClampingScrollPhysics(), shrinkWrap: true, - children: [ + children: [ _getListViewChild( iconData: MaterialCommunityIcons.twitter, title: 'Zenon Twitter', @@ -163,7 +163,7 @@ class CommunityCard extends StatelessWidget { return ListView( physics: const ClampingScrollPhysics(), shrinkWrap: true, - children: [ + children: [ _getListViewChild( iconData: MaterialCommunityIcons.book_open_page_variant, title: 'Zenon Wiki', @@ -193,22 +193,21 @@ class CommunityCard extends StatelessWidget { required BuildContext context, }) { return Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ Icon( iconData, color: AppColors.znnColor, - size: 20.0, + size: 20, ), const SizedBox( - width: 10.0, + width: 10, ), Text( title, style: Theme.of(context).textTheme.titleMedium, ), const SizedBox( - width: 10.0, + width: 10, ), LinkIcon(url: url), ], diff --git a/lib/widgets/modular_widgets/help_widgets/update_card.dart b/lib/widgets/modular_widgets/help_widgets/update_card.dart index 2b46dd35..c055a162 100644 --- a/lib/widgets/modular_widgets/help_widgets/update_card.dart +++ b/lib/widgets/modular_widgets/help_widgets/update_card.dart @@ -4,7 +4,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/navigation_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class UpdateCard extends StatelessWidget { - const UpdateCard({Key? key}) : super(key: key); + const UpdateCard({super.key}); @override Widget build(BuildContext context) { @@ -18,7 +18,7 @@ class UpdateCard extends StatelessWidget { Widget _getWidgetBody(BuildContext context) { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel( 'Check update', _getCheckUpdateExpandableChild(context), diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/detail_row.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/detail_row.dart index b06ee378..3765cebd 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/detail_row.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/detail_row.dart @@ -3,11 +3,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/icons/copy_to_clipboard_icon.dart'; class DetailRow extends StatelessWidget { - final String label; - final String value; - final String? valueToShow; - final Widget? prefixWidget; - final bool canBeCopied; const DetailRow({ required this.label, @@ -15,38 +10,43 @@ class DetailRow extends StatelessWidget { this.valueToShow, this.prefixWidget, this.canBeCopied = true, - Key? key, - }) : super(key: key); + super.key, + }); + final String label; + final String value; + final String? valueToShow; + final Widget? prefixWidget; + final bool canBeCopied; @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text(label, style: const TextStyle( - fontSize: 12.0, color: AppColors.subtitleColor)), + fontSize: 12, color: AppColors.subtitleColor,),), Row( - children: [ + children: [ prefixWidget ?? Container(), if (prefixWidget != null) const SizedBox( - width: 5.0, + width: 5, ), Text(valueToShow ?? value, style: const TextStyle( - fontSize: 12.0, color: AppColors.subtitleColor)), + fontSize: 12, color: AppColors.subtitleColor,),), Visibility( visible: canBeCopied, child: CopyToClipboardIcon( value, iconColor: AppColors.subtitleColor, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only(left: 8), ), ), ], - ) + ), ], ); } diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_card.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_card.dart index c2435c80..bc232bc7 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_card.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_card.dart @@ -14,16 +14,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_inf import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class HtlcCard extends StatefulWidget { - final String title; - final String sender; - final String? htlcId; - final String? hashLock; - final int? expirationTime; - final String? recipient; - final BigInt? amount; - final String? tokenStandard; - final int? tokenDecimals; - final String? tokenSymbol; const HtlcCard({ required this.title, @@ -36,8 +26,8 @@ class HtlcCard extends StatefulWidget { required this.tokenStandard, required this.tokenDecimals, required this.tokenSymbol, - Key? key, - }) : super(key: key); + super.key, + }); factory HtlcCard.sending({ required HtlcSwap swap, @@ -96,6 +86,16 @@ class HtlcCard extends StatefulWidget { tokenDecimals: token.decimals, tokenSymbol: token.symbol, ); + final String title; + final String sender; + final String? htlcId; + final String? hashLock; + final int? expirationTime; + final String? recipient; + final BigInt? amount; + final String? tokenStandard; + final int? tokenDecimals; + final String? tokenSymbol; @override State createState() => _HtlcCardState(); @@ -127,7 +127,7 @@ class _HtlcCardState extends State child: Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, - borderRadius: const BorderRadius.all(Radius.circular(8.0)), + borderRadius: const BorderRadius.all(Radius.circular(8)), ), child: widget.htlcId == null ? _getWaitingBody() : _getWidgetBody(), ), @@ -136,7 +136,7 @@ class _HtlcCardState extends State Widget _getWaitingBody() { return const SizedBox( - height: 94.0, + height: 94, child: LoadingInfoText( text: 'Waiting for the counterparty to join the swap.', ), @@ -145,14 +145,14 @@ class _HtlcCardState extends State Widget _getWidgetBody() { return Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ Text( widget.title, style: - const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + const TextStyle(fontSize: 14, color: AppColors.subtitleColor), ), const SizedBox( height: 10, @@ -160,14 +160,14 @@ class _HtlcCardState extends State Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.end, - children: [ + children: [ Row( - children: [ + children: [ Container( constraints: const BoxConstraints(maxWidth: 280), child: Text( widget.amount!.addDecimals(widget.tokenDecimals!), - style: const TextStyle(fontSize: 18.0), + style: const TextStyle(fontSize: 18), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, @@ -177,27 +177,27 @@ class _HtlcCardState extends State constraints: const BoxConstraints(maxWidth: 150), child: Text( ' ${widget.tokenSymbol!}', - style: const TextStyle(fontSize: 18.0), + style: const TextStyle(fontSize: 18), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, ), ), const SizedBox( - width: 8.0, + width: 8, ), Container( - height: 6.0, - width: 6.0, + height: 6, + width: 6, decoration: BoxDecoration( shape: BoxShape.circle, color: ColorUtils.getTokenColor( - TokenStandard.parse(widget.tokenStandard!)), + TokenStandard.parse(widget.tokenStandard!),), ), ), ], ), - _getDetailsButton() + _getDetailsButton(), ], ), _getDetailsSection(), @@ -217,8 +217,8 @@ class _HtlcCardState extends State }); }, child: RotationTransition( - turns: Tween(begin: 0.0, end: 0.5).animate(_animationController), - child: const Icon(Icons.keyboard_arrow_down, size: 22.0), + turns: Tween(begin: 0, end: 0.5).animate(_animationController), + child: const Icon(Icons.keyboard_arrow_down, size: 22), ), ); } @@ -230,10 +230,10 @@ class _HtlcCardState extends State child: Visibility( visible: _areDetailsExpanded, child: Column( - children: [ - const SizedBox(height: 20.0), + children: [ + const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.1)), - const SizedBox(height: 20.0), + const SizedBox(height: 20), _getDetailsList(), ], ), @@ -242,15 +242,15 @@ class _HtlcCardState extends State } Widget _getDetailsList() { - final List children = []; - final htlcId = Hash.parse(widget.htlcId!); - final hashLock = Hash.parse(widget.hashLock!); + final List children = []; + final Hash htlcId = Hash.parse(widget.htlcId!); + final Hash hashLock = Hash.parse(widget.hashLock!); children.add(_getExpirationRow(widget.expirationTime!)); children.add( DetailRow( label: 'Deposit ID', value: htlcId.toString(), - valueToShow: htlcId.toShortString()), + valueToShow: htlcId.toShortString(),), ); children.add( DetailRow( @@ -263,26 +263,26 @@ class _HtlcCardState extends State DetailRow( label: 'Sender', value: widget.sender, - valueToShow: ZenonAddressUtils.getLabel(widget.sender)), + valueToShow: ZenonAddressUtils.getLabel(widget.sender),), ); children.add( DetailRow( label: 'Recipient', value: widget.recipient!, - valueToShow: ZenonAddressUtils.getLabel(widget.recipient!)), + valueToShow: ZenonAddressUtils.getLabel(widget.recipient!),), ); children.add( DetailRow( label: 'Hashlock', value: hashLock.toString(), - valueToShow: hashLock.toShortString()), + valueToShow: hashLock.toShortString(),), ); return Column( children: children.zip( List.generate( children.length - 1, - (index) => const SizedBox( - height: 15.0, + (int index) => const SizedBox( + height: 15, ), ), ), @@ -290,10 +290,10 @@ class _HtlcCardState extends State } Widget? _getTokenStandardTooltip(String tokenStandard) { - var message = 'This token is not in your favorites.'; - var icon = Icons.help; - var iconColor = AppColors.errorColor; - if ([znnTokenStandard, qsrTokenStandard].contains(tokenStandard)) { + String message = 'This token is not in your favorites.'; + IconData icon = Icons.help; + Color iconColor = AppColors.errorColor; + if ([znnTokenStandard, qsrTokenStandard].contains(tokenStandard)) { message = 'This token is verified.'; icon = Icons.check_circle_outline; iconColor = AppColors.znnColor; @@ -305,22 +305,22 @@ class _HtlcCardState extends State return Tooltip( message: message, child: Padding( - padding: const EdgeInsets.only(top: 1.0), + padding: const EdgeInsets.only(top: 1), child: Icon( icon, color: iconColor, - size: 14.0, + size: 14, ), ), ); } Widget _getExpirationRow(int expirationTime) { - final duration = + final Duration duration = Duration(seconds: expirationTime - DateTimeUtils.unixTimeNow); if (duration.isNegative) { return const DetailRow( - label: 'Expires in', value: 'Expired', canBeCopied: false); + label: 'Expires in', value: 'Expired', canBeCopied: false,); } return TweenAnimationBuilder( duration: duration, @@ -329,7 +329,7 @@ class _HtlcCardState extends State return DetailRow( label: 'Expires in', value: d.toString().split('.').first, - canBeCopied: false); + canBeCopied: false,); }, ); } diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_swap_details_widget.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_swap_details_widget.dart index 8a5cc11c..5ce98c45 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_swap_details_widget.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/htlc_swap_details_widget.dart @@ -8,12 +8,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_wid import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class HtlcSwapDetailsWidget extends StatefulWidget { - final HtlcSwap swap; const HtlcSwapDetailsWidget({ required this.swap, - Key? key, - }) : super(key: key); + super.key, + }); + final HtlcSwap swap; @override State createState() => _HtlcSwapDetailsWidgetState(); @@ -40,7 +40,7 @@ class _HtlcSwapDetailsWidgetState extends State Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ InkWell( borderRadius: BorderRadius.circular(4), hoverColor: Colors.transparent, @@ -53,25 +53,25 @@ class _HtlcSwapDetailsWidgetState extends State }); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 10), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( _isExpanded ? 'Hide details' : 'Show details', style: const TextStyle( - fontSize: 14.0, + fontSize: 14, color: AppColors.subtitleColor, ), ), const SizedBox( - width: 3.0, + width: 3, ), RotationTransition( turns: - Tween(begin: 0.0, end: 0.5).animate(_animationController), - child: const Icon(Icons.keyboard_arrow_down, size: 18.0), + Tween(begin: 0, end: 0.5).animate(_animationController), + child: const Icon(Icons.keyboard_arrow_down, size: 18), ), ], ), @@ -83,11 +83,11 @@ class _HtlcSwapDetailsWidgetState extends State child: Visibility( visible: _isExpanded, child: Column( - children: [ - const SizedBox(height: 20.0), + children: [ + const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.1)), - const SizedBox(height: 20.0), - _getDetailsList(widget.swap) + const SizedBox(height: 20), + _getDetailsList(widget.swap), ], ), ), @@ -97,11 +97,11 @@ class _HtlcSwapDetailsWidgetState extends State } Widget _getDetailsList(HtlcSwap swap) { - final List children = []; - final yourDepositId = swap.direction == P2pSwapDirection.outgoing + final List children = []; + final String yourDepositId = swap.direction == P2pSwapDirection.outgoing ? swap.initialHtlcId : swap.counterHtlcId!; - final counterpartyDepositId = swap.direction == P2pSwapDirection.incoming + final String? counterpartyDepositId = swap.direction == P2pSwapDirection.incoming ? swap.initialHtlcId : swap.counterHtlcId; children.add( @@ -138,7 +138,7 @@ class _HtlcSwapDetailsWidgetState extends State DetailRow( label: 'Hashlock', value: swap.hashLock, - valueToShow: Hash.parse(swap.hashLock).toShortString()), + valueToShow: Hash.parse(swap.hashLock).toShortString(),), ); if (swap.preimage != null) { children.add( @@ -154,8 +154,8 @@ class _HtlcSwapDetailsWidgetState extends State children: children.zip( List.generate( children.length - 1, - (index) => const SizedBox( - height: 15.0, + (int index) => const SizedBox( + height: 15, ), ), ), diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/join_native_swap_modal.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/join_native_swap_modal.dart index b6cd633c..4fffd599 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/join_native_swap_modal.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/join_native_swap_modal.dart @@ -28,12 +28,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/modals/base import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class JoinNativeSwapModal extends StatefulWidget { - final Function(String) onJoinedSwap; const JoinNativeSwapModal({ required this.onJoinedSwap, - Key? key, - }) : super(key: key); + super.key, + }); + final Function(String) onJoinedSwap; @override State createState() => _JoinNativeSwapModalState(); @@ -85,17 +85,17 @@ class _JoinNativeSwapModalState extends State { : FutureBuilder( future: zenon!.embedded.token.getByZts(_initialHltc!.tokenStandard), - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: SyriusErrorWidget(snapshot.error!), ); } else if (snapshot.hasData) { return _getContent(snapshot.data!); } return const Padding( - padding: EdgeInsets.all(50.0), + padding: EdgeInsets.all(50), child: SyriusLoadingWidget(), ); }, @@ -105,17 +105,17 @@ class _JoinNativeSwapModalState extends State { Widget _getSearchView() { return Column( - children: [ + children: [ const SizedBox( - height: 20.0, + height: 20, ), Form( autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, - validator: (value) => InputValidators.checkHash(value), + validator: InputValidators.checkHash, controller: _depositIdController, suffixIcon: RawMaterialButton( shape: const CircleBorder(), @@ -129,30 +129,30 @@ class _JoinNativeSwapModalState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'Deposit ID provided by the counterparty', - contentLeftPadding: 10.0, + contentLeftPadding: 10, ), ), const SizedBox( - height: 25.0, + height: 25, ), Visibility( visible: _initialHtlcError != null, child: Column( - children: [ + children: [ ImportantTextContainer( text: _initialHtlcError ?? '', showBorder: true, ), const SizedBox( - height: 20.0, + height: 20, ), ], ), @@ -162,11 +162,11 @@ class _JoinNativeSwapModalState extends State { ); } - _getInitialHtlcViewModel() { + ViewModelBuilder _getInitialHtlcViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (InitialHtlcForSwapBloc model) { model.stream.listen( - (event) async { + (HtlcInfo? event) async { if (event is HtlcInfo) { _initialHltc = event; _isLoading = false; @@ -186,8 +186,8 @@ class _JoinNativeSwapModalState extends State { }, ); }, - builder: (_, model, __) => _getContinueButton(model), - viewModelBuilder: () => InitialHtlcForSwapBloc(), + builder: (_, InitialHtlcForSwapBloc model, __) => _getContinueButton(model), + viewModelBuilder: InitialHtlcForSwapBloc.new, ); } @@ -202,7 +202,7 @@ class _JoinNativeSwapModalState extends State { ); } - void _onContinueButtonPressed(InitialHtlcForSwapBloc model) async { + Future _onContinueButtonPressed(InitialHtlcForSwapBloc model) async { setState(() { _isLoading = true; _initialHtlcError = null; @@ -214,31 +214,31 @@ class _JoinNativeSwapModalState extends State { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 20.0), + children: [ + const SizedBox(height: 20), Row( - children: [ + children: [ Expanded( child: LabeledInputContainer( labelText: 'Your address', helpText: 'You will receive the swapped funds to this address.', inputWidget: DisabledAddressField( _addressController, - contentLeftPadding: 10.0, + contentLeftPadding: 10, ), ), ), ], ), - const SizedBox(height: 20.0), + const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.1)), - const SizedBox(height: 20.0), + const SizedBox(height: 20), LabeledInputContainer( labelText: 'You are sending', inputWidget: Flexible( child: StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -246,12 +246,12 @@ class _JoinNativeSwapModalState extends State { if (snapshot.hasData) { return AmountInputField( controller: _amountController, - accountInfo: (snapshot.data![_selfAddress]!), - valuePadding: 10.0, + accountInfo: snapshot.data![_selfAddress]!, + valuePadding: 10, textColor: Theme.of(context).colorScheme.inverseSurface, initialToken: _selectedToken, hintText: '0.0', - onChanged: (token, isValid) { + onChanged: (Token token, bool isValid) { setState(() { _selectedToken = token; _isAmountValid = isValid; @@ -280,36 +280,36 @@ class _JoinNativeSwapModalState extends State { htlc: _initialHltc!, token: tokenToReceive, ), - const SizedBox(height: 20.0), + const SizedBox(height: 20), Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'Exchange Rate', style: - TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + TextStyle(fontSize: 14, color: AppColors.subtitleColor), ), _getExchangeRateWidget(tokenToReceive), ], ), ), - const SizedBox(height: 20.0), + const SizedBox(height: 20), Divider(color: Colors.white.withOpacity(0.1)), - if (_safeExpirationTime != null) const SizedBox(height: 20.0), + if (_safeExpirationTime != null) const SizedBox(height: 20), if (_safeExpirationTime != null) BulletPointCard( - bulletPoints: [ + bulletPoints: [ RichText( text: BulletPointCard.textSpan( 'You have ', - children: [ + children: [ TextSpan( text: '${(((_initialHltc!.expirationTime - kMinSafeTimeToFindPreimage.inSeconds - kCounterHtlcDuration.inSeconds) - DateTimeUtils.unixTimeNow) / 60).ceil()} minutes', style: const TextStyle( - fontSize: 14.0, color: Colors.white)), + fontSize: 14, color: Colors.white,),), BulletPointCard.textSpan(' left to join the swap.'), ], ), @@ -317,11 +317,11 @@ class _JoinNativeSwapModalState extends State { RichText( text: BulletPointCard.textSpan( 'The counterparty will have ', - children: [ + children: [ TextSpan( - text: '~${(kCounterHtlcDuration).inHours} hour', + text: '~${kCounterHtlcDuration.inHours} hour', style: const TextStyle( - fontSize: 14.0, color: Colors.white)), + fontSize: 14, color: Colors.white,),), BulletPointCard.textSpan(' to complete the swap.'), ], ), @@ -333,40 +333,38 @@ class _JoinNativeSwapModalState extends State { ), ], ), - const SizedBox(height: 20.0), - _safeExpirationTime != null - ? Column(children: [ + const SizedBox(height: 20), + if (_safeExpirationTime != null) Column(children: [ Visibility( visible: !isTrustedToken(tokenToReceive.tokenStandard.toString()), child: Padding( - padding: const EdgeInsets.only(bottom: 20.0), + padding: const EdgeInsets.only(bottom: 20), child: ImportantTextContainer( text: '''You are receiving a token that is not in your favorites. ''' - '''Please verify that the token standard is correct: ${tokenToReceive.tokenStandard.toString()}''', + '''Please verify that the token standard is correct: ${tokenToReceive.tokenStandard}''', isSelectable: true, ), ), ), _getJoinSwapViewModel(tokenToReceive), - ]) - : const ImportantTextContainer( + ],) else const ImportantTextContainer( text: 'Cannot join swap. The swap will expire too soon for a safe swap.', showBorder: true, - ) + ), ], ); } - _getJoinSwapViewModel(Token tokenToReceive) { + ViewModelBuilder _getJoinSwapViewModel(Token tokenToReceive) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (JoinHtlcSwapBloc model) { model.stream.listen( - (event) async { + (HtlcSwap? event) async { if (event is HtlcSwap) { - widget.onJoinedSwap.call(event.id.toString()); + widget.onJoinedSwap.call(event.id); } }, onError: (error) { @@ -377,8 +375,8 @@ class _JoinNativeSwapModalState extends State { }, ); }, - builder: (_, model, __) => _getJoinSwapButton(model, tokenToReceive), - viewModelBuilder: () => JoinHtlcSwapBloc(), + builder: (_, JoinHtlcSwapBloc model, __) => _getJoinSwapButton(model, tokenToReceive), + viewModelBuilder: JoinHtlcSwapBloc.new, ); } @@ -393,8 +391,8 @@ class _JoinNativeSwapModalState extends State { ); } - void _onJoinButtonPressed( - JoinHtlcSwapBloc model, Token tokenToReceive) async { + Future _onJoinButtonPressed( + JoinHtlcSwapBloc model, Token tokenToReceive,) async { setState(() { _isLoading = true; }); @@ -407,14 +405,14 @@ class _JoinNativeSwapModalState extends State { swapType: P2pSwapType.native, fromChain: P2pSwapChain.nom, toChain: P2pSwapChain.nom, - counterHtlcExpirationTime: _safeExpirationTime!); + counterHtlcExpirationTime: _safeExpirationTime!,); } int? _calculateSafeExpirationTime(int initialHtlcExpiration) { - final minNeededRemainingTime = + final Duration minNeededRemainingTime = kMinSafeTimeToFindPreimage + kCounterHtlcDuration; - final now = DateTimeUtils.unixTimeNow; - final remaining = Duration(seconds: initialHtlcExpiration - now); + final int now = DateTimeUtils.unixTimeNow; + final Duration remaining = Duration(seconds: initialHtlcExpiration - now); return remaining >= minNeededRemainingTime ? now + kCounterHtlcDuration.inSeconds : null; @@ -428,7 +426,7 @@ class _JoinNativeSwapModalState extends State { fromSymbol: _selectedToken.symbol, toAmount: _initialHltc!.amount, toDecimals: tokenToReceive.decimals, - toSymbol: tokenToReceive.symbol); + toSymbol: tokenToReceive.symbol,); } bool _isInputValid() => _isAmountValid; diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/native_p2p_swap_modal.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/native_p2p_swap_modal.dart index fb9cd5fd..e8959dd0 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/native_p2p_swap_modal.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/native_p2p_swap_modal.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:stacked/stacked.dart'; -import 'package:zenon_syrius_wallet_flutter/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/p2p_swap/htlc_swap/complete_htlc_swap_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/p2p_swap/htlc_swap/htlc_swap_bloc.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/p2p_swap/htlc_swap/reclaim_htlc_swap_funds_bloc.dart'; import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/htlc_swap.dart'; import 'package:zenon_syrius_wallet_flutter/model/p2p_swap/p2p_swap.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; @@ -21,14 +21,14 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/modals/base import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class NativeP2pSwapModal extends StatefulWidget { - final String swapId; - final Function(String)? onSwapStarted; const NativeP2pSwapModal({ required this.swapId, this.onSwapStarted, - Key? key, - }) : super(key: key); + super.key, + }); + final String swapId; + final Function(String)? onSwapStarted; @override State createState() => _NativeP2pSwapModalState(); @@ -59,7 +59,7 @@ class _NativeP2pSwapModalState extends State { Widget build(BuildContext context) { return StreamBuilder( stream: _htlcSwapBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return BaseModal( title: _getTitle(snapshot.data!), @@ -69,7 +69,7 @@ class _NativeP2pSwapModalState extends State { return BaseModal( title: '', child: Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: SyriusErrorWidget(snapshot.error!), ), ); @@ -101,18 +101,18 @@ class _NativeP2pSwapModalState extends State { Widget _getPendingView() { return const SizedBox( - height: 215.0, + height: 215, child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Starting swap. This will take a moment.', style: TextStyle( - fontSize: 16.0, + fontSize: 16, ), ), - SizedBox(height: 25.0), - SyriusLoadingWidget() + SizedBox(height: 25), + SyriusLoadingWidget(), ], ), ); @@ -120,13 +120,13 @@ class _NativeP2pSwapModalState extends State { Widget _getActiveView(HtlcSwap swap) { return Column( - children: [ + children: [ const SizedBox( - height: 20.0, + height: 20, ), HtlcCard.sending(swap: swap), const SizedBox( - height: 15.0, + height: 15, ), const Icon( AntDesign.arrowdown, @@ -134,7 +134,7 @@ class _NativeP2pSwapModalState extends State { size: 20, ), const SizedBox( - height: 15.0, + height: 15, ), HtlcCard.receiving(swap: swap), const SizedBox( @@ -148,13 +148,13 @@ class _NativeP2pSwapModalState extends State { Widget _getCompletedView(HtlcSwap swap) { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ const SizedBox( - height: 10.0, + height: 10, ), Container( - width: 72.0, - height: 72.0, + width: 72, + height: 72, color: Colors.transparent, child: SvgPicture.asset( 'assets/svg/ic_completed_symbol.svg', @@ -163,62 +163,62 @@ class _NativeP2pSwapModalState extends State { ), ), const SizedBox( - height: 30.0, + height: 30, ), Text( _swapCompletedText, style: const TextStyle( - fontSize: 16.0, + fontSize: 16, ), ), - const SizedBox(height: 25.0), + const SizedBox(height: 25), Container( decoration: const BoxDecoration( color: Color(0xff282828), - borderRadius: BorderRadius.all(Radius.circular(8.0))), + borderRadius: BorderRadius.all(Radius.circular(8)),), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: Column( - children: [ + children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'From', style: TextStyle( - fontSize: 14.0, color: AppColors.subtitleColor), + fontSize: 14, color: AppColors.subtitleColor,), ), _getAmountAndSymbolWidget( swap.fromAmount.addDecimals(swap.fromDecimals), - swap.fromSymbol), + swap.fromSymbol,), ], ), const SizedBox( - height: 15.0, + height: 15, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'To', style: TextStyle( - fontSize: 14.0, color: AppColors.subtitleColor), + fontSize: 14, color: AppColors.subtitleColor,), ), _getAmountAndSymbolWidget( swap.toAmount!.addDecimals(swap.toDecimals!), - swap.toSymbol!), + swap.toSymbol!,), ], ), const SizedBox( - height: 15.0, + height: 15, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'Exchange Rate', style: TextStyle( - fontSize: 14.0, color: AppColors.subtitleColor), + fontSize: 14, color: AppColors.subtitleColor,), ), _getExchangeRateWidget(swap), ], @@ -236,22 +236,22 @@ class _NativeP2pSwapModalState extends State { } Widget _getUnsuccessfulView(HtlcSwap swap) { - final expiration = swap.direction == P2pSwapDirection.outgoing + final int? expiration = swap.direction == P2pSwapDirection.outgoing ? swap.initialHtlcExpirationTime : swap.counterHtlcExpirationTime; - final remainingDuration = + final Duration remainingDuration = Duration(seconds: (expiration ?? 0) - DateTimeUtils.unixTimeNow); - final isReclaimable = remainingDuration.inSeconds <= 0 && + final bool isReclaimable = remainingDuration.inSeconds <= 0 && swap.state == P2pSwapState.reclaimable; return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ const SizedBox( - height: 10.0, + height: 10, ), Container( - width: 72.0, - height: 72.0, + width: 72, + height: 72, color: Colors.transparent, child: SvgPicture.asset( 'assets/svg/ic_unsuccessful_symbol.svg', @@ -260,26 +260,26 @@ class _NativeP2pSwapModalState extends State { ), ), const SizedBox( - height: 30.0, + height: 30, ), Text( isReclaimable || swap.state == P2pSwapState.unsuccessful ? 'The swap was unsuccessful.' : 'The swap was unsuccessful.\nPlease wait for your deposit to expire to reclaim your funds.', style: const TextStyle( - fontSize: 16.0, + fontSize: 16, ), textAlign: TextAlign.center, ), - const SizedBox(height: 25.0), + const SizedBox(height: 25), Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, - borderRadius: const BorderRadius.all(Radius.circular(8.0))), + borderRadius: const BorderRadius.all(Radius.circular(8)),), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: Column( - children: [ + children: [ if (remainingDuration.inSeconds > 0) TweenAnimationBuilder( duration: remainingDuration, @@ -289,21 +289,21 @@ class _NativeP2pSwapModalState extends State { return Visibility( visible: d.inSeconds > 0, child: Padding( - padding: const EdgeInsets.only(bottom: 15.0), + padding: const EdgeInsets.only(bottom: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'Deposit expires in', style: TextStyle( - fontSize: 14.0, - color: AppColors.subtitleColor), + fontSize: 14, + color: AppColors.subtitleColor,), ), Text( d.toString().split('.').first, style: const TextStyle( - fontSize: 14.0, - color: AppColors.subtitleColor), + fontSize: 14, + color: AppColors.subtitleColor,), ), ], ), @@ -313,17 +313,17 @@ class _NativeP2pSwapModalState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text( swap.state == P2pSwapState.reclaimable ? 'Deposited amount' : 'Deposited amount (reclaimed)', style: const TextStyle( - fontSize: 14.0, color: AppColors.subtitleColor), + fontSize: 14, color: AppColors.subtitleColor,), ), _getAmountAndSymbolWidget( swap.fromAmount.addDecimals(swap.fromDecimals), - swap.fromSymbol), + swap.fromSymbol,), ], ), ], @@ -332,7 +332,7 @@ class _NativeP2pSwapModalState extends State { ), if (isReclaimable) Padding( - padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 5.0), + padding: const EdgeInsets.fromLTRB(0, 20, 0, 5), child: _getReclaimButton(swap), ), const SizedBox( @@ -346,14 +346,14 @@ class _NativeP2pSwapModalState extends State { Widget _getBottomSection(HtlcSwap swap) { if (swap.counterHtlcId == null) { return Column( - children: [ + children: [ const Padding( - padding: EdgeInsets.symmetric(horizontal: 10.0), + padding: EdgeInsets.symmetric(horizontal: 10), child: Text( 'Send your deposit ID to the counterparty via a messaging service so that they can join the swap.', textAlign: TextAlign.center, style: TextStyle( - fontSize: 16.0, + fontSize: 16, ), ), ), @@ -370,23 +370,23 @@ class _NativeP2pSwapModalState extends State { icon: const Icon( Icons.copy, color: Colors.white, - size: 18.0, + size: 18, ), - ) + ), ], ); } else { return Column( - children: [ + children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const Text( 'Exchange Rate', style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: AppColors.subtitleColor, ), ), @@ -400,11 +400,11 @@ class _NativeP2pSwapModalState extends State { Visibility( visible: swap.direction == P2pSwapDirection.outgoing, child: Column( - children: [ + children: [ Visibility( visible: !isTrustedToken(swap.toTokenStandard ?? ''), child: Padding( - padding: const EdgeInsets.only(bottom: 25.0), + padding: const EdgeInsets.only(bottom: 25), child: ImportantTextContainer( text: '''You are receiving a token that is not in your favorites. ''' @@ -425,7 +425,7 @@ class _NativeP2pSwapModalState extends State { Visibility( visible: swap.direction == P2pSwapDirection.incoming, child: const Padding( - padding: EdgeInsets.symmetric(vertical: 15.0), + padding: EdgeInsets.symmetric(vertical: 15), child: LoadingInfoText( text: 'Waiting for the counterparty. Please keep Syrius running.', @@ -440,10 +440,10 @@ class _NativeP2pSwapModalState extends State { } Widget _getExpirationWarningForOutgoingSwap(HtlcSwap swap) { - const warningThreshold = Duration(minutes: 10); - final timeToCompleteSwap = Duration( + const Duration warningThreshold = Duration(minutes: 10); + final Duration timeToCompleteSwap = Duration( seconds: - swap.counterHtlcExpirationTime! - DateTimeUtils.unixTimeNow) - + swap.counterHtlcExpirationTime! - DateTimeUtils.unixTimeNow,) - kMinSafeTimeToCompleteSwap; return TweenAnimationBuilder( duration: timeToCompleteSwap, @@ -453,7 +453,7 @@ class _NativeP2pSwapModalState extends State { return Visibility( visible: timeToCompleteSwap <= warningThreshold, child: Padding( - padding: const EdgeInsets.only(bottom: 25.0), + padding: const EdgeInsets.only(bottom: 25), child: ImportantTextContainer( text: 'The swap will expire in ${d.toString().split('.').first}', ), @@ -465,9 +465,9 @@ class _NativeP2pSwapModalState extends State { Widget _getSwapButtonViewModel(HtlcSwap swap) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (CompleteHtlcSwapBloc model) { model.stream.listen( - (event) async { + (HtlcSwap? event) async { if (event is HtlcSwap) { setState(() { _swapCompletedText = @@ -483,7 +483,7 @@ class _NativeP2pSwapModalState extends State { }, ); }, - builder: (_, model, __) => InstructionButton( + builder: (_, CompleteHtlcSwapBloc model, __) => InstructionButton( text: 'Swap', isEnabled: true, isLoading: _isSendingTransaction, @@ -495,13 +495,13 @@ class _NativeP2pSwapModalState extends State { model.completeHtlcSwap(swap: swap); }, ), - viewModelBuilder: () => CompleteHtlcSwapBloc(), + viewModelBuilder: CompleteHtlcSwapBloc.new, ); } Widget _getIncorrectAmountButton(HtlcSwap swap) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 10), child: SizedBox( width: double.infinity, child: AnimatedCrossFade( @@ -513,9 +513,9 @@ class _NativeP2pSwapModalState extends State { }), child: const Center( child: Text( - 'I\'m receiving the wrong token or amount.', + "I'm receiving the wrong token or amount.", style: TextStyle( - fontSize: 14.0, + fontSize: 14, color: AppColors.subtitleColor, ), ), @@ -536,14 +536,14 @@ class _NativeP2pSwapModalState extends State { 'If the token or the amount you are receiving is not what you have agreed upon, wait until your deposit expires to reclaim your funds.\nYour deposit will expire at ${FormatUtils.formatDate(expirationTime * 1000, dateFormat: kDefaultDateTimeFormat)}.', textAlign: TextAlign.center, style: const TextStyle( - fontSize: 14.0, + fontSize: 14, ), ); } Widget _getReclaimButton(HtlcSwap swap) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (ReclaimHtlcSwapFundsBloc model) { model.stream.listen( null, onError: (error) { @@ -553,7 +553,7 @@ class _NativeP2pSwapModalState extends State { }, ); }, - builder: (_, model, __) => InstructionButton( + builder: (_, ReclaimHtlcSwapFundsBloc model, __) => InstructionButton( text: 'Reclaim funds', isEnabled: true, isLoading: _isSendingTransaction, @@ -570,7 +570,7 @@ class _NativeP2pSwapModalState extends State { ); }, ), - viewModelBuilder: () => ReclaimHtlcSwapFundsBloc(), + viewModelBuilder: ReclaimHtlcSwapFundsBloc.new, ); } @@ -581,18 +581,18 @@ class _NativeP2pSwapModalState extends State { fromSymbol: swap.fromSymbol, toAmount: swap.toAmount!, toDecimals: swap.toDecimals!, - toSymbol: swap.toSymbol!); + toSymbol: swap.toSymbol!,); } Widget _getAmountAndSymbolWidget(String amount, String symbol) { return Row( - children: [ + children: [ Container( constraints: const BoxConstraints(maxWidth: 150), child: Text( amount, style: - const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + const TextStyle(fontSize: 14, color: AppColors.subtitleColor), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, @@ -603,7 +603,7 @@ class _NativeP2pSwapModalState extends State { child: Text( ' $symbol', style: - const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + const TextStyle(fontSize: 14, color: AppColors.subtitleColor), overflow: TextOverflow.ellipsis, maxLines: 1, softWrap: false, diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart index ccf3e562..5eb17d35 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/modals/base_modal.dart'; class P2PSwapWarningModal extends StatefulWidget { - final Function() onAccepted; const P2PSwapWarningModal({ required this.onAccepted, - Key? key, - }) : super(key: key); + super.key, + }); + final Function() onAccepted; @override State createState() => _P2PSwapWarningModalState(); @@ -24,19 +24,19 @@ class _P2PSwapWarningModalState extends State { Widget _getContent() { return Column( - children: [ + children: [ const SizedBox( - height: 20.0, + height: 20, ), const Text( '''Please note that the P2P swap is an experimental feature and may result in funds being lost.\n\n''' '''Use the feature with caution and consider splitting large swaps into multiple smaller ones.''', style: TextStyle( - fontSize: 14.0, + fontSize: 14, ), ), const SizedBox( - height: 30.0, + height: 30, ), SizedBox( width: double.infinity, diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/recover_deposit_modal.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/recover_deposit_modal.dart index bb584119..9fa20e21 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/recover_deposit_modal.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/recover_deposit_modal.dart @@ -13,8 +13,8 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class RecoverDepositModal extends StatefulWidget { const RecoverDepositModal({ - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _RecoverDepositModalState(); @@ -59,13 +59,13 @@ class _RecoverDepositModalState extends State { Widget _getPendingFundsView() { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ const SizedBox( - height: 10.0, + height: 10, ), Container( - width: 72.0, - height: 72.0, + width: 72, + height: 72, color: Colors.transparent, child: SvgPicture.asset( 'assets/svg/ic_completed_symbol.svg', @@ -74,16 +74,16 @@ class _RecoverDepositModalState extends State { ), ), const SizedBox( - height: 30.0, + height: 30, ), const Text( 'Recovery transaction sent. You will receive the funds shortly.', style: TextStyle( - fontSize: 16.0, + fontSize: 16, ), ), const SizedBox( - height: 30.0, + height: 30, ), ], ); @@ -91,37 +91,37 @@ class _RecoverDepositModalState extends State { Widget _getSearchView() { return Column( - children: [ + children: [ const SizedBox( - height: 20.0, + height: 20, ), const Text( - 'If you have lost access to the machine that a swap was started on, the deposited funds can be recovered with the deposit ID.\n\nIf you don\'t have the deposit ID, please refer to the swap tutorial for instructions on how to recover it using a block explorer.', + "If you have lost access to the machine that a swap was started on, the deposited funds can be recovered with the deposit ID.\n\nIf you don't have the deposit ID, please refer to the swap tutorial for instructions on how to recover it using a block explorer.", style: TextStyle( - fontSize: 14.0, + fontSize: 14, ), ), const SizedBox( - height: 20.0, + height: 20, ), MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: const Row( - children: [ + children: [ Text( 'View swap tutorial', style: TextStyle( color: AppColors.subtitleColor, - fontSize: 14.0, + fontSize: 14, ), ), SizedBox( - width: 3.0, + width: 3, ), Icon( Icons.open_in_new, - size: 18.0, + size: 18, color: AppColors.subtitleColor, ), ], @@ -130,15 +130,15 @@ class _RecoverDepositModalState extends State { ), ), const SizedBox( - height: 25.0, + height: 25, ), Form( autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, - validator: (value) => InputValidators.checkHash(value), + validator: InputValidators.checkHash, controller: _depositIdController, suffixIcon: RawMaterialButton( shape: const CircleBorder(), @@ -152,30 +152,30 @@ class _RecoverDepositModalState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'Deposit ID', - contentLeftPadding: 10.0, + contentLeftPadding: 10, ), ), const SizedBox( - height: 25.0, + height: 25, ), Visibility( visible: _errorText != null, child: Column( - children: [ + children: [ ImportantTextContainer( text: _errorText ?? '', showBorder: true, ), const SizedBox( - height: 20.0, + height: 20, ), ], ), @@ -187,9 +187,9 @@ class _RecoverDepositModalState extends State { Widget _getRecoverButton() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (RecoverHtlcSwapFundsBloc model) { model.stream.listen( - (event) async { + (AccountBlockTemplate? event) async { if (event is AccountBlockTemplate) { setState(() { _isPendingFunds = true; @@ -204,7 +204,7 @@ class _RecoverDepositModalState extends State { }, ); }, - builder: (_, model, __) => InstructionButton( + builder: (_, RecoverHtlcSwapFundsBloc model, __) => InstructionButton( text: 'Recover deposit', isEnabled: _isHashValid(), isLoading: _isLoading, @@ -218,7 +218,7 @@ class _RecoverDepositModalState extends State { model.recoverFunds(htlcId: Hash.parse(_depositIdController.text)); }, ), - viewModelBuilder: () => RecoverHtlcSwapFundsBloc(), + viewModelBuilder: RecoverHtlcSwapFundsBloc.new, ); } diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/start_native_swap_modal.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/start_native_swap_modal.dart index 4d529be6..3b562137 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/modals/start_native_swap_modal.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/modals/start_native_swap_modal.dart @@ -25,12 +25,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/modals/base import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StartNativeSwapModal extends StatefulWidget { - final Function(String) onSwapStarted; const StartNativeSwapModal({ required this.onSwapStarted, - Key? key, - }) : super(key: key); + super.key, + }); + final Function(String) onSwapStarted; @override State createState() => _StartNativeSwapModalState(); @@ -72,16 +72,16 @@ class _StartNativeSwapModalState extends State { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 20.0), + children: [ + const SizedBox(height: 20), Row( - children: [ + children: [ Expanded( child: LabeledInputContainer( labelText: 'Your address', inputWidget: AddressesDropdown( _selectedSelfAddress, - (address) => setState(() { + (String? address) => setState(() { _selectedSelfAddress = address; sl.get().getBalanceForAllAddresses(); }), @@ -89,7 +89,7 @@ class _StartNativeSwapModalState extends State { ), ), const SizedBox( - width: 20.0, + width: 20, ), Expanded( child: LabeledInputContainer( @@ -98,11 +98,11 @@ class _StartNativeSwapModalState extends State { inputWidget: Form( autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, enabled: !_isLoading, - validator: (value) => _validateCounterpartyAddress(value), + validator: _validateCounterpartyAddress, controller: _counterpartyAddressController, suffixIcon: RawMaterialButton( shape: const CircleBorder(), @@ -116,15 +116,15 @@ class _StartNativeSwapModalState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'Enter NoM address', - contentLeftPadding: 10.0, + contentLeftPadding: 10, ), ), ), @@ -137,7 +137,7 @@ class _StartNativeSwapModalState extends State { inputWidget: Flexible( child: StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -146,12 +146,12 @@ class _StartNativeSwapModalState extends State { return AmountInputField( controller: _amountController, enabled: !_isLoading, - accountInfo: (snapshot.data![_selectedSelfAddress]!), - valuePadding: 10.0, + accountInfo: snapshot.data![_selectedSelfAddress]!, + valuePadding: 10, textColor: Theme.of(context).colorScheme.inverseSurface, initialToken: _selectedToken, hintText: '0.0', - onChanged: (token, isValid) { + onChanged: (Token token, bool isValid) { if (!_isLoading) { setState(() { _selectedToken = token; @@ -170,43 +170,43 @@ class _StartNativeSwapModalState extends State { ), ), ), - const SizedBox(height: 20.0), + const SizedBox(height: 20), BulletPointCard( - bulletPoints: [ + bulletPoints: [ RichText( text: BulletPointCard.textSpan( - 'After starting the swap, wait for the counterparty to join the swap with the agreed upon amount.'), + 'After starting the swap, wait for the counterparty to join the swap with the agreed upon amount.',), ), RichText( text: BulletPointCard.textSpan( '''You can reclaim your funds in ''', - children: [ + children: [ TextSpan( text: '${kInitialHtlcDuration.inHours} hours', style: - const TextStyle(fontSize: 14.0, color: Colors.white)), + const TextStyle(fontSize: 14, color: Colors.white),), BulletPointCard.textSpan( - ' if the counterparty fails to join the swap.'), + ' if the counterparty fails to join the swap.',), ], ), ), RichText( text: BulletPointCard.textSpan( - 'The swap must be completed on this machine.'), + 'The swap must be completed on this machine.',), ), ], ), - const SizedBox(height: 20.0), + const SizedBox(height: 20), _getStartSwapViewModel(), ], ); } - _getStartSwapViewModel() { + ViewModelBuilder _getStartSwapViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (StartHtlcSwapBloc model) { model.stream.listen( - (event) async { + (HtlcSwap? event) async { if (event is HtlcSwap) { widget.onSwapStarted.call(event.id); } @@ -219,8 +219,8 @@ class _StartNativeSwapModalState extends State { }, ); }, - builder: (_, model, __) => _getStartSwapButton(model), - viewModelBuilder: () => StartHtlcSwapBloc(), + builder: (_, StartHtlcSwapBloc model, __) => _getStartSwapButton(model), + viewModelBuilder: StartHtlcSwapBloc.new, ); } @@ -235,7 +235,7 @@ class _StartNativeSwapModalState extends State { ); } - void _onStartButtonPressed(StartHtlcSwapBloc model) async { + Future _onStartButtonPressed(StartHtlcSwapBloc model) async { setState(() { _isLoading = true; }); @@ -249,7 +249,7 @@ class _StartNativeSwapModalState extends State { swapType: P2pSwapType.native, fromChain: P2pSwapChain.nom, toChain: P2pSwapChain.nom, - initialHtlcDuration: kInitialHtlcDuration.inSeconds); + initialHtlcDuration: kInitialHtlcDuration.inSeconds,); } bool _isInputValid() => @@ -258,7 +258,7 @@ class _StartNativeSwapModalState extends State { _isAmountValid; String? _validateCounterpartyAddress(String? address) { - String? result = InputValidators.checkAddress(address); + final String? result = InputValidators.checkAddress(address); if (result != null) { return result; } else { diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_button.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_button.dart index b5ed14fc..0796862e 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_button.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_button.dart @@ -2,17 +2,14 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class P2pSwapOptionsButton extends StatefulWidget { + + const P2pSwapOptionsButton({ + required this.primaryText, required this.secondaryText, required this.onClick, super.key, + }); final VoidCallback onClick; final String primaryText; final String secondaryText; - const P2pSwapOptionsButton({ - Key? key, - required this.primaryText, - required this.secondaryText, - required this.onClick, - }) : super(key: key); - @override State createState() => _P2pSwapOptionsButtonState(); } @@ -23,7 +20,7 @@ class _P2pSwapOptionsButtonState extends State { return Material( color: Theme.of(context).colorScheme.primaryContainer, borderRadius: BorderRadius.circular( - 8.0, + 8, ), child: InkWell( borderRadius: BorderRadius.circular(8), @@ -33,51 +30,51 @@ class _P2pSwapOptionsButtonState extends State { }); }, child: Container( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.02), - offset: const Offset(0.0, 4), + offset: const Offset(0, 4), blurRadius: 6, - spreadRadius: 8.0, + spreadRadius: 8, ), ], borderRadius: BorderRadius.circular( - 8.0, + 8, ), ), child: Row( - children: [ + children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ Text( widget.primaryText, textAlign: TextAlign.left, style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( - height: 8.0, + height: 8, ), Text( widget.secondaryText, textAlign: TextAlign.left, style: const TextStyle( color: AppColors.subtitleColor, - fontSize: 14.0, + fontSize: 14, ), ), ], ), ), const SizedBox( - width: 15.0, + width: 15, ), const Column( - children: [ - Icon(Icons.keyboard_arrow_right, size: 18.0), + children: [ + Icon(Icons.keyboard_arrow_right, size: 18), ], ), ], diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_card.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_card.dart index 1ec9bfa6..ba726dde 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_card.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_card.dart @@ -6,9 +6,9 @@ import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/join_native_swap_modal.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/native_p2p_swap_modal.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/recover_deposit_modal.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/start_native_swap_modal.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/modals/p2p_swap_warning_modal.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_button.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/dialogs.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/error_widget.dart'; @@ -17,8 +17,8 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class P2pSwapOptionsCard extends StatefulWidget { const P2pSwapOptionsCard({ - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _P2pSwapOptionsCardState(); @@ -46,15 +46,15 @@ class _P2pSwapOptionsCardState extends State { ); }, child: Row( - children: [ + children: [ const Icon( Icons.refresh, color: AppColors.znnColor, - size: 20.0, + size: 20, ), const SizedBox( - width: 5.0, - height: 38.0, + width: 5, + height: 38, ), Expanded( child: Text( @@ -72,32 +72,32 @@ class _P2pSwapOptionsCardState extends State { Widget _getWidgetBody(BuildContext context) { return StreamBuilder( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } - final isGeneratingPlasma = _isGeneratingPlasma(snapshot.data); + final bool isGeneratingPlasma = _isGeneratingPlasma(snapshot.data); return Container( - margin: const EdgeInsets.all(20.0), + margin: const EdgeInsets.all(20), child: _getNativeOptions(isGeneratingPlasma), ); }, ); } - void _showUserWarningModalIfNeeded({required Function() onContinue}) { + void _showUserWarningModalIfNeeded({required VoidCallback onContinue}) { final hasReadWarning = sharedPrefsService!.get( kHasReadP2pSwapWarningKey, defaultValue: kHasReadP2pSwapWarningDefaultValue, ); - if (!hasReadWarning) { + if (hasReadWarning == false) { showCustomDialog( context: context, content: P2PSwapWarningModal(onAccepted: () { Navigator.pop(context); sharedPrefsService!.put(kHasReadP2pSwapWarningKey, true); Timer.run(onContinue); - }), + },), ); } else { onContinue(); @@ -118,7 +118,7 @@ class _P2pSwapOptionsCardState extends State { Column _getNativeOptions(bool isGeneratingPlasma) { return Column( - children: [ + children: [ P2pSwapOptionsButton( primaryText: 'Start swap', secondaryText: 'Start a native swap with a counterparty.', @@ -128,11 +128,11 @@ class _P2pSwapOptionsCardState extends State { onContinue: () => showCustomDialog( context: context, content: StartNativeSwapModal( - onSwapStarted: _showNativeSwapModal), - )), + onSwapStarted: _showNativeSwapModal,), + ),), ), const SizedBox( - height: 25.0, + height: 25, ), P2pSwapOptionsButton( primaryText: 'Join swap', @@ -148,27 +148,27 @@ class _P2pSwapOptionsCardState extends State { ), ), const SizedBox( - height: 40.0, + height: 40, ), MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: const Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'View swap tutorial', style: TextStyle( color: AppColors.subtitleColor, - fontSize: 14.0, + fontSize: 14, ), ), SizedBox( - width: 3.0, + width: 3, ), Icon( Icons.open_in_new, - size: 18.0, + size: 18, color: AppColors.subtitleColor, ), ], @@ -177,7 +177,7 @@ class _P2pSwapOptionsCardState extends State { ), ), const SizedBox( - height: 40.0, + height: 40, ), ], ); diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart index a41d09a7..49d99b3e 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart @@ -8,12 +8,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_wid import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class P2pSwapsCard extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const P2pSwapsCard({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _P2pSwapsCardState(); @@ -54,10 +54,10 @@ class _P2pSwapsCardState extends State { return CardScaffold>( title: 'P2P Swaps', childStream: _p2pSwapsListBloc.stream, - onCompletedStatusCallback: (data) => data.isEmpty + onCompletedStatusCallback: (List data) => data.isEmpty ? const SyriusErrorWidget('No P2P swaps') : _getTable(data), - onRefreshPressed: () => _p2pSwapsListBloc.getData(), + onRefreshPressed: _p2pSwapsListBloc.getData, description: 'This card displays a list of P2P swaps that have been conducted ' 'with this wallet.', @@ -66,15 +66,15 @@ class _P2pSwapsCardState extends State { child: GestureDetector( onTap: _onDeleteSwapHistoryTapped, child: Row( - children: [ + children: [ const Icon( Icons.delete, color: AppColors.znnColor, - size: 20.0, + size: 20, ), const SizedBox( - width: 5.0, - height: 38.0, + width: 5, + height: 38, ), Expanded( child: Text( @@ -110,7 +110,7 @@ class _P2pSwapsCardState extends State { await htlcSwapsService!.deleteSwap(swap.id); } _p2pSwapsListBloc.getData(); - }); + },); } Future _onDeleteSwapHistoryTapped() async { @@ -123,17 +123,17 @@ class _P2pSwapsCardState extends State { onYesButtonPressed: () async { await htlcSwapsService!.deleteInactiveSwaps(); _p2pSwapsListBloc.getData(); - }); + },); } Widget _getTable(List swaps) { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( - children: [ + children: [ _getHeader(), const SizedBox( - height: 15.0, + height: 15, ), Visibility( visible: _isListScrolled, @@ -148,17 +148,17 @@ class _P2pSwapsCardState extends State { itemCount: swaps.length, separatorBuilder: (_, __) { return const SizedBox( - height: 15.0, + height: 15, ); }, - itemBuilder: (_, index) { + itemBuilder: (_, int index) { return P2pSwapsListItem( key: ValueKey(swaps.elementAt(index).id), swap: swaps.elementAt(index), onTap: _onSwapTapped, onDelete: _onDeleteSwapTapped, ); - }), + },), ), ), ], @@ -168,9 +168,9 @@ class _P2pSwapsCardState extends State { Widget _getHeader() { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20.0), + padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( - children: [ + children: [ Expanded( flex: 20, child: _getHeaderItem('Status'), @@ -193,24 +193,24 @@ class _P2pSwapsCardState extends State { visible: htlcSwapsService!.isMaxSwapsReached, child: Row( mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ _getHeaderItem( 'Swap history is full', textColor: AppColors.errorColor, - textHeight: 1.0, + textHeight: 1, ), const SizedBox( - width: 5.0, + width: 5, ), const Tooltip( message: 'The oldest swap entry will be deleted when a new swap is started.', child: Padding( - padding: EdgeInsets.only(top: 3.0), + padding: EdgeInsets.only(top: 3), child: Icon( Icons.info, color: AppColors.errorColor, - size: 12.0, + size: 12, ), ), ), @@ -226,7 +226,7 @@ class _P2pSwapsCardState extends State { Widget _getHeaderItem(String text, {Color? textColor, double? textHeight}) { return Text( text, - style: TextStyle(fontSize: 12.0, height: textHeight, color: textColor), + style: TextStyle(fontSize: 12, height: textHeight, color: textColor), ); } } diff --git a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_list_item.dart b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_list_item.dart index eac438f3..a3d7ff94 100644 --- a/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_list_item.dart +++ b/lib/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_list_item.dart @@ -8,16 +8,16 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_wid import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class P2pSwapsListItem extends StatefulWidget { - final P2pSwap swap; - final Function(String) onTap; - final Function(P2pSwap) onDelete; const P2pSwapsListItem({ required this.swap, required this.onTap, required this.onDelete, - Key? key, - }) : super(key: key); + super.key, + }); + final P2pSwap swap; + final Function(String) onTap; + final Function(P2pSwap) onDelete; @override State createState() => _P2pSwapsListItemState(); @@ -30,27 +30,27 @@ class _P2pSwapsListItemState extends State { Widget build(BuildContext context) { return Material( color: Theme.of(context).colorScheme.primaryContainer, - elevation: 1.0, + elevation: 1, borderRadius: BorderRadius.circular( - 8.0, + 8, ), child: InkWell( borderRadius: BorderRadius.circular(8), onTap: () => widget.onTap.call(widget.swap.id), child: Container( - height: 56.0, - padding: const EdgeInsets.symmetric(horizontal: 20.0), + height: 56, + padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( - children: [ + children: [ Expanded( flex: 20, child: Row( - children: [ + children: [ _getStatusWidget(), const SizedBox( - width: 8.0, + width: 8, ), - _getStatusText() + _getStatusText(), ], ), ), @@ -60,7 +60,7 @@ class _P2pSwapsListItemState extends State { widget.swap.fromAmount, widget.swap.fromDecimals, widget.swap.fromTokenStandard, - widget.swap.fromSymbol), + widget.swap.fromSymbol,), ), Expanded( flex: 20, @@ -69,7 +69,7 @@ class _P2pSwapsListItemState extends State { widget.swap.toAmount, widget.swap.toDecimals, widget.swap.toTokenStandard, - widget.swap.toSymbol) + widget.swap.toSymbol,) : _getTextWidget('-'), ), Expanded( @@ -90,21 +90,21 @@ class _P2pSwapsListItemState extends State { } Widget _getStatusWidget() { - const size = 16.0; + const double size = 16; switch (widget.swap.state) { case P2pSwapState.pending: case P2pSwapState.active: return const SyriusLoadingWidget( - size: 12.0, - strokeWidth: 2.0, - padding: 2.0, + size: 12, + strokeWidth: 2, + padding: 2, ); case P2pSwapState.completed: return const Icon(Icons.check_circle_outline, - color: AppColors.znnColor, size: size); + color: AppColors.znnColor, size: size,); default: return const Icon(Icons.cancel_outlined, - color: AppColors.errorColor, size: size); + color: AppColors.errorColor, size: size,); } } @@ -113,13 +113,10 @@ class _P2pSwapsListItemState extends State { switch (widget.swap.state) { case P2pSwapState.pending: text = 'Starting'; - break; case P2pSwapState.active: text = 'Active'; - break; case P2pSwapState.completed: text = 'Completed'; - break; default: text = 'Unsuccessful'; } @@ -129,14 +126,14 @@ class _P2pSwapsListItemState extends State { Widget _getTextWidget(String text) { return Text(text, style: const TextStyle( - fontSize: 12.0, height: 1, color: AppColors.subtitleColor), + fontSize: 12, height: 1, color: AppColors.subtitleColor,), overflow: TextOverflow.ellipsis, maxLines: 1, - softWrap: false); + softWrap: false,); } Widget _getAmountWidget( - BigInt? amount, int? decimals, String? tokenStandard, String? symbol) { + BigInt? amount, int? decimals, String? tokenStandard, String? symbol,) { if (amount == null || decimals == null || tokenStandard == null || @@ -144,9 +141,9 @@ class _P2pSwapsListItemState extends State { return _getTextWidget('-'); } return Row( - children: [ + children: [ Row( - children: [ + children: [ Container( constraints: const BoxConstraints(maxWidth: 70), child: _getTextWidget(amount.addDecimals(decimals)), @@ -158,11 +155,11 @@ class _P2pSwapsListItemState extends State { ], ), const SizedBox( - width: 6.0, + width: 6, ), Container( - height: 6.0, - width: 6.0, + height: 6, + width: 6, decoration: BoxDecoration( shape: BoxShape.circle, color: ColorUtils.getTokenColor( @@ -186,7 +183,7 @@ class _P2pSwapsListItemState extends State { height: 32, decoration: BoxDecoration( borderRadius: BorderRadius.circular( - 4.0, + 4, ), color: const Color(0xff333333), ), @@ -201,7 +198,7 @@ class _P2pSwapsListItemState extends State { color: _isDeleteIconHovered ? Colors.white : AppColors.subtitleColor, - size: 18.0, + size: 18, ), ), ), @@ -214,12 +211,12 @@ class _P2pSwapsListItemState extends State { child: FittedBox( fit: BoxFit.scaleDown, child: SizedBox( - height: 32.0, + height: 32, child: ElevatedButton( onPressed: () => widget.onTap.call(widget.swap.id), child: const Text( 'Reclaim funds', - style: TextStyle(fontSize: 12.0, color: Colors.white), + style: TextStyle(fontSize: 12, color: Colors.white), ), ), ), @@ -231,17 +228,17 @@ class _P2pSwapsListItemState extends State { } String _formatTime(int transactionMillis) { - int currentMillis = DateTime.now().millisecondsSinceEpoch; + final int currentMillis = DateTime.now().millisecondsSinceEpoch; if (currentMillis - transactionMillis <= const Duration(days: 1).inMilliseconds) { return _formatTimeShort(currentMillis - transactionMillis); } return FormatUtils.formatDate(transactionMillis, - dateFormat: 'MM/dd/yyyy hh:mm a'); + dateFormat: 'MM/dd/yyyy hh:mm a',); } String _formatTimeShort(int i) { - Duration duration = Duration(milliseconds: i); + final Duration duration = Duration(milliseconds: i); if (duration.inHours > 0) { return '${duration.inHours} h ago'; } diff --git a/lib/widgets/modular_widgets/pillar_widgets/create_pillar.dart b/lib/widgets/modular_widgets/pillar_widgets/create_pillar.dart index c05533ca..347ea0aa 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/create_pillar.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/create_pillar.dart @@ -9,12 +9,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CreatePillar extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const CreatePillar({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _CreatePillarState(); @@ -36,7 +36,7 @@ class _CreatePillarState extends State { Widget _getStreamBuilder(BuildContext context) { return StreamBuilder>( stream: _getPillarByOwnerBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot> snapshot) { if (snapshot.hasData) { if (snapshot.data!.isNotEmpty) { return _getUpdatePillarWidgetBody(context, snapshot.data!.first); @@ -54,17 +54,17 @@ class _CreatePillarState extends State { Widget _getCreatePillarWidgetBody(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ + children: [ Lottie.asset('assets/lottie/ic_anim_pillar.json', repeat: false), Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ SyriusElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: const PillarStepperContainer(), onStepperNotificationSeeMorePressed: widget.onStepperNotificationSeeMorePressed, @@ -79,7 +79,7 @@ class _CreatePillarState extends State { ], ), const SizedBox( - width: 10.0, + width: 10, ), ], ); @@ -91,7 +91,7 @@ class _CreatePillarState extends State { ) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ + children: [ Expanded( child: Lottie.asset( 'assets/lottie/ic_anim_pillar.json', @@ -102,7 +102,7 @@ class _CreatePillarState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Update Pillar settings', style: Theme.of(context).textTheme.headlineSmall, @@ -110,13 +110,13 @@ class _CreatePillarState extends State { kVerticalSpacing, Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ SyriusElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: PillarUpdateStepper(pillarInfo), onStepperNotificationSeeMorePressed: widget.onStepperNotificationSeeMorePressed, @@ -147,7 +147,7 @@ class _CreatePillarState extends State { child: const Icon( MaterialCommunityIcons.plus, color: Colors.white, - size: 15.0, + size: 15, ), ); } diff --git a/lib/widgets/modular_widgets/pillar_widgets/pillar_collect.dart b/lib/widgets/modular_widgets/pillar_widgets/pillar_collect.dart index d4662c73..46e7dae8 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/pillar_collect.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/pillar_collect.dart @@ -11,12 +11,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PillarCollect extends StatefulWidget { - final PillarRewardsHistoryBloc pillarRewardsHistoryBloc; const PillarCollect({ required this.pillarRewardsHistoryBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final PillarRewardsHistoryBloc pillarRewardsHistoryBloc; @override State createState() => _PillarCollectState(); @@ -40,7 +40,7 @@ class _PillarCollectState extends State { 'registered in the network, but also deployed (use znn-controller for ' 'this operation) and it must produce momentums', childBuilder: () => Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: _getFutureBuilder(), ), ); @@ -49,7 +49,7 @@ class _PillarCollectState extends State { Widget _getFutureBuilder() { return StreamBuilder( stream: _pillarCollectRewardsBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { @@ -66,18 +66,17 @@ class _PillarCollectState extends State { Widget _getWidgetBody(UncollectedReward uncollectedReward) { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ NumberAnimation( end: uncollectedReward.znnAmount .addDecimals( coinDecimals, ) .toNum(), - isInt: false, after: ' ${kZnnCoin.symbol}', style: Theme.of(context).textTheme.headlineLarge!.copyWith( color: AppColors.znnColor, - fontSize: 30.0, + fontSize: 30, ), ), kVerticalSpacing, @@ -103,7 +102,7 @@ class _PillarCollectState extends State { 'collect Pillar rewards', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); if (mounted) { _pillarCollectRewardsBloc.updateStream(); @@ -113,7 +112,7 @@ class _PillarCollectState extends State { ); } catch (e) { await NotificationUtils.sendNotificationError( - e, 'Error while collecting Pillar rewards'); + e, 'Error while collecting Pillar rewards',); } finally { _collectButtonKey.currentState?.animateReverse(); } diff --git a/lib/widgets/modular_widgets/pillar_widgets/pillar_list_widget.dart b/lib/widgets/modular_widgets/pillar_widgets/pillar_list_widget.dart index ddb59ef4..4113d069 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/pillar_list_widget.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/pillar_list_widget.dart @@ -15,9 +15,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PillarListWidget extends StatefulWidget { - final String? title; - const PillarListWidget({Key? key, this.title}) : super(key: key); + const PillarListWidget({super.key, this.title}); + final String? title; @override State createState() => _PillarListWidgetState(); @@ -34,9 +34,9 @@ class _PillarListWidgetState extends State { final PillarsListBloc _pillarsListBloc = PillarsListBloc(); final DelegationInfoBloc _delegationInfoBloc = DelegationInfoBloc(); - final List _pillarInfoWrappers = []; + final List _pillarInfoWrappers = []; - final Map> _delegateButtonKeys = {}; + final Map> _delegateButtonKeys = >{}; bool _sortAscending = true; @@ -50,11 +50,11 @@ class _PillarListWidgetState extends State { void initState() { super.initState(); sl.get().getBalanceForAllAddresses(); - _pagingController.addPageRequestListener((pageKey) { + _pagingController.addPageRequestListener((int pageKey) { _pillarsListBloc.onPageRequestSink.add(pageKey); }); _blocListingStateSubscription = _pillarsListBloc.onNewListingState.listen( - (listingState) { + (InfiniteScrollBlocListingState listingState) { _pagingController.value = PagingState( nextPageKey: listingState.nextPageKey, error: listingState.error, @@ -93,7 +93,7 @@ class _PillarListWidgetState extends State { ) { return StreamBuilder( stream: _delegationInfoBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -112,7 +112,7 @@ class _PillarListWidgetState extends State { Widget _getTable(PillarsListBloc bloc) { return Column( - children: [ + children: [ _getTableHeader(bloc), Expanded( child: Scrollbar( @@ -121,7 +121,7 @@ class _PillarListWidgetState extends State { scrollController: _scrollController, pagingController: _pagingController, builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (_, item, index) => _getTableRow( + itemBuilder: (_, PillarInfo item, int index) => _getTableRow( item, index, ), @@ -147,22 +147,21 @@ class _PillarListWidgetState extends State { border: Border( bottom: BorderSide( color: Theme.of(context).dividerTheme.color!, - width: 1.0, ), ), ), padding: const EdgeInsets.symmetric( - vertical: 15.0, + vertical: 15, ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + - [ + [ InfiniteScrollTableHeaderColumn( columnName: 'Name', onSortArrowsPressed: _onSortArrowsPressed, @@ -178,9 +177,9 @@ class _PillarListWidgetState extends State { ), const InfiniteScrollTableHeaderColumn(columnName: 'Delegation'), const InfiniteScrollTableHeaderColumn( - columnName: 'Momentum reward'), + columnName: 'Momentum reward',), const InfiniteScrollTableHeaderColumn( - columnName: 'Delegation reward'), + columnName: 'Delegation reward',), const InfiniteScrollTableHeaderColumn( columnName: 'Expected/produced momentums', ), @@ -189,30 +188,28 @@ class _PillarListWidgetState extends State { ), const InfiniteScrollTableHeaderColumn( columnName: '', - flex: 1, ), const SizedBox( - width: 5.0, - ) + width: 5, + ), ] + - [ + [ SizedBox( width: 110, child: Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Visibility( visible: _delegationInfo?.name != null, child: _getUndelegateButtonViewModel(bloc), ), - ])), - ]), + ],),), + ],), ); } Widget _getTableRow(dynamic item, int indexOfRow) { - bool isSelected = _selectedRowIndex == indexOfRow; + final bool isSelected = _selectedRowIndex == indexOfRow; return InkWell( onTap: () { @@ -226,7 +223,7 @@ class _PillarListWidgetState extends State { }, child: Container( constraints: const BoxConstraints( - minHeight: 75.0, + minHeight: 75, ), decoration: BoxDecoration( color: isSelected @@ -242,25 +239,25 @@ class _PillarListWidgetState extends State { left: isSelected ? const BorderSide( color: AppColors.znnColor, - width: 2.0, + width: 2, ) : BorderSide.none, ), ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + generateRowCells(item, isSelected) + - [ + [ const SizedBox( width: 110, - ) - ]), + ), + ],), ), ); } @@ -273,7 +270,7 @@ class _PillarListWidgetState extends State { PillarInfo pillarInfo, bool isSelected, ) { - return [ + return [ InfiniteScrollTableCell.withText( context, pillarInfo.name, @@ -296,7 +293,7 @@ class _PillarListWidgetState extends State { kZnnCoin.decimals, ), tokenSymbol: kZnnCoin.symbol, - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( '$formattedAmount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium!.copyWith( color: _isStakeAddressDefault(pillarInfo) @@ -321,7 +318,7 @@ class _PillarListWidgetState extends State { '${pillarInfo.giveDelegateRewardPercentage} %', ), InfiniteScrollTableCell.withText(context, - '${pillarInfo.expectedMomentums}/${pillarInfo.producedMomentums} '), + '${pillarInfo.expectedMomentums}/${pillarInfo.producedMomentums} ',), InfiniteScrollTableCell.withText( context, '${_getMomentumsPercentage(pillarInfo)} %', @@ -341,7 +338,7 @@ class _PillarListWidgetState extends State { PillarsListBloc model, ) { return Row( - children: [ + children: [ Visibility( visible: _currentlyDelegatingToPillar == null ? true @@ -386,7 +383,7 @@ class _PillarListWidgetState extends State { return Visibility( visible: _isStakeAddressDefault(pillarItem), child: Row( - children: [ + children: [ Visibility( visible: pillarItem.isRevocable, child: _getDisassemblePillarViewModel( @@ -398,7 +395,7 @@ class _PillarListWidgetState extends State { Visibility( visible: pillarItem.isRevocable, child: const SizedBox( - width: 5.0, + width: 5, ), ), SizedBox( @@ -444,9 +441,9 @@ class _PillarListWidgetState extends State { PillarInfo pillarInfo, ) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (DisassemblePillarBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { pillarsListModel.refreshResults(); } @@ -459,9 +456,9 @@ class _PillarListWidgetState extends State { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, DisassemblePillarBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getDisassembleButton(isSelected, model, pillarInfo); } @@ -469,12 +466,12 @@ class _PillarListWidgetState extends State { if (snapshot.hasData) { return _getDisassembleButton(isSelected, model, pillarInfo); } - return const SyriusLoadingWidget(size: 25.0); + return const SyriusLoadingWidget(size: 25); } return _getDisassembleButton(isSelected, model, pillarInfo); }, ), - viewModelBuilder: () => DisassemblePillarBloc(), + viewModelBuilder: DisassemblePillarBloc.new, ); } @@ -484,7 +481,7 @@ class _PillarListWidgetState extends State { PillarInfo pillarItem, ) { return MyOutlinedButton( - minimumSize: const Size(55.0, 25.0), + minimumSize: const Size(55, 25), outlineColor: isSelected ? AppColors.errorColor : Theme.of(context).textTheme.titleSmall!.color, @@ -498,7 +495,7 @@ class _PillarListWidgetState extends State { : null, child: Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ Text( 'DISASSEMBLE', style: isSelected @@ -508,11 +505,11 @@ class _PillarListWidgetState extends State { : Theme.of(context).textTheme.titleSmall, ), const SizedBox( - width: 20.0, + width: 20, ), Icon( SimpleLineIcons.close, - size: 11.0, + size: 11, color: isSelected ? AppColors.errorColor : Theme.of(context).textTheme.titleSmall!.color, @@ -544,25 +541,22 @@ class _PillarListWidgetState extends State { switch (columnName) { case 'Name': _sortAscending - ? _pillarInfoWrappers.sort((a, b) => a.name.compareTo(b.name)) - : _pillarInfoWrappers.sort((a, b) => b.name.compareTo(a.name)); - break; + ? _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => a.name.compareTo(b.name)) + : _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => b.name.compareTo(a.name)); case 'Producer Address': _sortAscending ? _pillarInfoWrappers - .sort((a, b) => a.producerAddress.compareTo(b.producerAddress)) + .sort((PillarInfo a, PillarInfo b) => a.producerAddress.compareTo(b.producerAddress)) : _pillarInfoWrappers - .sort((a, b) => b.producerAddress.compareTo(a.producerAddress)); - break; + .sort((PillarInfo a, PillarInfo b) => b.producerAddress.compareTo(a.producerAddress)); case 'Weight': _sortAscending - ? _pillarInfoWrappers.sort((a, b) => a.weight.compareTo(b.weight)) - : _pillarInfoWrappers.sort((a, b) => b.weight.compareTo(a.weight)); - break; + ? _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => a.weight.compareTo(b.weight)) + : _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => b.weight.compareTo(a.weight)); default: _sortAscending - ? _pillarInfoWrappers.sort((a, b) => a.name.compareTo(b.name)) - : _pillarInfoWrappers.sort((a, b) => b.name.compareTo(a.name)); + ? _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => a.name.compareTo(b.name)) + : _pillarInfoWrappers.sort((PillarInfo a, PillarInfo b) => b.name.compareTo(a.name)); break; } @@ -572,12 +566,12 @@ class _PillarListWidgetState extends State { } Widget _getUndelegateButtonViewModel(PillarsListBloc pillarsModel) { - final GlobalKey undelegateButtonKey = GlobalKey(); + final GlobalKey undelegateButtonKey = GlobalKey(); return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (UndelegateButtonBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { undelegateButtonKey.currentState?.animateReverse(); _delegationInfoBloc.updateStream(); @@ -592,11 +586,11 @@ class _PillarListWidgetState extends State { }, ); }, - builder: (_, model, __) => _getUndelegateButton( + builder: (_, UndelegateButtonBloc model, __) => _getUndelegateButton( model, undelegateButtonKey, ), - viewModelBuilder: () => UndelegateButtonBloc(), + viewModelBuilder: UndelegateButtonBloc.new, ); } @@ -606,7 +600,7 @@ class _PillarListWidgetState extends State { ) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return Expanded(child: SyriusErrorWidget(snapshot.error!)); } @@ -644,9 +638,9 @@ class _PillarListWidgetState extends State { ? true : _currentlyDelegatingToPillar == pillarInfo.name), child: ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (DelegateButtonBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _delegationInfoBloc.updateStream(); delegateButtonKey.currentState?.animateReverse(); @@ -667,12 +661,12 @@ class _PillarListWidgetState extends State { }, ); }, - builder: (_, model, __) => _getDelegateButton( + builder: (_, DelegateButtonBloc model, __) => _getDelegateButton( pillarInfo, model, delegateButtonKey, ), - viewModelBuilder: () => DelegateButtonBloc(), + viewModelBuilder: DelegateButtonBloc.new, ), ); } @@ -686,7 +680,7 @@ class _PillarListWidgetState extends State { } int _getMomentumsPercentage(PillarInfo pillarInfo) { - double percentage = + final double percentage = pillarInfo.producedMomentums / pillarInfo.expectedMomentums * 100; if (percentage.isNaN) { return 0; diff --git a/lib/widgets/modular_widgets/pillar_widgets/pillar_rewards.dart b/lib/widgets/modular_widgets/pillar_widgets/pillar_rewards.dart index 89bdb140..b8193280 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/pillar_rewards.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/pillar_rewards.dart @@ -4,10 +4,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PillarRewards extends StatefulWidget { - final PillarRewardsHistoryBloc pillarRewardsHistoryBloc; - const PillarRewards({required this.pillarRewardsHistoryBloc, Key? key}) - : super(key: key); + const PillarRewards({required this.pillarRewardsHistoryBloc, super.key}); + final PillarRewardsHistoryBloc pillarRewardsHistoryBloc; @override State createState() => _PillarRewardsState(); @@ -22,7 +21,7 @@ class _PillarRewardsState extends State { 'Pillar rewards are generated either by operating a Pillar Node or from ' 'delegations to a Pillar Node', childBuilder: () => Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: _getStreamBody(), ), ); @@ -31,7 +30,7 @@ class _PillarRewardsState extends State { Widget _getStreamBody() { return StreamBuilder( stream: widget.pillarRewardsHistoryBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } diff --git a/lib/widgets/modular_widgets/pillar_widgets/pillar_stepper_container.dart b/lib/widgets/modular_widgets/pillar_widgets/pillar_stepper_container.dart index b7b7c0c7..4dc64b4b 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/pillar_stepper_container.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/pillar_stepper_container.dart @@ -34,7 +34,7 @@ enum PillarStepperStep { } class PillarStepperContainer extends StatefulWidget { - const PillarStepperContainer({Key? key}) : super(key: key); + const PillarStepperContainer({super.key}); @override State createState() { @@ -73,13 +73,13 @@ class _MainPillarState extends State { final List> _pillarFormKeys = List.generate( 3, - (index) => GlobalKey(), + (int index) => GlobalKey(), ); late PillarsQsrInfoBloc _pillarsQsrInfoViewModel; - double _momentumRewardPercentageGiven = 0.0; - double _delegateRewardPercentageGiven = 0.0; + double _momentumRewardPercentageGiven = 0; + double _delegateRewardPercentageGiven = 0; @override void initState() { @@ -97,7 +97,7 @@ class _MainPillarState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -117,14 +117,14 @@ class _MainPillarState extends State { Widget _getQsrManagementStep(BuildContext context, AccountInfo accountInfo) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (PillarsQsrInfoBloc model) { _pillarsQsrInfoViewModel = model; model.getQsrManagementInfo( _selectedPillarType, _addressController.text, ); model.stream.listen( - (event) { + (PillarsQsrInfo? event) { if (event != null) { _maxQsrAmount = MathUtils.bigMin( accountInfo.getBalance( @@ -140,9 +140,9 @@ class _MainPillarState extends State { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, PillarsQsrInfoBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return _getQsrManagementStepBody( context, @@ -153,12 +153,12 @@ class _MainPillarState extends State { return SyriusErrorWidget(snapshot.error!); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); }, ), - viewModelBuilder: () => PillarsQsrInfoBloc(), + viewModelBuilder: PillarsQsrInfoBloc.new, ); } @@ -169,14 +169,14 @@ class _MainPillarState extends State { ) { return Row( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( children: [ Expanded( @@ -185,13 +185,13 @@ class _MainPillarState extends State { ], ), const SizedBox( - height: 10.0, + height: 10, ), Padding( - padding: const EdgeInsets.only(left: 20.0), + padding: const EdgeInsets.only(left: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ AvailableBalance( kQsrCoin, accountInfo, @@ -205,10 +205,10 @@ class _MainPillarState extends State { ), ), const SizedBox( - height: 10.0, + height: 10, ), Row( - children: [ + children: [ Expanded( child: Form( key: _qsrFormKey, @@ -219,7 +219,7 @@ class _MainPillarState extends State { _qsrAmountController.text, ), controller: _qsrAmountController, - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, _maxQsrAmount, kQsrCoin.decimals, @@ -227,9 +227,9 @@ class _MainPillarState extends State { ), suffixIcon: _getAmountSuffix(accountInfo), suffixIconConstraints: - const BoxConstraints(maxWidth: 50.0), + const BoxConstraints(maxWidth: 50), hintText: 'Amount', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -238,7 +238,7 @@ class _MainPillarState extends State { ], ), Padding( - padding: const EdgeInsets.symmetric(vertical: 25.0), + padding: const EdgeInsets.symmetric(vertical: 25), child: DottedBorderInfoWidget( text: 'All the deposited ${kQsrCoin.symbol} will be burned ' @@ -249,7 +249,7 @@ class _MainPillarState extends State { ], ), Row( - children: [ + children: [ Visibility( visible: qsrInfo.deposit < qsrInfo.cost, child: _getDepositQsrViewModel(accountInfo, qsrInfo), @@ -262,44 +262,44 @@ class _MainPillarState extends State { ), ), ], - ) + ), ], ), ), const SizedBox( - width: 45.0, + width: 45, ), Expanded( child: Visibility( visible: qsrInfo.deposit > BigInt.zero, child: Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(6), ), margin: const EdgeInsets.only( - bottom: 30.0, + bottom: 30, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 30.0), + padding: const EdgeInsets.symmetric(vertical: 30), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ Column( - children: [ + children: [ Stack( alignment: Alignment.center, - children: [ + children: [ SizedBox( - width: 150.0, - height: 150.0, + width: 150, + height: 150, child: AspectRatio( - aspectRatio: 1.0, + aspectRatio: 1, child: StandardPieChart( - sections: [ + sections: [ PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, value: (qsrInfo.cost - qsrInfo.deposit) / qsrInfo.cost, color: @@ -307,7 +307,7 @@ class _MainPillarState extends State { ), PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, value: qsrInfo.deposit / qsrInfo.cost, color: AppColors.qsrColor, ), @@ -327,9 +327,9 @@ class _MainPillarState extends State { ], ), Column( - children: [ + children: [ SizedBox( - width: 130.0, + width: 130, child: Text( 'You have deposited ${qsrInfo.deposit.addDecimals(coinDecimals)} ' '${kQsrCoin.symbol}', @@ -354,11 +354,11 @@ class _MainPillarState extends State { } Widget _getDepositQsrViewModel( - AccountInfo accountInfo, PillarsQsrInfo qsrInfo) { + AccountInfo accountInfo, PillarsQsrInfo qsrInfo,) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (PillarsDepositQsrBloc model) { model.stream.listen( - (response) { + (AccountBlockTemplate? response) { if (response != null) { _depositQsrButtonKey.currentState?.animateReverse(); _pillarsQsrInfoViewModel.getQsrManagementInfo( @@ -380,9 +380,9 @@ class _MainPillarState extends State { }, ); }, - builder: (_, model, __) => + builder: (_, PillarsDepositQsrBloc model, __) => _getDepositQsrButton(model, accountInfo, qsrInfo), - viewModelBuilder: () => PillarsDepositQsrBloc(), + viewModelBuilder: PillarsDepositQsrBloc.new, ); } @@ -406,9 +406,9 @@ class _MainPillarState extends State { BigInt qsrDeposit, ) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (PillarsWithdrawQsrBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _withdrawButtonKey.currentState?.animateReverse(); _saveProgressAndNavigateToNextStep( @@ -429,8 +429,8 @@ class _MainPillarState extends State { }, ); }, - builder: (_, model, __) => _getWithdrawQsrButton(model, qsrDeposit), - viewModelBuilder: () => PillarsWithdrawQsrBloc(), + builder: (_, PillarsWithdrawQsrBloc model, __) => _getWithdrawQsrButton(model, qsrDeposit), + viewModelBuilder: PillarsWithdrawQsrBloc.new, ); } @@ -459,7 +459,7 @@ class _MainPillarState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Pillar deployment: Plasma check', stepContent: _getPlasmaCheckFutureBuilder(), @@ -508,9 +508,9 @@ class _MainPillarState extends State { Widget _getAmountSuffix(AccountInfo accountInfo) { return Row( - children: [ + children: [ Container( - height: 20.0, + height: 20, alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(3), @@ -518,11 +518,11 @@ class _MainPillarState extends State { ), child: Padding( padding: const EdgeInsets.symmetric( - vertical: 3.0, - horizontal: 7.0, + vertical: 3, + horizontal: 7, ), child: Row( - children: [ + children: [ Text( kQsrCoin.symbol, style: Theme.of(context).textTheme.titleSmall!.copyWith( @@ -539,12 +539,12 @@ class _MainPillarState extends State { Widget _getDeployPillarStepBody(BuildContext context) { return Padding( - padding: const EdgeInsets.only(bottom: 25.0), + padding: const EdgeInsets.only(bottom: 25), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: Form( key: _pillarFormKeys[0], @@ -554,23 +554,21 @@ class _MainPillarState extends State { controller: _pillarNameController, thisNode: _pillarNameNode, nextNode: _pillarRewardNode, - validator: (value) => Validations.pillarName( - value, - ), - onChanged: (value) { + validator: Validations.pillarName, + onChanged: (String value) { setState(() {}); }, ), ), ), const SizedBox( - width: 23.0, - ) + width: 23, + ), ], ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _pillarFormKeys[1], @@ -581,7 +579,7 @@ class _MainPillarState extends State { thisNode: _pillarRewardNode, nextNode: _pillarMomentumNode, validator: InputValidators.checkAddress, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -595,7 +593,7 @@ class _MainPillarState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _pillarFormKeys[2], @@ -604,9 +602,8 @@ class _MainPillarState extends State { hintText: 'Pillar producer address', controller: _pillarMomentumController, thisNode: _pillarMomentumNode, - validator: (value) => - InputValidators.validatePillarMomentumAddress(value), - onChanged: (value) { + validator: InputValidators.validatePillarMomentumAddress, + onChanged: (String value) { setState(() {}); }, ), @@ -621,7 +618,7 @@ class _MainPillarState extends State { kVerticalSpacing, _getPillarMomentumRewardsStepContent(), const SizedBox( - height: 25.0, + height: 25, ), _getDeployButton(), ], @@ -631,9 +628,9 @@ class _MainPillarState extends State { Widget _getDeployButton() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (PillarsDeployBloc model) { model.stream.listen( - (response) { + (AccountBlockTemplate? response) { if (response != null) { _registerButtonKey.currentState?.animateReverse(); _saveProgressAndNavigateToNextStep( @@ -647,13 +644,13 @@ class _MainPillarState extends State { onError: (error) async { _registerButtonKey.currentState?.animateReverse(); await NotificationUtils.sendNotificationError( - error, 'Error while deploying a Pillar'); + error, 'Error while deploying a Pillar',); setState(() {}); }, ); }, - builder: (_, model, __) => _getRegisterPillarButton(model), - viewModelBuilder: () => PillarsDeployBloc(), + builder: (_, PillarsDeployBloc model, __) => _getRegisterPillarButton(model), + viewModelBuilder: PillarsDeployBloc.new, ); } @@ -671,9 +668,8 @@ class _MainPillarState extends State { ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), @@ -684,7 +680,7 @@ class _MainPillarState extends State { StepperUtils.getBalanceWidget(kZnnCoin, accountInfo), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -695,11 +691,10 @@ class _MainPillarState extends State { ], ), Padding( - padding: const EdgeInsets.symmetric(vertical: 25.0), + padding: const EdgeInsets.symmetric(vertical: 25), child: DottedBorderInfoWidget( text: 'You will be able to unlock the ${kZnnCoin.symbol} if you ' 'choose to disassemble the Pillar', - borderColor: AppColors.znnColor, ), ), StepperButton( @@ -745,7 +740,7 @@ class _MainPillarState extends State { void _onDeployPressed(PillarsDeployBloc model) { if (_lastCompletedStep == PillarStepperStep.znnManagement) { if (_pillarFormKeys - .every((element) => element.currentState!.validate())) { + .every((GlobalKey element) => element.currentState!.validate())) { _registerButtonKey.currentState?.animateForward(); model.deployPillar( pillarType: _selectedPillarType!, @@ -756,7 +751,7 @@ class _MainPillarState extends State { giveDelegateRewardPercentage: _delegateRewardPercentageGiven.toInt(), ); } else { - for (var element in _pillarFormKeys) { + for (final GlobalKey element in _pillarFormKeys) { element.currentState!.validate(); } } @@ -775,30 +770,29 @@ class _MainPillarState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), Visibility( visible: (_lastCompletedStep?.index ?? -1) == _numSteps - 1, child: Column( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Container( padding: const EdgeInsets.symmetric( - vertical: 40.0, - horizontal: 50.0, + vertical: 40, + horizontal: 50, ), margin: const EdgeInsets.symmetric( - vertical: 20.0, - horizontal: 50.0, + vertical: 20, + horizontal: 50, ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondaryContainer, borderRadius: const BorderRadius.all( Radius.circular( - 10.0, + 10, ), ), ), @@ -806,7 +800,7 @@ class _MainPillarState extends State { textAlign: TextAlign.center, text: TextSpan( style: Theme.of(context).textTheme.headlineSmall, - children: [ + children: [ TextSpan( text: 'Pillar ', style: Theme.of(context).textTheme.headlineSmall, @@ -840,7 +834,7 @@ class _MainPillarState extends State { ), const WidgetSpan( child: Icon(MaterialCommunityIcons.link, - size: 20.0, color: AppColors.znnColor), + size: 20, color: AppColors.znnColor,), ), TextSpan( text: ' to check the Pillar status', @@ -852,20 +846,19 @@ class _MainPillarState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton.icon( - context: context, label: 'Register another Pillar', onPressed: _onDeployAnotherPillarButtonPressed, iconData: Icons.refresh, ), const SizedBox( - width: 80.0, + width: 80, ), - _getViewPillarsButton() + _getViewPillarsButton(), ], ), - Container(height: 20.0) + Container(height: 20), ], ), ), @@ -874,10 +867,10 @@ class _MainPillarState extends State { Visibility( visible: (_lastCompletedStep?.index ?? -1) == _numSteps - 1, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_pillar.json', @@ -893,7 +886,6 @@ class _MainPillarState extends State { Widget _getViewPillarsButton() { return StepperButton.icon( - context: context, label: 'View Pillars', onPressed: () { Navigator.pop(context); @@ -902,7 +894,7 @@ class _MainPillarState extends State { ); } - void _onDeployAnotherPillarButtonPressed() async { + Future _onDeployAnotherPillarButtonPressed() async { _pillarNameController.clear(); _pillarRewardAddressController.clear(); _pillarMomentumController.clear(); @@ -911,9 +903,7 @@ class _MainPillarState extends State { _selectedPillarType, _addressController.text, ); - setState(() { - _iniStepperControllers(); - }); + setState(_iniStepperControllers); } void _saveProgressAndNavigateToNextStep(PillarStepperStep completedStep) { @@ -971,14 +961,14 @@ class _MainPillarState extends State { Widget _getPlasmaCheckFutureBuilder() { return FutureBuilder( future: zenon!.embedded.plasma.get(Address.parse(kSelectedAddress!)), - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { return _getPlasmaCheckBody(snapshot.data!); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); }, @@ -988,28 +978,27 @@ class _MainPillarState extends State { Widget _getPlasmaCheckBody(PlasmaInfo plasmaInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'More Plasma is required to perform complex transactions. Please fuse enough QSR before proceeding.', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( - height: 25.0, + height: 25, ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), ), const SizedBox( - width: 25.0, + width: 25, ), PlasmaIcon(plasmaInfo), ], ), const SizedBox( - height: 25.0, + height: 25, ), StepperButton( text: 'Next', @@ -1037,10 +1026,10 @@ class _MainPillarState extends State { Widget _getPillarMomentumRewardsStepContent() { return Column( - children: [ + children: [ Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Percentage of momentum rewards given to the delegators', style: Theme.of(context).textTheme.headlineSmall, @@ -1048,11 +1037,10 @@ class _MainPillarState extends State { ], ), CustomSlider( - activeColor: AppColors.znnColor, description: '', - startValue: 0.0, + startValue: 0, min: 0, - maxValue: 100.0, + maxValue: 100, callback: (double value) { setState(() { _momentumRewardPercentageGiven = value; @@ -1061,7 +1049,7 @@ class _MainPillarState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text( 'Pillar: ${100 - _momentumRewardPercentageGiven.toInt()}', style: Theme.of(context).textTheme.titleMedium, @@ -1075,7 +1063,7 @@ class _MainPillarState extends State { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Percentage of delegation rewards given to the delegators', style: Theme.of(context).textTheme.headlineSmall, @@ -1083,11 +1071,10 @@ class _MainPillarState extends State { ], ), CustomSlider( - activeColor: AppColors.znnColor, description: '', - startValue: 0.0, + startValue: 0, min: 0, - maxValue: 100.0, + maxValue: 100, callback: (double value) { setState(() { _delegateRewardPercentageGiven = value; @@ -1096,7 +1083,7 @@ class _MainPillarState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text( 'Pillar: ${100 - _delegateRewardPercentageGiven.toInt()}', style: Theme.of(context).textTheme.titleMedium, diff --git a/lib/widgets/modular_widgets/pillar_widgets/pillar_update_stepper.dart b/lib/widgets/modular_widgets/pillar_widgets/pillar_update_stepper.dart index 24ee9f7b..1e01124e 100644 --- a/lib/widgets/modular_widgets/pillar_widgets/pillar_update_stepper.dart +++ b/lib/widgets/modular_widgets/pillar_widgets/pillar_update_stepper.dart @@ -2,13 +2,12 @@ import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; import 'package:stacked/stacked.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/input_validators.dart'; import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/custom_material_stepper.dart' as custom_material_stepper; +import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; enum PillarUpdateStep { @@ -18,9 +17,9 @@ enum PillarUpdateStep { } class PillarUpdateStepper extends StatefulWidget { - final PillarInfo pillarInfo; - const PillarUpdateStepper(this.pillarInfo, {Key? key}) : super(key: key); + const PillarUpdateStepper(this.pillarInfo, {super.key}); + final PillarInfo pillarInfo; @override State createState() => _PillarUpdateStepperState(); @@ -62,21 +61,21 @@ class _PillarUpdateStepperState extends State { @override Widget build(BuildContext context) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(), ], ), Visibility( visible: _lastCompletedStep == PillarUpdateStep.pillarUpdate, child: Positioned( - bottom: 20.0, - right: 0.0, - left: 0.0, + bottom: 20, + right: 0, + left: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton( text: 'View Pillars', onPressed: () { @@ -90,13 +89,13 @@ class _PillarUpdateStepperState extends State { Visibility( visible: _lastCompletedStep == PillarUpdateStep.pillarUpdate, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset('assets/lottie/ic_anim_pillar.json', - repeat: false), + repeat: false,), ), ), ), @@ -115,7 +114,7 @@ class _PillarUpdateStepperState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Pillar details', stepContent: _getPillarDetailsStepContent(), @@ -157,7 +156,7 @@ class _PillarUpdateStepperState extends State { Widget _getPillarDetailsStepContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'Pillar name', style: Theme.of(context).textTheme.bodyLarge, @@ -182,7 +181,7 @@ class _PillarUpdateStepperState extends State { thisNode: _pillarRewardNode, nextNode: _pillarMomentumNode, validator: InputValidators.checkAddress, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -200,17 +199,15 @@ class _PillarUpdateStepperState extends State { hintText: 'Pillar producer address', controller: _pillarProducerController, thisNode: _pillarMomentumNode, - validator: (value) => InputValidators.validatePillarMomentumAddress( - value, - ), - onChanged: (value) { + validator: InputValidators.validatePillarMomentumAddress, + onChanged: (String value) { setState(() {}); }, ), ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { Navigator.pop(context); @@ -218,7 +215,7 @@ class _PillarUpdateStepperState extends State { text: 'Cancel', ), const SizedBox( - width: 25.0, + width: 25, ), StepperButton( onPressed: _arePillarDetailsValid() @@ -239,10 +236,10 @@ class _PillarUpdateStepperState extends State { Widget _getPillarMomentumRewardsStepContent() { return Column( - children: [ + children: [ Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Percentage of momentum rewards given to the delegators', style: Theme.of(context).textTheme.headlineSmall, @@ -250,11 +247,10 @@ class _PillarUpdateStepperState extends State { ], ), CustomSlider( - activeColor: AppColors.znnColor, description: '', startValue: widget.pillarInfo.giveMomentumRewardPercentage.toDouble(), - min: 0.0, - maxValue: 100.0, + min: 0, + maxValue: 100, callback: (double value) { setState(() { _momentumRewardPercentageGiven = value; @@ -263,7 +259,7 @@ class _PillarUpdateStepperState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text( 'Pillar: ${100 - _momentumRewardPercentageGiven.toInt()}', style: Theme.of(context).textTheme.titleMedium, @@ -277,7 +273,7 @@ class _PillarUpdateStepperState extends State { kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Percentage of delegation rewards given to the delegators', style: Theme.of(context).textTheme.headlineSmall, @@ -285,11 +281,10 @@ class _PillarUpdateStepperState extends State { ], ), CustomSlider( - activeColor: AppColors.znnColor, description: '', startValue: widget.pillarInfo.giveDelegateRewardPercentage.toDouble(), - min: 0.0, - maxValue: 100.0, + min: 0, + maxValue: 100, callback: (double value) { setState(() { _delegateRewardPercentageGiven = value; @@ -298,7 +293,7 @@ class _PillarUpdateStepperState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Text( 'Pillar: ${100 - _delegateRewardPercentageGiven.toInt()}', style: Theme.of(context).textTheme.titleMedium, @@ -311,7 +306,7 @@ class _PillarUpdateStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -322,7 +317,7 @@ class _PillarUpdateStepperState extends State { text: 'Go back', ), const SizedBox( - width: 25.0, + width: 25, ), StepperButton( onPressed: () { @@ -341,7 +336,7 @@ class _PillarUpdateStepperState extends State { Widget _getPillarUpdateStepContent() { return Row( - children: [ + children: [ StepperButton( onPressed: () { setState(() { @@ -352,7 +347,7 @@ class _PillarUpdateStepperState extends State { text: 'Go back', ), const SizedBox( - width: 25.0, + width: 25, ), _getUpdatePillarViewModel(), ], @@ -379,14 +374,14 @@ class _PillarUpdateStepperState extends State { bool _arePillarDetailsValid() => InputValidators.checkAddress(_pillarRewardController.text) == null && InputValidators.validatePillarMomentumAddress( - _pillarProducerController.text) == + _pillarProducerController.text,) == null; Widget _getUpdatePillarViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (UpdatePillarBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _updateButtonKey.currentState?.animateReverse(); setState(() { @@ -403,8 +398,8 @@ class _PillarUpdateStepperState extends State { }, ); }, - builder: (_, model, __) => _getUpdatePillarButton(model), - viewModelBuilder: () => UpdatePillarBloc(), + builder: (_, UpdatePillarBloc model, __) => _getUpdatePillarButton(model), + viewModelBuilder: UpdatePillarBloc.new, ); } diff --git a/lib/widgets/modular_widgets/plasma_widgets/plasma_list/plasma_list.dart b/lib/widgets/modular_widgets/plasma_widgets/plasma_list/plasma_list.dart index c725594f..6a000989 100644 --- a/lib/widgets/modular_widgets/plasma_widgets/plasma_list/plasma_list.dart +++ b/lib/widgets/modular_widgets/plasma_widgets/plasma_list/plasma_list.dart @@ -10,12 +10,11 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PlasmaList extends StatefulWidget { + + const PlasmaList({required this.bloc, this.errorText, super.key}); final String? errorText; final PlasmaListBloc bloc; - const PlasmaList({required this.bloc, this.errorText, Key? key}) - : super(key: key); - @override State createState() { return _PlasmaListState(); @@ -23,7 +22,7 @@ class PlasmaList extends StatefulWidget { } class _PlasmaListState extends State { - final List _stakingList = []; + final List _stakingList = []; bool _sortAscending = true; @@ -44,7 +43,7 @@ class _PlasmaListState extends State { return InfiniteScrollTable( disposeBloc: false, bloc: bloc, - headerColumns: [ + headerColumns: [ InfiniteScrollTableHeaderColumn( columnName: 'Amount', onSortArrowsPressed: _onSortArrowsPressed, @@ -58,15 +57,15 @@ class _PlasmaListState extends State { columnName: 'Expiration', ), ], - generateRowCells: (plasmaItem, bool isSelected) { - return [ + generateRowCells: (FusionEntry plasmaItem, bool isSelected) { + return [ InfiniteScrollTableCell( FormattedAmountWithTooltip( amount: plasmaItem.qsrAmount.addDecimals( kQsrCoin.decimals, ), tokenSymbol: kQsrCoin.symbol, - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( '$formattedAmount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -95,11 +94,8 @@ class _PlasmaListState extends State { ) { return Stack( alignment: Alignment.centerLeft, - fit: StackFit.loose, - children: [ - plasmaItem.isRevocable! - ? _getCancelButtonViewModel(plasmaModel, isSelected, plasmaItem) - : _getCancelCountdownTimer(plasmaItem, plasmaModel) + children: [ + if (plasmaItem.isRevocable!) _getCancelButtonViewModel(plasmaModel, isSelected, plasmaItem) else _getCancelCountdownTimer(plasmaItem, plasmaModel), ], ); } @@ -109,12 +105,12 @@ class _PlasmaListState extends State { bool isSelected, FusionEntry plasmaItem, ) { - final GlobalKey cancelButtonKey = GlobalKey(); + final GlobalKey cancelButtonKey = GlobalKey(); return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (CancelPlasmaBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { cancelButtonKey.currentState?.animateReverse(); plasmaModel.refreshResults(); @@ -123,16 +119,16 @@ class _PlasmaListState extends State { onError: (error) async { cancelButtonKey.currentState?.animateReverse(); await NotificationUtils.sendNotificationError( - error, 'Error while cancelling plasma'); + error, 'Error while cancelling plasma',); }, ); }, - builder: (_, model, __) => _getCancelButton( + builder: (_, CancelPlasmaBloc model, __) => _getCancelButton( model, plasmaItem.id.toString(), cancelButtonKey, ), - viewModelBuilder: () => CancelPlasmaBloc(), + viewModelBuilder: CancelPlasmaBloc.new, ); } @@ -150,7 +146,7 @@ class _PlasmaListState extends State { key: key, icon: const Icon( SimpleLineIcons.close, - size: 11.0, + size: 11, color: AppColors.errorColor, ), outlineColor: AppColors.errorColor, @@ -164,22 +160,20 @@ class _PlasmaListState extends State { switch (columnName) { case 'Amount': _sortAscending - ? _stakingList.sort((a, b) => a.qsrAmount.compareTo(b.qsrAmount)) - : _stakingList.sort((a, b) => b.qsrAmount.compareTo(a.qsrAmount)); - break; + ? _stakingList.sort((FusionEntry a, FusionEntry b) => a.qsrAmount.compareTo(b.qsrAmount)) + : _stakingList.sort((FusionEntry a, FusionEntry b) => b.qsrAmount.compareTo(a.qsrAmount)); case 'Beneficiary': _sortAscending ? _stakingList - .sort((a, b) => a.beneficiary.compareTo(b.beneficiary)) + .sort((FusionEntry a, FusionEntry b) => a.beneficiary.compareTo(b.beneficiary)) : _stakingList - .sort((a, b) => b.beneficiary.compareTo(a.beneficiary)); - break; + .sort((FusionEntry a, FusionEntry b) => b.beneficiary.compareTo(a.beneficiary)); default: _sortAscending ? _stakingList - .sort((a, b) => a.beneficiary.compareTo(b.beneficiary)) + .sort((FusionEntry a, FusionEntry b) => a.beneficiary.compareTo(b.beneficiary)) : _stakingList - .sort((a, b) => b.beneficiary.compareTo(a.beneficiary)); + .sort((FusionEntry a, FusionEntry b) => b.beneficiary.compareTo(a.beneficiary)); break; } @@ -196,10 +190,10 @@ class _PlasmaListState extends State { FusionEntry plasmaItem, PlasmaListBloc model, ) { - int heightUntilCancellation = + final int heightUntilCancellation = plasmaItem.expirationHeight - model.lastMomentumHeight!; - Duration durationUntilCancellation = + final Duration durationUntilCancellation = kIntervalBetweenMomentums * heightUntilCancellation; if (plasmaItem.isRevocable!) { diff --git a/lib/widgets/modular_widgets/plasma_widgets/plasma_options/plasma_options.dart b/lib/widgets/modular_widgets/plasma_widgets/plasma_options/plasma_options.dart index ca991821..df5737fa 100644 --- a/lib/widgets/modular_widgets/plasma_widgets/plasma_options/plasma_options.dart +++ b/lib/widgets/modular_widgets/plasma_widgets/plasma_options/plasma_options.dart @@ -19,16 +19,15 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PlasmaOptions extends StatefulWidget { - final List plasmaStatsResults; - final String? errorText; - final PlasmaListBloc plasmaListBloc; const PlasmaOptions({ required this.plasmaListBloc, - this.errorText, - required this.plasmaStatsResults, - Key? key, - }) : super(key: key); + required this.plasmaStatsResults, this.errorText, + super.key, + }); + final List plasmaStatsResults; + final String? errorText; + final PlasmaListBloc plasmaListBloc; @override State createState() { @@ -50,8 +49,8 @@ class _PlasmaOptionsState extends State { BigInt _maxQsrAmount = BigInt.zero; double? _maxWidth; - final double _marginWidth = 20.0; - final double _spaceBetweenExpandedWidgets = 10.0; + final double _marginWidth = 20; + final double _spaceBetweenExpandedWidgets = 10; final int _beneficiaryAddressExpandedFlex = 8; final int _fuseButtonExpandedFlex = 6; @@ -72,12 +71,12 @@ class _PlasmaOptionsState extends State { @override Widget build(BuildContext context) { return Consumer( - builder: (_, __, child) { + builder: (_, __, Widget? child) { _addressController.text = kSelectedAddress!; return child!; }, child: LayoutBuilder( - builder: (_, constraints) { + builder: (_, BoxConstraints constraints) { _maxWidth = constraints.maxWidth; return CardScaffold( title: 'Plasma Options', @@ -96,7 +95,7 @@ class _PlasmaOptionsState extends State { ? SyriusErrorWidget(widget.errorText!) : StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -112,12 +111,12 @@ class _PlasmaOptionsState extends State { ); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); }, @@ -140,15 +139,15 @@ class _PlasmaOptionsState extends State { margin: EdgeInsets.all(_marginWidth), child: Row( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Expanded( flex: _beneficiaryAddressExpandedFlex, child: ListView( shrinkWrap: true, - children: [ + children: [ DisabledAddressField( _addressController, - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), StepperUtils.getBalanceWidget(kQsrCoin, accountInfo!), Form( @@ -158,13 +157,13 @@ class _PlasmaOptionsState extends State { onChanged: (String value) { _beneficiaryAddressString.value = value; }, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[0-9a-z]')), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9a-z]')), ], controller: _beneficiaryAddressController, hintText: 'Beneficiary address', - contentLeftPadding: 20.0, - validator: (value) => InputValidators.checkAddress(value), + contentLeftPadding: 20, + validator: InputValidators.checkAddress, ), ), ], @@ -177,9 +176,9 @@ class _PlasmaOptionsState extends State { flex: _fuseButtonExpandedFlex, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ SizedBox( - height: 87.0, + height: 87, child: Form( key: _qsrAmountKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -193,7 +192,7 @@ class _PlasmaOptionsState extends State { _qsrAmountController.text, ), controller: _qsrAmountController, - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, _maxQsrAmount, kQsrCoin.decimals, @@ -202,7 +201,7 @@ class _PlasmaOptionsState extends State { ), suffixIcon: _getAmountSuffix(), hintText: 'Amount', - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), ), ), @@ -210,19 +209,19 @@ class _PlasmaOptionsState extends State { valueListenable: _beneficiaryAddressString, builder: (_, __, ___) { return Row( - children: [ + children: [ _getGeneratePlasmaButtonStreamBuilder(), Visibility( visible: _isInputValid(), child: Row( - children: [ + children: [ const SizedBox( - width: 10.0, + width: 10, ), _getPlasmaIcon(), ], ), - ) + ), ], ); }, @@ -238,12 +237,12 @@ class _PlasmaOptionsState extends State { PlasmaIcon _getPlasmaIcon() { return PlasmaIcon( PlasmaInfo.fromJson( - { + { 'currentPlasma': ((_qsrAmountController.text.isNotEmpty ? BigInt.parse(zenon!.embedded.plasma .getPlasmaByQsr(_qsrAmountController.text - .extractDecimals(coinDecimals)) - .addDecimals(coinDecimals)) + .extractDecimals(coinDecimals),) + .addDecimals(coinDecimals),) : BigInt.zero) + BigInt.from(_getPlasmaForCurrentBeneficiary())) .toInt(), @@ -258,7 +257,7 @@ class _PlasmaOptionsState extends State { try { return widget.plasmaStatsResults .firstWhere( - (plasmaInfo) => + (PlasmaInfoWrapper plasmaInfo) => plasmaInfo.address == _beneficiaryAddressController.text, ) .plasmaInfo @@ -269,21 +268,21 @@ class _PlasmaOptionsState extends State { } Widget _getGeneratePlasmaButton(PlasmaOptionsBloc model) { - Widget icon = Container( + final Widget icon = Container( decoration: const BoxDecoration( shape: BoxShape.circle, color: AppColors.qsrColor, ), - padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 15.0), + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 15), child: const Icon( MaterialCommunityIcons.lightning_bolt, - size: 15.0, + size: 15, color: Colors.white, ), ); - double widthOfPlasmaIcon = _isInputValid() ? 20.0 : 0.0; - double plasmaIconMargin = _isInputValid() ? 10.0 : 0.0; + final double widthOfPlasmaIcon = _isInputValid() ? 20.0 : 0.0; + final double plasmaIconMargin = _isInputValid() ? 10.0 : 0.0; return LoadingButton.icon( onPressed: _isInputValid() ? () => _onGeneratePlasmaPressed(model) : null, @@ -291,12 +290,12 @@ class _PlasmaOptionsState extends State { outlineColor: AppColors.qsrColor, icon: icon, minimumSize: Size( - ((_maxWidth! - _marginWidth * 2 - _spaceBetweenExpandedWidgets) / + (_maxWidth! - _marginWidth * 2 - _spaceBetweenExpandedWidgets) / (_beneficiaryAddressExpandedFlex + _fuseButtonExpandedFlex) * _fuseButtonExpandedFlex - widthOfPlasmaIcon - - plasmaIconMargin), - 40.0), + plasmaIconMargin, + 40,), key: _fuseButtonKey, ); } @@ -331,9 +330,9 @@ class _PlasmaOptionsState extends State { Widget _getGeneratePlasmaButtonStreamBuilder() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (PlasmaOptionsBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _fuseButtonKey.currentState?.animateReverse(); _qsrAmountKey.currentState?.reset(); @@ -342,7 +341,7 @@ class _PlasmaOptionsState extends State { widget.plasmaListBloc.refreshResults(); } }, - onError: (error) async { + onError: (Object error) async { _fuseButtonKey.currentState?.animateReverse(); await NotificationUtils.sendNotificationError( error, @@ -351,8 +350,8 @@ class _PlasmaOptionsState extends State { }, ); }, - builder: (_, model, __) => _getGeneratePlasmaButton(model), - viewModelBuilder: () => PlasmaOptionsBloc(), + builder: (_, PlasmaOptionsBloc model, __) => _getGeneratePlasmaButton(model), + viewModelBuilder: PlasmaOptionsBloc.new, ); } diff --git a/lib/widgets/modular_widgets/sentinel_widgets/create_sentinel.dart b/lib/widgets/modular_widgets/sentinel_widgets/create_sentinel.dart index 65b759f2..138c9efc 100644 --- a/lib/widgets/modular_widgets/sentinel_widgets/create_sentinel.dart +++ b/lib/widgets/modular_widgets/sentinel_widgets/create_sentinel.dart @@ -8,12 +8,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CreateSentinel extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const CreateSentinel({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _CreateSentinelState(); @@ -36,7 +36,7 @@ class _CreateSentinelState extends State { Widget _getStreamBuilder(BuildContext context) { return StreamBuilder( stream: _getSentinelByOwnerBloc.stream, - builder: (context, snapshot) { + builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -56,7 +56,7 @@ class _CreateSentinelState extends State { return Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( 'Sentinel detected on this address', style: Theme.of(context).textTheme.bodyLarge, @@ -74,14 +74,14 @@ class _CreateSentinelState extends State { Row _getCreateSentinelWidgetBody(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ + children: [ Lottie.asset('assets/lottie/ic_anim_sentinel.json', repeat: false), SyriusElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: const SentinelStepperContainer(), onStepperNotificationSeeMorePressed: widget.onStepperNotificationSeeMorePressed, @@ -94,8 +94,8 @@ class _CreateSentinelState extends State { icon: _getFilledButtonIcon(), ), const SizedBox( - width: 10.0, - ) + width: 10, + ), ], ); } @@ -110,7 +110,7 @@ class _CreateSentinelState extends State { child: const Icon( MaterialCommunityIcons.eye, color: Colors.white, - size: 15.0, + size: 15, ), ); } diff --git a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_collect.dart b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_collect.dart index 19487666..61ba7c18 100644 --- a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_collect.dart +++ b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_collect.dart @@ -11,12 +11,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SentinelCollect extends StatefulWidget { - final SentinelRewardsHistoryBloc sentinelRewardsHistoryBloc; const SentinelCollect({ required this.sentinelRewardsHistoryBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final SentinelRewardsHistoryBloc sentinelRewardsHistoryBloc; @override State createState() => _SentinelCollectState(); @@ -39,7 +39,7 @@ class _SentinelCollectState extends State { 'deployed (use znn-controller for this operation) and it must have >90% ' 'daily uptime', childBuilder: () => Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: _getFutureBuilder(), ), ); @@ -48,7 +48,7 @@ class _SentinelCollectState extends State { Widget _getFutureBuilder() { return StreamBuilder( stream: _sentinelCollectRewardsBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { @@ -66,24 +66,22 @@ class _SentinelCollectState extends State { Widget _getWidgetBody(UncollectedReward uncollectedReward) { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ NumberAnimation( end: uncollectedReward.znnAmount.addDecimals(coinDecimals).toNum(), - isInt: false, after: ' ${kZnnCoin.symbol}', style: Theme.of(context).textTheme.headlineLarge!.copyWith( color: AppColors.znnColor, - fontSize: 30.0, + fontSize: 30, ), ), kVerticalSpacing, NumberAnimation( end: uncollectedReward.qsrAmount.addDecimals(coinDecimals).toNum(), - isInt: false, after: ' ${kQsrCoin.symbol}', style: Theme.of(context).textTheme.headlineLarge!.copyWith( color: AppColors.qsrColor, - fontSize: 30.0, + fontSize: 30, ), ), kVerticalSpacing, @@ -103,7 +101,7 @@ class _SentinelCollectState extends State { ); } - void _onCollectPressed() async { + Future _onCollectPressed() async { try { _collectButtonKey.currentState?.animateForward(); await AccountBlockUtils.createAccountBlock( @@ -111,7 +109,7 @@ class _SentinelCollectState extends State { 'collect Sentinel rewards', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); if (mounted) { _sentinelCollectRewardsBloc.updateStream(); diff --git a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_list_widget.dart b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_list_widget.dart index 58455840..cad4ac95 100644 --- a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_list_widget.dart +++ b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_list_widget.dart @@ -10,7 +10,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SentinelListWidget extends StatefulWidget { - const SentinelListWidget({Key? key}) : super(key: key); + const SentinelListWidget({super.key}); @override State createState() => _SentinelListWidgetState(); @@ -19,7 +19,7 @@ class SentinelListWidget extends StatefulWidget { class _SentinelListWidgetState extends State { late SentinelsListBloc _bloc; - final List _sentinels = []; + final List _sentinels = []; bool _sortAscending = true; @override @@ -40,7 +40,7 @@ class _SentinelListWidgetState extends State { Widget _getTable(SentinelsListBloc bloc) { return InfiniteScrollTable( bloc: _bloc, - headerColumns: [ + headerColumns: [ InfiniteScrollTableHeaderColumn( columnName: 'Sentinel Address', onSortArrowsPressed: _onSortArrowsPressed, @@ -50,11 +50,10 @@ class _SentinelListWidgetState extends State { ), const InfiniteScrollTableHeaderColumn( columnName: '', - onSortArrowsPressed: null, ), ], - generateRowCells: (sentinelInfo, isSelected) { - return [ + generateRowCells: (SentinelInfo sentinelInfo, bool isSelected) { + return [ WidgetUtils.getTextAddressTableCell( sentinelInfo.owner, context, @@ -65,11 +64,9 @@ class _SentinelListWidgetState extends State { InfiniteScrollTableCell( _getSentinelRevokeTimer(sentinelInfo, bloc), ), - isStakeAddressDefault(sentinelInfo) - ? InfiniteScrollTableCell( + if (isStakeAddressDefault(sentinelInfo)) InfiniteScrollTableCell( _getCancelContainer(isSelected, sentinelInfo, bloc), - ) - : const Spacer(), + ) else const Spacer(), ]; }, ); @@ -82,12 +79,10 @@ class _SentinelListWidgetState extends State { return Visibility( visible: isStakeAddressDefault(sentinelInfo), child: Stack( - fit: StackFit.loose, - children: [ + children: [ Row( - children: [ - sentinelInfo.isRevocable - ? CancelTimer( + children: [ + if (sentinelInfo.isRevocable) CancelTimer( Duration( seconds: sentinelInfo.revokeCooldown, ), @@ -95,8 +90,7 @@ class _SentinelListWidgetState extends State { onTimeFinishedCallback: () { model.refreshResults(); }, - ) - : CancelTimer( + ) else CancelTimer( Duration( seconds: sentinelInfo.revokeCooldown, ), @@ -106,7 +100,7 @@ class _SentinelListWidgetState extends State { }, ), const SizedBox( - width: 5.0, + width: 5, ), StandardTooltipIcon( sentinelInfo.isRevocable @@ -136,9 +130,8 @@ class _SentinelListWidgetState extends State { return Visibility( visible: sentinelInfo.isRevocable, child: Stack( - fit: StackFit.loose, alignment: Alignment.center, - children: [ + children: [ _getDisassembleButtonViewModel(isSelected, model, sentinelInfo), ], ), @@ -151,7 +144,7 @@ class _SentinelListWidgetState extends State { SentinelInfo sentinelInfo, ) { return MyOutlinedButton( - minimumSize: const Size(55.0, 25.0), + minimumSize: const Size(55, 25), outlineColor: isSelected ? AppColors.errorColor : Theme.of(context).textTheme.titleSmall!.color, @@ -162,7 +155,7 @@ class _SentinelListWidgetState extends State { : null, child: Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ Text( 'DISASSEMBLE', style: isSelected @@ -172,11 +165,11 @@ class _SentinelListWidgetState extends State { : Theme.of(context).textTheme.titleSmall, ), const SizedBox( - width: 20.0, + width: 20, ), Icon( SimpleLineIcons.close, - size: 11.0, + size: 11, color: isSelected ? AppColors.errorColor : Theme.of(context).textTheme.titleSmall!.color, @@ -190,16 +183,14 @@ class _SentinelListWidgetState extends State { switch (columnName) { case 'Sentinel Owner': _sortAscending - ? _sentinels.sort((a, b) => a.owner.compareTo(b.owner)) - : _sentinels.sort((a, b) => b.owner.compareTo(a.owner)); - break; + ? _sentinels.sort((SentinelInfo a, SentinelInfo b) => a.owner.compareTo(b.owner)) + : _sentinels.sort((SentinelInfo a, SentinelInfo b) => b.owner.compareTo(a.owner)); case 'Registration time': _sortAscending - ? _sentinels.sort((a, b) => - a.registrationTimestamp.compareTo(b.registrationTimestamp)) - : _sentinels.sort((a, b) => - b.registrationTimestamp.compareTo(a.registrationTimestamp)); - break; + ? _sentinels.sort((SentinelInfo a, SentinelInfo b) => + a.registrationTimestamp.compareTo(b.registrationTimestamp),) + : _sentinels.sort((SentinelInfo a, SentinelInfo b) => + b.registrationTimestamp.compareTo(a.registrationTimestamp),); case 'Reward Address': default: break; @@ -216,9 +207,9 @@ class _SentinelListWidgetState extends State { SentinelInfo sentinelInfo, ) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (DisassembleButtonBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { sentinelsModel.refreshResults(); } @@ -231,9 +222,9 @@ class _SentinelListWidgetState extends State { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, DisassembleButtonBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getDisassembleButton(isSelected, model, sentinelInfo); } @@ -241,12 +232,12 @@ class _SentinelListWidgetState extends State { if (snapshot.hasData) { return _getDisassembleButton(isSelected, model, sentinelInfo); } - return const SyriusLoadingWidget(size: 25.0); + return const SyriusLoadingWidget(size: 25); } return _getDisassembleButton(isSelected, model, sentinelInfo); }, ), - viewModelBuilder: () => DisassembleButtonBloc(), + viewModelBuilder: DisassembleButtonBloc.new, ); } } diff --git a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_rewards.dart b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_rewards.dart index 8fe010c6..f7d8cb01 100644 --- a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_rewards.dart +++ b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_rewards.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SentinelRewards extends StatefulWidget { - final SentinelRewardsHistoryBloc sentinelRewardsHistoryBloc; const SentinelRewards({ required this.sentinelRewardsHistoryBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final SentinelRewardsHistoryBloc sentinelRewardsHistoryBloc; @override State createState() { @@ -25,7 +25,7 @@ class _SentinelRewardsState extends State { description: 'This card displays a chart with your Sentinel rewards from ' 'your Sentinel Node', childBuilder: () => Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: _getStreamBody(), ), ); @@ -34,7 +34,7 @@ class _SentinelRewardsState extends State { Widget _getStreamBody() { return StreamBuilder( stream: widget.sentinelRewardsHistoryBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } diff --git a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_stepper_container.dart b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_stepper_container.dart index e183e75c..442592d7 100644 --- a/lib/widgets/modular_widgets/sentinel_widgets/sentinel_stepper_container.dart +++ b/lib/widgets/modular_widgets/sentinel_widgets/sentinel_stepper_container.dart @@ -30,7 +30,7 @@ enum SentinelStepperStep { } class SentinelStepperContainer extends StatefulWidget { - const SentinelStepperContainer({Key? key}) : super(key: key); + const SentinelStepperContainer({super.key}); @override State createState() { @@ -72,7 +72,7 @@ class _MainSentinelState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -92,11 +92,11 @@ class _MainSentinelState extends State { Widget _getQsrManagementStep(BuildContext context, AccountInfo accountInfo) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SentinelsQsrInfoBloc model) { _sentinelsQsrInfoViewModel = model; model.getQsrManagementInfo(_addressController.text); model.stream.listen( - (event) { + (SentinelsQsrInfo? event) { if (event != null) { _maxQsrAmount = MathUtils.bigMin( accountInfo.getBalance( @@ -112,9 +112,9 @@ class _MainSentinelState extends State { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, SentinelsQsrInfoBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return _getQsrManagementStepBody( context, @@ -125,12 +125,12 @@ class _MainSentinelState extends State { return SyriusErrorWidget(snapshot.error!); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); }, ), - viewModelBuilder: () => SentinelsQsrInfoBloc(), + viewModelBuilder: SentinelsQsrInfoBloc.new, ); } @@ -141,14 +141,14 @@ class _MainSentinelState extends State { ) { return Row( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( children: [ Expanded( @@ -157,13 +157,13 @@ class _MainSentinelState extends State { ], ), const SizedBox( - height: 10.0, + height: 10, ), Padding( - padding: const EdgeInsets.only(left: 20.0), + padding: const EdgeInsets.only(left: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ AvailableBalance( kQsrCoin, accountInfo, @@ -177,10 +177,10 @@ class _MainSentinelState extends State { ), ), const SizedBox( - height: 10.0, + height: 10, ), Row( - children: [ + children: [ Expanded( child: Form( key: _qsrFormKey, @@ -191,7 +191,7 @@ class _MainSentinelState extends State { _qsrAmountController.text, ), controller: _qsrAmountController, - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, _maxQsrAmount, kQsrCoin.decimals, @@ -199,9 +199,9 @@ class _MainSentinelState extends State { ), suffixIcon: _getAmountSuffix(accountInfo), suffixIconConstraints: - const BoxConstraints(maxWidth: 50.0), + const BoxConstraints(maxWidth: 50), hintText: 'Amount', - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, ), @@ -210,7 +210,7 @@ class _MainSentinelState extends State { ], ), Padding( - padding: const EdgeInsets.symmetric(vertical: 25.0), + padding: const EdgeInsets.symmetric(vertical: 25), child: DottedBorderInfoWidget( text: 'You will be able to unlock the ${kQsrCoin.symbol} if you ' @@ -221,7 +221,7 @@ class _MainSentinelState extends State { ], ), Row( - children: [ + children: [ Visibility( visible: qsrInfo.deposit < qsrInfo.cost, child: _getDepositQsrViewModel(accountInfo, qsrInfo), @@ -234,44 +234,44 @@ class _MainSentinelState extends State { ), ), ], - ) + ), ], ), ), const SizedBox( - width: 45.0, + width: 45, ), Expanded( child: Visibility( visible: qsrInfo.deposit > BigInt.zero, child: Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(6), ), margin: const EdgeInsets.only( - bottom: 30.0, + bottom: 30, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 30.0), + padding: const EdgeInsets.symmetric(vertical: 30), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ Column( - children: [ + children: [ Stack( alignment: Alignment.center, - children: [ + children: [ SizedBox( - width: 150.0, - height: 150.0, + width: 150, + height: 150, child: AspectRatio( - aspectRatio: 1.0, + aspectRatio: 1, child: StandardPieChart( - sections: [ + sections: [ PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, value: (qsrInfo.cost - qsrInfo.deposit) / qsrInfo.cost, color: @@ -279,7 +279,7 @@ class _MainSentinelState extends State { ), PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, value: qsrInfo.deposit / qsrInfo.cost, color: AppColors.qsrColor, ), @@ -298,9 +298,9 @@ class _MainSentinelState extends State { ], ), Column( - children: [ + children: [ SizedBox( - width: 130.0, + width: 130, child: Text( 'You have deposited ${qsrInfo.deposit.addDecimals(coinDecimals)} ' '${kQsrCoin.symbol}', @@ -325,11 +325,11 @@ class _MainSentinelState extends State { } Widget _getDepositQsrViewModel( - AccountInfo accountInfo, SentinelsQsrInfo qsrInfo) { + AccountInfo accountInfo, SentinelsQsrInfo qsrInfo,) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SentinelsDepositQsrBloc model) { model.stream.listen( - (response) { + (AccountBlockTemplate? response) { if (response != null) { _depositQsrButtonKey.currentState?.animateReverse(); _sentinelsQsrInfoViewModel.getQsrManagementInfo( @@ -350,9 +350,9 @@ class _MainSentinelState extends State { }, ); }, - builder: (_, model, __) => + builder: (_, SentinelsDepositQsrBloc model, __) => _getDepositQsrButton(model, accountInfo, qsrInfo), - viewModelBuilder: () => SentinelsDepositQsrBloc(), + viewModelBuilder: SentinelsDepositQsrBloc.new, ); } @@ -374,9 +374,9 @@ class _MainSentinelState extends State { Widget _getWithdrawQsrButtonViewModel(BigInt qsrDeposit) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SentinelsWithdrawQsrBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _withdrawButtonKey.currentState?.animateReverse(); _saveProgressAndNavigateToNextStep( @@ -396,8 +396,8 @@ class _MainSentinelState extends State { }, ); }, - builder: (_, model, __) => _getWithdrawQsrButton(model, qsrDeposit), - viewModelBuilder: () => SentinelsWithdrawQsrBloc(), + builder: (_, SentinelsWithdrawQsrBloc model, __) => _getWithdrawQsrButton(model, qsrDeposit), + viewModelBuilder: SentinelsWithdrawQsrBloc.new, ); } @@ -426,7 +426,7 @@ class _MainSentinelState extends State { child: custom_material_stepper.Stepper( currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Sentinel deployment: Plasma check', stepContent: _getPlasmaCheckFutureBuilder(), @@ -483,10 +483,10 @@ class _MainSentinelState extends State { Widget _getDeploySentinelStepBody(BuildContext context) { return Padding( padding: const EdgeInsets.only( - bottom: 25.0, + bottom: 25, ), child: Row( - children: [ + children: [ _getDeployButtonViewModel(), ], ), @@ -495,13 +495,13 @@ class _MainSentinelState extends State { Widget _getDeployButtonViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SentinelsDeployBloc model) { model.stream.listen( - (response) { + (AccountBlockTemplate? response) { if (response != null) { _registerButtonKey.currentState?.animateReverse(); _saveProgressAndNavigateToNextStep( - SentinelStepperStep.deploySentinel); + SentinelStepperStep.deploySentinel,); setState(() {}); } else { setState(() {}); @@ -517,8 +517,8 @@ class _MainSentinelState extends State { }, ); }, - builder: (_, model, __) => _getRegisterSentinelButton(model), - viewModelBuilder: () => SentinelsDeployBloc(), + builder: (_, SentinelsDeployBloc model, __) => _getRegisterSentinelButton(model), + viewModelBuilder: SentinelsDeployBloc.new, ); } @@ -536,9 +536,8 @@ class _MainSentinelState extends State { ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), @@ -549,7 +548,7 @@ class _MainSentinelState extends State { StepperUtils.getBalanceWidget(kZnnCoin, accountInfo), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -560,11 +559,10 @@ class _MainSentinelState extends State { ], ), Padding( - padding: const EdgeInsets.symmetric(vertical: 25.0), + padding: const EdgeInsets.symmetric(vertical: 25), child: DottedBorderInfoWidget( text: 'You will be able to unlock the ${kZnnCoin.symbol} if you ' 'choose to disassemble the Sentinel', - borderColor: AppColors.znnColor, ), ), StepperButton( @@ -576,7 +574,7 @@ class _MainSentinelState extends State { } void _onDepositButtonPressed( - SentinelsDepositQsrBloc model, SentinelsQsrInfo qsrInfo) { + SentinelsDepositQsrBloc model, SentinelsQsrInfo qsrInfo,) { if (qsrInfo.deposit >= qsrInfo.cost) { _depositQsrButtonKey.currentState?.animateForward(); model.depositQsr( @@ -609,7 +607,7 @@ class _MainSentinelState extends State { if (_lastCompletedStep == SentinelStepperStep.znnManagement) { _registerButtonKey.currentState?.animateForward(); model.deploySentinel( - _znnAmountController.text.extractDecimals(coinDecimals)); + _znnAmountController.text.extractDecimals(coinDecimals),); } } @@ -625,30 +623,29 @@ class _MainSentinelState extends State { Widget _getWidgetBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), Visibility( visible: _lastCompletedStep == SentinelStepperStep.deploySentinel, child: Column( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Container( padding: const EdgeInsets.symmetric( - vertical: 40.0, - horizontal: 50.0, + vertical: 40, + horizontal: 50, ), margin: const EdgeInsets.symmetric( - vertical: 20.0, - horizontal: 50.0, + vertical: 20, + horizontal: 50, ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondaryContainer, borderRadius: const BorderRadius.all( Radius.circular( - 10.0, + 10, ), ), ), @@ -656,7 +653,7 @@ class _MainSentinelState extends State { textAlign: TextAlign.center, text: TextSpan( style: Theme.of(context).textTheme.headlineSmall, - children: [ + children: [ TextSpan( text: 'Sentinel ', style: Theme.of(context).textTheme.headlineSmall, @@ -691,7 +688,7 @@ class _MainSentinelState extends State { const WidgetSpan( child: Icon( MaterialCommunityIcons.link, - size: 20.0, + size: 20, color: AppColors.znnColor, ), ), @@ -705,11 +702,11 @@ class _MainSentinelState extends State { ), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ _getViewSentinelsButton(), ], ), - Container(height: 20.0) + Container(height: 20), ], ), ), @@ -718,10 +715,10 @@ class _MainSentinelState extends State { Visibility( visible: _lastCompletedStep == SentinelStepperStep.deploySentinel, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_sentinel.json', @@ -737,7 +734,6 @@ class _MainSentinelState extends State { Widget _getViewSentinelsButton() { return StepperButton.icon( - context: context, label: 'View Sentinels', onPressed: () { Navigator.pop(context); @@ -783,14 +779,14 @@ class _MainSentinelState extends State { Widget _getPlasmaCheckFutureBuilder() { return FutureBuilder( future: zenon!.embedded.plasma.get(Address.parse(kSelectedAddress!)), - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { return _getPlasmaCheckBody(snapshot.data!); } return const Padding( - padding: EdgeInsets.all(8.0), + padding: EdgeInsets.all(8), child: SyriusLoadingWidget(), ); }, @@ -800,28 +796,27 @@ class _MainSentinelState extends State { Widget _getPlasmaCheckBody(PlasmaInfo plasmaInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'More Plasma is required to perform complex transactions. Please fuse enough QSR before proceeding.', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( - height: 25.0, + height: 25, ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), ), const SizedBox( - width: 25.0, + width: 25, ), PlasmaIcon(plasmaInfo), ], ), const SizedBox( - height: 25.0, + height: 25, ), StepperButton( text: 'Next', diff --git a/lib/widgets/modular_widgets/settings_widgets/account_chain_stats.dart b/lib/widgets/modular_widgets/settings_widgets/account_chain_stats.dart index 3ca4fdcf..ccf7e0a4 100644 --- a/lib/widgets/modular_widgets/settings_widgets/account_chain_stats.dart +++ b/lib/widgets/modular_widgets/settings_widgets/account_chain_stats.dart @@ -13,12 +13,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AccountChainStatsWidget extends StatefulWidget { - final AccountChainStatsBloc accountChainStatsBloc; const AccountChainStatsWidget({ required this.accountChainStatsBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final AccountChainStatsBloc accountChainStatsBloc; @override State createState() { @@ -33,7 +33,7 @@ class _AccountChainStatsState extends State { title: 'Account-chain Stats', description: 'This card displays information regarding the account-chain ' 'for the specified address', - childBuilder: () => _getStreamBuilder(), + childBuilder: _getStreamBuilder, ); } @@ -43,7 +43,7 @@ class _AccountChainStatsState extends State { shrinkWrap: true, children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 12.0), + padding: const EdgeInsets.symmetric(vertical: 12), child: Column( children: [ Text( @@ -52,7 +52,7 @@ class _AccountChainStatsState extends State { ), Stack( alignment: Alignment.center, - children: [ + children: [ NumberAnimation( end: stats.blockCount, isInt: true, @@ -64,8 +64,8 @@ class _AccountChainStatsState extends State { _getChartLegend(stats), RawMaterialButton( constraints: const BoxConstraints( - minWidth: 40.0, - minHeight: 40.0, + minWidth: 40, + minHeight: 40, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () => NavigationUtils.openUrl( @@ -78,23 +78,23 @@ class _AccountChainStatsState extends State { 'Block hash', style: Theme.of(context).textTheme.bodyMedium, ), - Container(width: 10.0), + Container(width: 10), const Icon( MaterialCommunityIcons.compass, - size: 20.0, + size: 20, color: AppColors.qsrColor, ), ], ), ), Row( - children: [ + children: [ Expanded( child: Container( padding: const EdgeInsets.only( - top: 12.0, - right: 22.0, - left: 22.0, + top: 12, + right: 22, + left: 22, ), child: Marquee( child: Text( @@ -103,7 +103,7 @@ class _AccountChainStatsState extends State { ), ), ), - ) + ), ], ), ], @@ -116,10 +116,10 @@ class _AccountChainStatsState extends State { Container _getChart(AccountChainStats stats) { return Container( - width: 150.0, - height: 150.0, + width: 150, + height: 150, margin: const EdgeInsets.all( - 10.0, + 10, ), child: StandardPieChart( sections: _getChartSections(stats), @@ -131,11 +131,11 @@ class _AccountChainStatsState extends State { AccountChainStats stats, BlockTypeEnum blockType, ) { - int blockTypeCount = stats.blockTypeNumOfBlocksMap[blockType]!; + final int blockTypeCount = stats.blockTypeNumOfBlocksMap[blockType]!; return PieChartSectionData( showTitle: false, - radius: 7.0, + radius: 7, color: kBlockTypeColorMap[blockType] ?? AppColors.errorColor, value: 100.0 * blockTypeCount / stats.blockCount, ); @@ -144,7 +144,7 @@ class _AccountChainStatsState extends State { Widget _getStreamBuilder() { return StreamBuilder( stream: widget.accountChainStatsBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -162,7 +162,7 @@ class _AccountChainStatsState extends State { List _getChartSections(AccountChainStats stats) => List.generate( BlockTypeEnum.values.length, - (index) => _getChartSection( + (int index) => _getChartSection( stats, BlockTypeEnum.values.elementAt(index), ), @@ -174,12 +174,12 @@ class _AccountChainStatsState extends State { ) { return Container( margin: const EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 4.0, + horizontal: 20, + vertical: 4, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( '● ', style: Theme.of(context).textTheme.bodyMedium!.copyWith( @@ -191,7 +191,7 @@ class _AccountChainStatsState extends State { style: Theme.of(context).textTheme.bodyMedium, ), const SizedBox( - width: 10.0, + width: 10, ), AutoSizeText( blockTypeCount.toString(), @@ -203,14 +203,14 @@ class _AccountChainStatsState extends State { } Widget _getChartLegend(AccountChainStats stats) { - List typesWithBlocks = stats.blockTypeNumOfBlocksMap.keys - .where((key) => stats.blockTypeNumOfBlocksMap[key]! > 0) + final List typesWithBlocks = stats.blockTypeNumOfBlocksMap.keys + .where((BlockTypeEnum key) => stats.blockTypeNumOfBlocksMap[key]! > 0) .toList(); return ListView.builder( shrinkWrap: true, itemCount: typesWithBlocks.length, - itemBuilder: (context, index) => _getBlockTypeCountDetails( + itemBuilder: (BuildContext context, int index) => _getBlockTypeCountDetails( typesWithBlocks[index], stats.blockTypeNumOfBlocksMap[typesWithBlocks[index]], ), diff --git a/lib/widgets/modular_widgets/settings_widgets/addresses.dart b/lib/widgets/modular_widgets/settings_widgets/addresses.dart index eacabb3e..f1a54d95 100644 --- a/lib/widgets/modular_widgets/settings_widgets/addresses.dart +++ b/lib/widgets/modular_widgets/settings_widgets/addresses.dart @@ -14,12 +14,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/notifiers/plasma_beneficiary_a import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class Addresses extends StatefulWidget { - final AccountChainStatsBloc accountChainStatsBloc; const Addresses({ required this.accountChainStatsBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final AccountChainStatsBloc accountChainStatsBloc; @override State createState() { @@ -51,13 +51,13 @@ class AddressesState extends State { title: 'Addresses', description: 'Select the default address that will be used throughout ' 'the wallet for any network operation', - childBuilder: () => _getGenerateNewAddressFutureBuilder(), + childBuilder: _getGenerateNewAddressFutureBuilder, ); } Future _changeDefaultAddress(String? newDefaultAddress) async { try { - Box box = Hive.box(kSharedPrefsBox); + final Box box = Hive.box(kSharedPrefsBox); await box.put(kDefaultAddressKey, newDefaultAddress); if (!mounted) return; Provider.of( @@ -77,23 +77,21 @@ class AddressesState extends State { Widget _getAddAddressWidget() { return Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ Expanded( - flex: 1, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 20.0), + padding: const EdgeInsets.symmetric(horizontal: 20), child: NumberSelector.plain( borderColor: AppColors.znnColor, iconColor: AppColors.znnColor, dividerColor: AppColors.znnColor, - step: 1, current: 1, min: 1, max: 10, - onUpdate: (val) { + onUpdate: (int val) { _onAddAddressPressedCallback(val); }, ), @@ -109,21 +107,21 @@ class AddressesState extends State { setState(() { _shouldScrollToTheEnd = true; }); - }); + },); }); }, child: Container( constraints: - const BoxConstraints(minWidth: 150.0, minHeight: 50.0), + const BoxConstraints(minWidth: 150, minHeight: 50), alignment: Alignment.center, child: Row( - children: [ + children: [ const Icon( Icons.add_circle, color: AppColors.znnColor, - size: 20.0, + size: 20, ), - const SizedBox(width: 10.0), + const SizedBox(width: 10), Text( (numberOfAddressesToAdd == 1) ? 'Add $numberOfAddressesToAdd address ' @@ -131,19 +129,19 @@ class AddressesState extends State { style: Theme.of(context).textTheme.bodyLarge, ), ], - )), + ),), ), - const SizedBox(width: 10.0), + const SizedBox(width: 10), ], ), ); } Widget _getAddresses() { - List addresses = kDefaultAddressList + final List addresses = kDefaultAddressList .map( - (e) => Row( - children: [ + (String? e) => Row( + children: [ Radio( value: e, groupValue: _selectedAddress, @@ -160,12 +158,12 @@ class AddressesState extends State { ) .toList(); - Widget listView = ListView.builder( + final Widget listView = ListView.builder( controller: _scrollController, key: const PageStorageKey('Addresses list view'), shrinkWrap: true, itemCount: addresses.length, - itemBuilder: (context, index) { + itemBuilder: (BuildContext context, int index) { return addresses[index]; }, ); @@ -191,7 +189,7 @@ class AddressesState extends State { Widget _getCardBody() { return Column( - children: [ + children: [ Expanded( child: _getAddresses(), ), @@ -204,10 +202,10 @@ class AddressesState extends State { Widget _getGenerateNewAddressFutureBuilder() { return FutureBuilder( future: _futureGenerateNewAddress, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); - } else if ([ + } else if ([ ConnectionState.none, ConnectionState.done, ].contains(snapshot.connectionState)) { @@ -221,10 +219,10 @@ class AddressesState extends State { Widget _getChangeDefaultAddressFutureBuilder() { return FutureBuilder( future: _futureChangeDefaultAddress, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); - } else if ([ + } else if ([ ConnectionState.none, ConnectionState.done, ].contains(snapshot.connectionState)) { diff --git a/lib/widgets/modular_widgets/settings_widgets/backup.dart b/lib/widgets/modular_widgets/settings_widgets/backup.dart index 2055e3ab..0eb4dd7b 100644 --- a/lib/widgets/modular_widgets/settings_widgets/backup.dart +++ b/lib/widgets/modular_widgets/settings_widgets/backup.dart @@ -6,7 +6,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class BackupWidget extends StatefulWidget { - const BackupWidget({Key? key}) : super(key: key); + const BackupWidget({super.key}); @override State createState() => _BackupWidgetState(); @@ -45,16 +45,16 @@ class _BackupWidgetState extends State { ); } - void _onBackupWalletPressed() async { + Future _onBackupWalletPressed() async { kWalletFile! - .access((wallet) => Future.value((wallet as KeyStore).mnemonic!)) - .then((value) => NavigationUtils.push( + .access((Wallet wallet) => Future.value((wallet as KeyStore).mnemonic!)) + .then((String value) => NavigationUtils.push( context, ExportWalletInfoScreen( value, backupWalletFlow: true, ), - )); + ),); } Widget _getDumpMnemonicButton() { diff --git a/lib/widgets/modular_widgets/settings_widgets/display.dart b/lib/widgets/modular_widgets/settings_widgets/display.dart index b22dfd10..937c57d8 100644 --- a/lib/widgets/modular_widgets/settings_widgets/display.dart +++ b/lib/widgets/modular_widgets/settings_widgets/display.dart @@ -23,7 +23,7 @@ enum LocaleType { } class DisplayWidget extends StatefulWidget { - const DisplayWidget({Key? key}) : super(key: key); + const DisplayWidget({super.key}); @override State createState() => _DisplayWidget(); @@ -40,24 +40,24 @@ class _DisplayWidget extends State { return CardScaffold( title: 'Display', description: 'Wallet appearance and theme settings', - childBuilder: () => _getWidgetBody(), + childBuilder: _getWidgetBody, ); } Widget _getWidgetBody() { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel('Text scaling', _getTextScalingExpandableChild()), CustomExpandablePanel('Locale', _getLocaleExpandableChild()), - CustomExpandablePanel('Theme', _getThemeExpandableChild()) + CustomExpandablePanel('Theme', _getThemeExpandableChild()), ], ); } Widget _getTextScalingExpandableChild() { return Column( - children: [ + children: [ _getTextScalingTiles(), _getConfirmScaleButton(), ], @@ -69,7 +69,7 @@ class _DisplayWidget extends State { crossAxisAlignment: CrossAxisAlignment.start, children: TextScaling.values .map( - (e) => _getListTile( + (TextScaling e) => _getListTile( FormatUtils.extractNameFromEnum(e), e, ), @@ -80,7 +80,7 @@ class _DisplayWidget extends State { Widget _getListTile(String text, T value) { return Row( - children: [ + children: [ Radio( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: value, @@ -88,7 +88,7 @@ class _DisplayWidget extends State { ? Provider.of( context, listen: false, - ).currentTextScaling + ).currentTextScaling as T : value is LocaleType ? _selectedLocaleType as T? : Provider.of( @@ -117,7 +117,7 @@ class _DisplayWidget extends State { child: Text( text, style: Theme.of(context).textTheme.bodyLarge!.copyWith( - fontSize: 10.0, + fontSize: 10, ), ), ), @@ -130,7 +130,7 @@ class _DisplayWidget extends State { crossAxisAlignment: CrossAxisAlignment.start, children: LocaleType.values .map( - (e) => _getListTile( + (LocaleType e) => _getListTile( FormatUtils.extractNameFromEnum(e), e, ), @@ -141,7 +141,7 @@ class _DisplayWidget extends State { Widget _getThemeExpandableChild() { return Column( - children: [ + children: [ _getThemeModeTiles(), _getConfirmThemeButton(), ], @@ -153,7 +153,7 @@ class _DisplayWidget extends State { crossAxisAlignment: CrossAxisAlignment.start, children: ThemeMode.values .map( - (e) => _getListTile( + (ThemeMode e) => _getListTile( FormatUtils.extractNameFromEnum(e), e, ), @@ -165,9 +165,9 @@ class _DisplayWidget extends State { Widget _getConfirmThemeButton() { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: LoadingButton.settings( text: 'Confirm theme', onPressed: _onConfirmThemeButtonPressed, @@ -181,7 +181,7 @@ class _DisplayWidget extends State { Future _onConfirmThemeButtonPressed() async { try { _confirmThemeButtonKey.currentState!.animateForward(); - ThemeMode? currentThemeMode = Provider.of( + final ThemeMode? currentThemeMode = Provider.of( context, listen: false, ).currentThemeMode; @@ -213,9 +213,9 @@ class _DisplayWidget extends State { Widget _getConfirmScaleButton() { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: LoadingButton.settings( text: 'Confirm scale', onPressed: _onConfirmScaleButtonPressed, @@ -226,11 +226,11 @@ class _DisplayWidget extends State { ); } - void _onConfirmScaleButtonPressed() async { + Future _onConfirmScaleButtonPressed() async { try { _confirmScaleButtonKey.currentState!.animateForward(); - TextScaling? currentTextScaling = Provider.of( + final TextScaling? currentTextScaling = Provider.of( context, listen: false, ).currentTextScaling; @@ -246,7 +246,7 @@ class _DisplayWidget extends State { timestamp: DateTime.now().millisecondsSinceEpoch, details: 'Text scale successfully changed to ' '${FormatUtils.extractNameFromEnum(currentTextScaling)}', - type: NotificationType.paymentSent), + type: NotificationType.paymentSent,), ); } catch (e) { await NotificationUtils.sendNotificationError(e, 'Text scale change failed'); diff --git a/lib/widgets/modular_widgets/settings_widgets/general.dart b/lib/widgets/modular_widgets/settings_widgets/general.dart index 3f3cd382..26b6671d 100644 --- a/lib/widgets/modular_widgets/settings_widgets/general.dart +++ b/lib/widgets/modular_widgets/settings_widgets/general.dart @@ -9,7 +9,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/navigation_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class GeneralWidget extends StatefulWidget { - const GeneralWidget({Key? key}) : super(key: key); + const GeneralWidget({super.key}); @override State createState() { @@ -31,7 +31,7 @@ class GeneralWidgetState extends State { return CardScaffold( title: 'General', description: 'Generic wallet & network information', - childBuilder: () => _getStreamBuilder(), + childBuilder: _getStreamBuilder, ); } @@ -46,15 +46,15 @@ class GeneralWidgetState extends State { 'Momentum height', style: Theme.of(context).textTheme.titleMedium, ), - Container(height: 10.0), + Container(height: 10), Container( - width: 150.0, - height: 150.0, + width: 150, + height: 150, decoration: const ShapeDecoration( color: Colors.transparent, shape: CircleBorder( side: BorderSide( - width: 6.0, + width: 6, color: AppColors.znnColor, ), ), @@ -67,62 +67,56 @@ class GeneralWidgetState extends State { ), ), ), - Container(height: 10.0), + Container(height: 10), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - (generalStats.networkInfo.peers.isNotEmpty) - ? const Icon( + if (generalStats.networkInfo.peers.isNotEmpty) const Icon( MaterialCommunityIcons.lan_connect, - size: 15.0, + size: 15, color: AppColors.znnColor, - ) - : const Icon( + ) else const Icon( MaterialCommunityIcons.lan_disconnect, - size: 15.0, + size: 15, color: AppColors.errorColor, ), const SizedBox( - width: 4.0, + width: 4, ), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ - (generalStats.networkInfo.peers.isNotEmpty) - ? Text( + children: [ + if (generalStats.networkInfo.peers.isNotEmpty) Text( 'Peers connected', style: Theme.of(context).textTheme.bodyMedium, - ) - : const Text('Peers available'), + ) else const Text('Peers available'), const SizedBox( - width: 10.0, + width: 10, ), - (generalStats.networkInfo.peers.isNotEmpty) - ? Text( + if (generalStats.networkInfo.peers.isNotEmpty) Text( '${generalStats.networkInfo.peers.length}', style: Theme.of(context).textTheme.titleMedium, - ) - : Text( + ) else Text( 'No peers found', style: Theme.of(context).textTheme.bodyMedium, ), ], - ) + ), ], ), const SizedBox( - height: 10.0, + height: 10, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( MaterialCommunityIcons.timer, - size: 15.0, + size: 15, color: AppColors.qsrColor, ), const SizedBox( - width: 4.0, + width: 4, ), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -133,7 +127,7 @@ class GeneralWidgetState extends State { ), ], ), - const SizedBox(width: 10.0), + const SizedBox(width: 10), Text( '${generalStats.frontierMomentum.timestamp}', style: Theme.of(context).textTheme.titleMedium, @@ -145,7 +139,7 @@ class GeneralWidgetState extends State { ), RawMaterialButton( constraints: const BoxConstraints( - minHeight: 40.0, + minHeight: 40, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () => NavigationUtils.openUrl( @@ -158,23 +152,23 @@ class GeneralWidgetState extends State { 'Momentum hash', style: Theme.of(context).textTheme.bodyMedium, ), - Container(width: 10.0), + Container(width: 10), const Icon( MaterialCommunityIcons.compass, - size: 20.0, + size: 20, color: AppColors.znnColor, ), ], ), ), Row( - children: [ + children: [ Expanded( child: Container( padding: const EdgeInsets.only( - top: 12.0, - right: 22.0, - left: 22.0, + top: 12, + right: 22, + left: 22, ), child: Marquee( child: Text( @@ -183,9 +177,9 @@ class GeneralWidgetState extends State { ), ), ), - ) + ), ], - ) + ), ], ), ], @@ -196,7 +190,7 @@ class GeneralWidgetState extends State { Widget _getStreamBuilder() { return StreamBuilder( stream: _generalStatsBloc!.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return _getNewBody(snapshot.data!); } else if (snapshot.hasError) { diff --git a/lib/widgets/modular_widgets/settings_widgets/node_management.dart b/lib/widgets/modular_widgets/settings_widgets/node_management.dart index 489f3684..d5239314 100644 --- a/lib/widgets/modular_widgets/settings_widgets/node_management.dart +++ b/lib/widgets/modular_widgets/settings_widgets/node_management.dart @@ -15,12 +15,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class NodeManagement extends StatefulWidget { - final VoidCallback onNodeChangedCallback; const NodeManagement({ required this.onNodeChangedCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onNodeChangedCallback; @override State createState() => _NodeManagementState(); @@ -73,14 +73,14 @@ class _NodeManagementState extends State { 'This card allows one to set the ZNN Node used to connect to. ' 'By default the wallet is connected to the Embedded Node. ' 'If you are running a local ZNN Node, please use the localhost option', - childBuilder: () => _getWidgetBody(), + childBuilder: _getWidgetBody, ); } Widget _getWidgetBody() { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel( 'Client chain identifier selection', _getChainIdSelectionExpandableChild(), @@ -99,17 +99,17 @@ class _NodeManagementState extends State { Widget _getNodeSelectionExpandableChild() { return Column( - children: [ + children: [ _getNodeTiles(), _getConfirmNodeSelectionButton(), ], ); } - _getConfirmNodeSelectionButton() { + Row _getConfirmNodeSelectionButton() { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ LoadingButton.settings( text: 'Confirm node', onPressed: _onConfirmNodeButtonPressed, @@ -127,7 +127,7 @@ class _NodeManagementState extends State { try { _confirmNodeButtonKey.currentState?.animateForward(); - var isConnectionEstablished = + final bool isConnectionEstablished = await _establishConnectionToNode(_selectedNode); if (isConnectionEstablished) { kNodeChainId = await NodeUtils.getNodeChainIdentifier(); @@ -137,14 +137,14 @@ class _NodeManagementState extends State { kSelectedNodeKey, _selectedNode, ); - kCurrentNode = _selectedNode!; + kCurrentNode = _selectedNode; await _sendChangingNodeSuccessNotification(); widget.onNodeChangedCallback(); } else { await _establishConnectionToNode(kCurrentNode); kNodeChainId = await NodeUtils.getNodeChainIdentifier(); setState(() { - _selectedNode = kCurrentNode!; + _selectedNode = kCurrentNode; }); } } else { @@ -156,7 +156,7 @@ class _NodeManagementState extends State { 'Connection failed', ); setState(() { - _selectedNode = kCurrentNode!; + _selectedNode = kCurrentNode; }); } finally { _confirmNodeButtonKey.currentState?.animateReverse(); @@ -164,16 +164,16 @@ class _NodeManagementState extends State { } Future _establishConnectionToNode(String? url) async { - String targetUrl = url == kEmbeddedNode ? kLocalhostDefaultNodeUrl : url!; + final String targetUrl = url == kEmbeddedNode ? kLocalhostDefaultNodeUrl : url!; bool isConnectionEstablished = await NodeUtils.establishConnectionToNode(targetUrl); if (url == kEmbeddedNode) { // Check if node is already running if (!isConnectionEstablished) { // Initialize local full node - await Isolate.spawn(EmbeddedNode.runNode, [''], + await Isolate.spawn(EmbeddedNode.runNode, [''], onExit: - sl(instanceName: 'embeddedStoppedPort').sendPort); + sl(instanceName: 'embeddedStoppedPort').sendPort,); kEmbeddedNodeRunning = true; // The node needs a couple of seconds to actually start await Future.delayed(kEmbeddedConnectionDelay); @@ -192,14 +192,14 @@ class _NodeManagementState extends State { Widget _getAddNodeExpandableChild() { return Column( - children: [ + children: [ Form( key: _newNodeKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( controller: _newNodeController, hintText: 'Node address with port', - onSubmitted: (value) { + onSubmitted: (String value) { if (_ifUserInputValid()) { _onAddNodePressed(); } @@ -226,11 +226,11 @@ class _NodeManagementState extends State { InputValidators.node(_newNodeController.text) == null; Future _onAddNodePressed() async { - if ([...kDbNodes, ...kDefaultCommunityNodes, ...kDefaultNodes] + if ([...kDbNodes, ...kDefaultCommunityNodes, ...kDefaultNodes] .contains(_newNodeController.text)) { await NotificationUtils.sendNotificationError( 'Node ${_newNodeController.text} already exists', - 'Node already exists'); + 'Node already exists',); } else { _addNodeToDb(); } @@ -259,18 +259,18 @@ class _NodeManagementState extends State { children: { ...kDefaultNodes, ...kDefaultCommunityNodes, - ...kDbNodes - }.toList().map((e) => _getNodeTile(e)).toList(), + ...kDbNodes, + }.toList().map(_getNodeTile).toList(), ); } Row _getNodeTile(String node) { return Row( - children: [ + children: [ Radio( value: node, groupValue: _selectedNode, - onChanged: (value) { + onChanged: (String? value) { setState(() { _selectedNode = value; }); @@ -280,7 +280,7 @@ class _NodeManagementState extends State { child: SettingsNode( key: ValueKey(node), node: node, - onNodePressed: (value) { + onNodePressed: (String? value) { setState(() { _selectedNode = value; }); @@ -326,22 +326,21 @@ class _NodeManagementState extends State { Widget _getChainIdSelectionExpandableChild() { return Column( - children: [ + children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ Expanded( child: Form( key: _newChainIdKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - inputFormatters: [ + inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], controller: _newChainIdController, hintText: - 'Current client chain identifier is ${getChainIdentifier().toString()}', - onSubmitted: (value) async { + 'Current client chain identifier is ${getChainIdentifier()}', + onSubmitted: (String value) async { if (_isChainIdSelectionInputIsValid()) { _onConfirmChainIdPressed(); } @@ -353,7 +352,7 @@ class _NodeManagementState extends State { }, validator: InputValidators.validateNumber, ), - )), + ),), StandardTooltipIcon( (getChainIdentifier() == 1) ? 'Alphanet chain identifier' @@ -421,8 +420,8 @@ class _NodeManagementState extends State { Future _checkForChainIdMismatch() async { bool match = false; - await zenon!.ledger.getFrontierMomentum().then((momentum) async { - int nodeChainId = momentum.chainIdentifier; + await zenon!.ledger.getFrontierMomentum().then((Momentum momentum) async { + final int nodeChainId = momentum.chainIdentifier; if (nodeChainId != _currentChainId) { match = await _showChainIdWarningDialog(nodeChainId, _currentChainId); } else { @@ -433,8 +432,8 @@ class _NodeManagementState extends State { } Future _showChainIdWarningDialog( - int nodeChainId, int currentChainId) async { - return await showWarningDialog( + int nodeChainId, int currentChainId,) async { + return showWarningDialog( context: context, title: 'Chain identifier mismatch', buttonText: 'Proceed anyway', diff --git a/lib/widgets/modular_widgets/settings_widgets/peers.dart b/lib/widgets/modular_widgets/settings_widgets/peers.dart index 87284fb7..a607d9ab 100644 --- a/lib/widgets/modular_widgets/settings_widgets/peers.dart +++ b/lib/widgets/modular_widgets/settings_widgets/peers.dart @@ -4,7 +4,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PeersWidget extends StatefulWidget { - const PeersWidget({Key? key}) : super(key: key); + const PeersWidget({super.key}); @override State createState() => _PeersWidget(); @@ -29,14 +29,14 @@ class _PeersWidget extends State { title: 'Peers', description: 'This card displays information about connected network peers', - childBuilder: () => _getStreamBuilder(), + childBuilder: _getStreamBuilder, ); } Widget _getTable() { return CustomTable( items: _peers, - headerColumns: [ + headerColumns: [ CustomHeaderColumn( columnName: 'IP', onSortArrowsPressed: _onSortArrowsPressed, @@ -48,8 +48,8 @@ class _PeersWidget extends State { contentAlign: MainAxisAlignment.center, ), ], - generateRowCells: (peer, isSelected, {SentinelsListBloc? model}) { - return [ + generateRowCells: (Peer peer, bool isSelected, {SentinelsListBloc? model}) { + return [ CustomTableCell.withText(context, peer.ip), CustomTableCell.withMarquee( peer.publicKey, @@ -63,7 +63,7 @@ class _PeersWidget extends State { Widget _getStreamBuilder() { return StreamBuilder( stream: _peersBloc!.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { _peers = snapshot.data!.peers; return _getTable(); @@ -79,18 +79,16 @@ class _PeersWidget extends State { switch (columnName) { case 'IP': _sortAscending - ? _peers!.sort((a, b) => a.ip.compareTo(b.ip)) - : _peers!.sort((a, b) => b.ip.compareTo(a.ip)); - break; + ? _peers!.sort((Peer a, Peer b) => a.ip.compareTo(b.ip)) + : _peers!.sort((Peer a, Peer b) => b.ip.compareTo(a.ip)); case 'Public Key': _sortAscending - ? _peers!.sort((a, b) => a.publicKey.compareTo(b.publicKey)) - : _peers!.sort((a, b) => b.publicKey.compareTo(a.publicKey)); - break; + ? _peers!.sort((Peer a, Peer b) => a.publicKey.compareTo(b.publicKey)) + : _peers!.sort((Peer a, Peer b) => b.publicKey.compareTo(a.publicKey)); default: _sortAscending - ? _peers!.sort((a, b) => a.ip.compareTo(b.ip)) - : _peers!.sort((a, b) => b.ip.compareTo(a.ip)); + ? _peers!.sort((Peer a, Peer b) => a.ip.compareTo(b.ip)) + : _peers!.sort((Peer a, Peer b) => b.ip.compareTo(a.ip)); break; } setState(() { diff --git a/lib/widgets/modular_widgets/settings_widgets/security.dart b/lib/widgets/modular_widgets/settings_widgets/security.dart index aee0b33d..0b5e7b66 100644 --- a/lib/widgets/modular_widgets/settings_widgets/security.dart +++ b/lib/widgets/modular_widgets/settings_widgets/security.dart @@ -17,19 +17,19 @@ import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; -const double _kMaxMinutesOfInactivity = 30.0; -const double _kMinUnlockAttempts = 3.0; -const double _kMaxUnlockAttempts = 10.0; +const double _kMaxMinutesOfInactivity = 30; +const double _kMinUnlockAttempts = 3; +const double _kMaxUnlockAttempts = 10; class SecurityWidget extends StatefulWidget { - final VoidCallback _onChangeAutoLockTime; - final VoidCallback onStepperNotificationSeeMorePressed; const SecurityWidget( this._onChangeAutoLockTime, { required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback _onChangeAutoLockTime; + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() { @@ -91,7 +91,7 @@ class _SecurityWidgetState extends State { Widget _getWidgetBody(BuildContext context) { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel( 'Change password', _getChangePasswordExpandedWidget(), @@ -127,7 +127,7 @@ class _SecurityWidgetState extends State { Widget _getAutoLockSlider() { return Column( - children: [ + children: [ CustomSlider( description: 'Lock after $_autoLockWalletMinutes minutes of inactivity', @@ -147,7 +147,7 @@ class _SecurityWidgetState extends State { Widget _getAutoEraseSlider() { return Column( - children: [ + children: [ CustomSlider( description: 'Erase after ${_autoEraseWalletLimit!.toInt()} ' 'failed password attempts', @@ -174,7 +174,7 @@ class _SecurityWidgetState extends State { ); } - void _onConfirmAutoLockDurationButtonPressed() async { + Future _onConfirmAutoLockDurationButtonPressed() async { try { _confirmIntervalButtonKey.currentState?.animateForward(); await sharedPrefsService! @@ -223,7 +223,6 @@ class _SecurityWidgetState extends State { details: 'The auto-erase limit has now ' '$kAutoEraseWalletLimit attempt(s)', timestamp: DateTime.now().millisecondsSinceEpoch, - id: null, type: NotificationType.autoEraseNumAttemptsChanged, ), ); @@ -241,7 +240,7 @@ class _SecurityWidgetState extends State { Widget _getSignExpandedWidget() { return Column( - children: [ + children: [ kVerticalSpacing, InputField( controller: _textToBeSignedController, @@ -266,16 +265,16 @@ class _SecurityWidgetState extends State { visible: _signedTextController.text.isNotEmpty, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ const SizedBox( - height: 10.0, + height: 10, ), const Text('Signature:'), const SizedBox( - height: 10.0, + height: 10, ), Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -286,14 +285,14 @@ class _SecurityWidgetState extends State { ], ), const SizedBox( - height: 10.0, + height: 10, ), const Text('Public key:'), const SizedBox( - height: 10.0, + height: 10, ), Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -313,7 +312,7 @@ class _SecurityWidgetState extends State { Future _onSignButtonPressed() async { try { _signButtonKey.currentState?.animateForward(); - final signature = await walletSign( + final Signature signature = await walletSign( _textToBeSignedController.text.codeUnits, ); setState(() { @@ -329,10 +328,10 @@ class _SecurityWidgetState extends State { Widget _getVerifyExpandedWidget() { return Column( - children: [ + children: [ kVerticalSpacing, InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _textToBeVerifiedController, @@ -353,17 +352,17 @@ class _SecurityWidgetState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), ), kVerticalSpacing, InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _signatureController, @@ -384,17 +383,17 @@ class _SecurityWidgetState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), ), kVerticalSpacing, InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _publicKeyToBeFilledController, @@ -415,12 +414,12 @@ class _SecurityWidgetState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), ), kVerticalSpacing, @@ -440,7 +439,7 @@ class _SecurityWidgetState extends State { Future _onVerifyButtonPressed() async { try { _verifyButtonKey.currentState?.animateForward(); - bool verified = await Crypto.verify( + final bool verified = await Crypto.verify( FormatUtils.decodeHexString(_signatureController.text), Uint8List.fromList(_textToBeVerifiedController.text.codeUnits), FormatUtils.decodeHexString(_publicKeyToBeFilledController.text), @@ -466,7 +465,7 @@ class _SecurityWidgetState extends State { } } catch (e) { await NotificationUtils.sendNotificationError( - e, 'Error while verifying message'); + e, 'Error while verifying message',); } finally { _verifyButtonKey.currentState?.animateReverse(); } @@ -483,7 +482,7 @@ class _SecurityWidgetState extends State { Widget _getSignFileExpandedWidget() { return Column( - children: [ + children: [ SelectFileWidget( onPathFoundCallback: (String path) { setState(() { @@ -496,7 +495,7 @@ class _SecurityWidgetState extends State { Visibility( visible: _toBeSignedFilePath != null, child: Column( - children: [ + children: [ kVerticalSpacing, LoadingButton.settings( key: _signFileButtonKey, @@ -510,12 +509,12 @@ class _SecurityWidgetState extends State { visible: _fileHashController.text.isNotEmpty, child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ kVerticalSpacing, const Text('Signed hash:'), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -529,7 +528,7 @@ class _SecurityWidgetState extends State { const Text('Public key:'), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: InputField( enabled: false, @@ -546,15 +545,15 @@ class _SecurityWidgetState extends State { ); } - void _onSignFileButtonPressed() async { + Future _onSignFileButtonPressed() async { try { _signFileButtonKey.currentState?.animateForward(); - File droppedFile = File( + final File droppedFile = File( _toBeSignedFilePath!, ); - final fileSignature = await walletSign(Crypto.digest( + final Signature fileSignature = await walletSign(Crypto.digest( await droppedFile.readAsBytes(), - )); + ),); setState(() { _fileHashController.text = fileSignature.signature; _publicKeySignFileController.text = fileSignature.publicKey; @@ -570,7 +569,7 @@ class _SecurityWidgetState extends State { Widget _getVerifyFileExpandedWidget() { return Column( - children: [ + children: [ SelectFileWidget( onPathFoundCallback: (String path) { setState(() { @@ -583,7 +582,7 @@ class _SecurityWidgetState extends State { Visibility( visible: _toBeVerifiedFilePath != null, child: Column( - children: [ + children: [ kVerticalSpacing, LoadingButton.settings( key: _verifyFileButtonKey, @@ -597,10 +596,10 @@ class _SecurityWidgetState extends State { ), ), Column( - children: [ + children: [ kVerticalSpacing, InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _fileHashVerifyController, @@ -621,17 +620,17 @@ class _SecurityWidgetState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), ), kVerticalSpacing, InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _publicKeyVerifyFileController, @@ -652,15 +651,15 @@ class _SecurityWidgetState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), ), - kVerticalSpacing + kVerticalSpacing, ], ), ], @@ -670,11 +669,11 @@ class _SecurityWidgetState extends State { Future _onVerifyFileButtonPressed() async { try { _verifyFileButtonKey.currentState?.animateForward(); - bool verified = await Crypto.verify( + final bool verified = await Crypto.verify( FormatUtils.decodeHexString(_fileHashVerifyController.text), Uint8List.fromList(Crypto.digest(await File( _toBeVerifiedFilePath!, - ).readAsBytes())), + ).readAsBytes(),),), FormatUtils.decodeHexString(_publicKeyVerifyFileController.text), ); if (verified) { @@ -699,7 +698,7 @@ class _SecurityWidgetState extends State { } } catch (e) { await NotificationUtils.sendNotificationError( - e, 'Error while verifying file hash:'); + e, 'Error while verifying file hash:',); } finally { _verifyFileButtonKey.currentState?.animateReverse(); } diff --git a/lib/widgets/modular_widgets/settings_widgets/wallet_options.dart b/lib/widgets/modular_widgets/settings_widgets/wallet_options.dart index 296b6f1d..584e6344 100644 --- a/lib/widgets/modular_widgets/settings_widgets/wallet_options.dart +++ b/lib/widgets/modular_widgets/settings_widgets/wallet_options.dart @@ -12,7 +12,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class WalletOptions extends StatefulWidget { - const WalletOptions({Key? key}) : super(key: key); + const WalletOptions({super.key}); @override State createState() => _WalletOptionsState(); @@ -50,14 +50,14 @@ class _WalletOptionsState extends State { return CardScaffold( title: 'Wallet Options', description: 'Other wallet options', - childBuilder: () => _getWidgetBody(), + childBuilder: _getWidgetBody, ); } Widget _getWidgetBody() { return ListView( shrinkWrap: true, - children: [ + children: [ CustomExpandablePanel('Delete cache', _getDeleteCacheExpandedWidget()), CustomExpandablePanel('Reset wallet', _getResetWalletExpandedWidget()), CustomExpandablePanel('Preferences', _getPreferencesExpandedWidget()), @@ -116,24 +116,24 @@ class _WalletOptionsState extends State { Widget _getPreferencesExpandedWidget() { return Column( - children: [ + children: [ _getLaunchAtStartupWidget(), _getEnableDesktopNotifications(), _buildEnableClipboardWatcher(), - _getAutoReceiveWidget() + _getAutoReceiveWidget(), ], ); } Widget _getLaunchAtStartupWidget() { return Row( - children: [ + children: [ Text( 'Launch at startup ', style: Theme.of(context).textTheme.bodyMedium, ), SyriusCheckbox( - onChanged: (value) async { + onChanged: (bool? value) async { setState(() { _launchAtStartup = value; }); @@ -148,19 +148,19 @@ class _WalletOptionsState extends State { Widget _getAutoReceiveWidget() { return Row( - children: [ + children: [ Text( 'Auto-receiver', style: Theme.of(context).textTheme.bodyMedium, ), SyriusCheckbox( - onChanged: (value) async { + onChanged: (bool? value) async { if (value == true) { NodeUtils.getUnreceivedTransactions().then((value) { sl().autoReceive(); - }).onError((error, stackTrace) { + }).onError((Object? error, StackTrace stackTrace) { Logger('MainAppContainer').log( - Level.WARNING, '_getAutoReceiveWidget', error, stackTrace); + Level.WARNING, '_getAutoReceiveWidget', error, stackTrace,); }); } else if (value == false && sl().pool.isNotEmpty) { @@ -183,7 +183,7 @@ class _WalletOptionsState extends State { } Future _setupLaunchAtStartup() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); + final PackageInfo packageInfo = await PackageInfo.fromPlatform(); launchAtStartup.setup( appName: packageInfo.appName, appPath: Platform.resolvedExecutable, @@ -260,13 +260,13 @@ class _WalletOptionsState extends State { Widget _getEnableDesktopNotifications() { return Row( - children: [ + children: [ Text( 'Enable desktop notifications ', style: Theme.of(context).textTheme.bodyMedium, ), SyriusCheckbox( - onChanged: (value) { + onChanged: (bool? value) { setState(() { _enableDesktopNotifications = value; _changeEnableDesktopNotificationsStatus(value ?? false); @@ -281,13 +281,13 @@ class _WalletOptionsState extends State { Widget _buildEnableClipboardWatcher() { return Row( - children: [ + children: [ Text( 'Enable clipboard watcher', style: Theme.of(context).textTheme.bodyMedium, ), SyriusCheckbox( - onChanged: (value) { + onChanged: (bool? value) { setState(() { _enabledClipboardWatcher = value; _changeEnableClipboardWatcherStatus(value ?? false); @@ -331,7 +331,7 @@ class _WalletOptionsState extends State { } Future _sendEnabledDesktopNotificationsStatusNotification( - bool enabled) async { + bool enabled,) async { await sl.get().addNotification( WalletNotification( title: 'Desktop notifications ${enabled ? 'enabled' : 'disabled'}', @@ -344,7 +344,7 @@ class _WalletOptionsState extends State { } Future _sendEnableClipboardWatcherStatusNotification( - bool enabled) async { + bool enabled,) async { await sl.get().addNotification( WalletNotification( title: 'Clipboard watcher ${enabled ? 'enabled' : 'disabled'}', diff --git a/lib/widgets/modular_widgets/staking_widgets/stake_collect.dart b/lib/widgets/modular_widgets/staking_widgets/stake_collect.dart index 9c2ce185..d5cebe5b 100644 --- a/lib/widgets/modular_widgets/staking_widgets/stake_collect.dart +++ b/lib/widgets/modular_widgets/staking_widgets/stake_collect.dart @@ -11,12 +11,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StakeCollect extends StatefulWidget { - final StakingRewardsHistoryBloc stakingRewardsHistoryBloc; const StakeCollect({ required this.stakingRewardsHistoryBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final StakingRewardsHistoryBloc stakingRewardsHistoryBloc; @override State createState() => _StakeCollectState(); @@ -36,7 +36,7 @@ class _StakeCollectState extends State { 'ready to be collected. If there are any rewards available, you ' 'will be able to collect them', childBuilder: () => Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16), child: _getFutureBuilder(), ), ); @@ -45,7 +45,7 @@ class _StakeCollectState extends State { Widget _getFutureBuilder() { return StreamBuilder( stream: _stakingUncollectedRewardsBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { @@ -62,14 +62,13 @@ class _StakeCollectState extends State { Widget _getWidgetBody(UncollectedReward uncollectedReward) { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ NumberAnimation( end: uncollectedReward.qsrAmount.addDecimals(coinDecimals).toNum(), - isInt: false, after: ' ${kQsrCoin.symbol}', style: Theme.of(context).textTheme.headlineLarge!.copyWith( color: AppColors.qsrColor, - fontSize: 30.0, + fontSize: 30, ), ), kVerticalSpacing, @@ -88,7 +87,7 @@ class _StakeCollectState extends State { ); } - void _onCollectPressed() async { + Future _onCollectPressed() async { try { _collectButtonKey.currentState?.animateForward(); await AccountBlockUtils.createAccountBlock( @@ -96,7 +95,7 @@ class _StakeCollectState extends State { 'collect staking rewards', waitForRequiredPlasma: true, ).then( - (response) async { + (AccountBlockTemplate response) async { await Future.delayed(kDelayAfterAccountBlockCreationCall); if (mounted) { _stakingUncollectedRewardsBloc.updateStream(); diff --git a/lib/widgets/modular_widgets/staking_widgets/staking_list/staking_list.dart b/lib/widgets/modular_widgets/staking_widgets/staking_list/staking_list.dart index acb29063..5f26ff73 100644 --- a/lib/widgets/modular_widgets/staking_widgets/staking_list/staking_list.dart +++ b/lib/widgets/modular_widgets/staking_widgets/staking_list/staking_list.dart @@ -10,9 +10,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StakingList extends StatefulWidget { - final StakingListBloc bloc; - const StakingList(this.bloc, {Key? key}) : super(key: key); + const StakingList(this.bloc, {super.key}); + final StakingListBloc bloc; @override State createState() { @@ -21,7 +21,7 @@ class StakingList extends StatefulWidget { } class _StakingListState extends State { - final List _stakingList = []; + final List _stakingList = []; bool _sortAscending = true; @@ -42,7 +42,7 @@ class _StakingListState extends State { // This bloc is being used in another place, so it shouldn't be disposed // when this widget is disposed itself disposeBloc: false, - headerColumns: [ + headerColumns: [ InfiniteScrollTableHeaderColumn( columnName: 'Amount', onSortArrowsPressed: _onSortArrowsPressed, @@ -62,15 +62,15 @@ class _StakingListState extends State { ), const InfiniteScrollTableHeaderColumn(columnName: ''), ], - generateRowCells: (stakingItem, bool isSelected) { - return [ + generateRowCells: (StakeEntry stakingItem, bool isSelected) { + return [ InfiniteScrollTableCell( FormattedAmountWithTooltip( amount: stakingItem.amount.addDecimals( kZnnCoin.decimals, ), tokenSymbol: kZnnCoin.symbol, - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( '$formattedAmount $tokenSymbol', style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -91,8 +91,8 @@ class _StakingListState extends State { showCopyToClipboardIcon: isSelected ? true : false, ), InfiniteScrollTableCell( - _getCancelContainer(isSelected, stakingItem, bloc)), - InfiniteScrollTableCell.withText(context, '') + _getCancelContainer(isSelected, stakingItem, bloc),), + InfiniteScrollTableCell.withText(context, ''), ]; }, ); @@ -105,16 +105,13 @@ class _StakingListState extends State { ) { return Stack( alignment: Alignment.centerLeft, - fit: StackFit.loose, - children: [ - stakingItem.expirationTimestamp * 1000 < - DateTime.now().millisecondsSinceEpoch - ? _getCancelButtonViewModel( + children: [ + if (stakingItem.expirationTimestamp * 1000 < + DateTime.now().millisecondsSinceEpoch) _getCancelButtonViewModel( stakingListModel, isSelected, stakingItem.id.toString(), - ) - : _getCancelTimer(stakingItem, stakingListModel) + ) else _getCancelTimer(stakingItem, stakingListModel), ], ); } @@ -124,12 +121,12 @@ class _StakingListState extends State { bool isSelected, String stakeHash, ) { - final GlobalKey cancelButtonKey = GlobalKey(); + final GlobalKey cancelButtonKey = GlobalKey(); return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (CancelStakeBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { cancelButtonKey.currentState?.animateReverse(); bloc.refreshResults(); @@ -144,12 +141,12 @@ class _StakingListState extends State { }, ); }, - builder: (_, model, __) => _getCancelButton( + builder: (_, CancelStakeBloc model, __) => _getCancelButton( model, stakeHash, cancelButtonKey, ), - viewModelBuilder: () => CancelStakeBloc(), + viewModelBuilder: CancelStakeBloc.new, ); } @@ -168,7 +165,7 @@ class _StakingListState extends State { key: key, icon: const Icon( SimpleLineIcons.close, - size: 11.0, + size: 11, color: AppColors.errorColor, ), textStyle: Theme.of(context).textTheme.titleSmall!.copyWith( @@ -181,36 +178,32 @@ class _StakingListState extends State { switch (columnName) { case 'Amount': _sortAscending - ? _stakingList.sort((a, b) => a.amount.compareTo(b.amount)) - : _stakingList.sort((a, b) => b.amount.compareTo(a.amount)); - break; + ? _stakingList.sort((StakeEntry a, StakeEntry b) => a.amount.compareTo(b.amount)) + : _stakingList.sort((StakeEntry a, StakeEntry b) => b.amount.compareTo(a.amount)); case 'Staking duration': _sortAscending ? _stakingList.sort( - (a, b) => (a.expirationTimestamp - a.startTimestamp) + (StakeEntry a, StakeEntry b) => (a.expirationTimestamp - a.startTimestamp) .compareTo(b.expirationTimestamp - b.startTimestamp), ) : _stakingList.sort( - (a, b) => (b.expirationTimestamp - b.startTimestamp) + (StakeEntry a, StakeEntry b) => (b.expirationTimestamp - b.startTimestamp) .compareTo(a.expirationTimestamp - a.startTimestamp), ); - break; case 'Recipient': _sortAscending - ? _stakingList.sort((a, b) => a.address.compareTo(b.address)) - : _stakingList.sort((a, b) => b.address.compareTo(a.address)); - break; + ? _stakingList.sort((StakeEntry a, StakeEntry b) => a.address.compareTo(b.address)) + : _stakingList.sort((StakeEntry a, StakeEntry b) => b.address.compareTo(a.address)); case 'Expiration': _sortAscending - ? _stakingList.sort((a, b) => - a.expirationTimestamp.compareTo(b.expirationTimestamp)) - : _stakingList.sort((a, b) => - b.expirationTimestamp.compareTo(a.expirationTimestamp)); - break; + ? _stakingList.sort((StakeEntry a, StakeEntry b) => + a.expirationTimestamp.compareTo(b.expirationTimestamp),) + : _stakingList.sort((StakeEntry a, StakeEntry b) => + b.expirationTimestamp.compareTo(a.expirationTimestamp),); default: _sortAscending - ? _stakingList.sort((a, b) => a.address.compareTo(b.address)) - : _stakingList.sort((a, b) => b.address.compareTo(a.address)); + ? _stakingList.sort((StakeEntry a, StakeEntry b) => a.address.compareTo(b.address)) + : _stakingList.sort((StakeEntry a, StakeEntry b) => b.address.compareTo(a.address)); break; } @@ -223,7 +216,7 @@ class _StakingListState extends State { StakeEntry stakingItem, StakingListBloc model, ) { - int secondsUntilExpiration = stakingItem.expirationTimestamp - + final int secondsUntilExpiration = stakingItem.expirationTimestamp - DateTime.now().millisecondsSinceEpoch ~/ 1000; return CancelTimer( Duration(seconds: secondsUntilExpiration), @@ -235,8 +228,8 @@ class _StakingListState extends State { } String _getStakingDurationInMonths(int seconds) { - int numDays = seconds / 3600 ~/ 24; - int numMonths = numDays ~/ 30; + final int numDays = seconds / 3600 ~/ 24; + final int numMonths = numDays ~/ 30; return '$numMonths month${numMonths > 1 ? 's' : ''}'; } diff --git a/lib/widgets/modular_widgets/staking_widgets/staking_options/staking_options.dart b/lib/widgets/modular_widgets/staking_widgets/staking_options/staking_options.dart index 69d5f896..1313b650 100644 --- a/lib/widgets/modular_widgets/staking_widgets/staking_options/staking_options.dart +++ b/lib/widgets/modular_widgets/staking_widgets/staking_options/staking_options.dart @@ -15,12 +15,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StakingOptions extends StatefulWidget { - final StakingListBloc? stakingListViewModel; const StakingOptions( this.stakingListViewModel, { - Key? key, - }) : super(key: key); + super.key, + }); + final StakingListBloc? stakingListViewModel; @override State createState() { @@ -32,10 +32,10 @@ class _StakingOptionsState extends State { Duration? _selectedStakeDuration; final List _durations = List.generate( - (stakeTimeMaxSec ~/ stakeTimeUnitSec), - (index) => Duration( + stakeTimeMaxSec ~/ stakeTimeUnitSec, + (int index) => Duration( seconds: (index + 1) * stakeTimeUnitSec, - )); + ),); BigInt _maxZnnAmount = BigInt.zero; @@ -58,7 +58,7 @@ class _StakingOptionsState extends State { _addressController.text = kSelectedAddress!; return LayoutBuilder( - builder: (_, constraints) { + builder: (_, BoxConstraints constraints) { _maxWidth = constraints.maxWidth; return CardScaffold( title: 'Staking Options', @@ -68,7 +68,7 @@ class _StakingOptionsState extends State { '${kQsrCoin.symbol}', childBuilder: () => StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -95,21 +95,21 @@ class _StakingOptionsState extends State { Widget _getWidgetBody(AccountInfo? accountInfo) { return Container( margin: const EdgeInsets.all( - 20.0, + 20, ), child: ListView( shrinkWrap: true, - children: [ + children: [ DisabledAddressField( _addressController, - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), StepperUtils.getBalanceWidget(kZnnCoin, accountInfo!), Container( - padding: const EdgeInsets.only(left: 20.0), + padding: const EdgeInsets.only(left: 20), decoration: BoxDecoration( color: Theme.of(context).inputDecorationTheme.fillColor, - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5), ), child: _getStakeDurationDropdown(), ), @@ -125,7 +125,7 @@ class _StakingOptionsState extends State { _znnAmountController.text, ), controller: _znnAmountController, - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, _maxZnnAmount, kZnnCoin.decimals, @@ -134,13 +134,13 @@ class _StakingOptionsState extends State { ), suffixIcon: _getZnnAmountSuffix(), hintText: 'Amount', - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), ), kVerticalSpacing, Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ _getStakeForQsrViewModel(), ], ), @@ -151,9 +151,9 @@ class _StakingOptionsState extends State { Widget _getStakeForQsrViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (StakingOptionsBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { _stakeButtonKey.currentState?.animateReverse(); widget.stakingListViewModel!.refreshResults(); @@ -173,21 +173,21 @@ class _StakingOptionsState extends State { }, ); }, - builder: (_, model, __) => _getStakeForQsrButton(model), - viewModelBuilder: () => StakingOptionsBloc(), + builder: (_, StakingOptionsBloc model, __) => _getStakeForQsrButton(model), + viewModelBuilder: StakingOptionsBloc.new, ); } Widget _getStakeForQsrButton(StakingOptionsBloc model) { - Widget icon = Container( + final Widget icon = Container( decoration: const BoxDecoration( shape: BoxShape.circle, color: AppColors.znnColor, ), - padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 15.0), + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 15), child: const Icon( MaterialCommunityIcons.lock_smart, - size: 15.0, + size: 15, color: Colors.white, ), ); @@ -197,7 +197,7 @@ class _StakingOptionsState extends State { label: 'Stake', icon: icon, key: _stakeButtonKey, - minimumSize: Size(_maxWidth! - 2 * 20.0, 40.0), + minimumSize: Size(_maxWidth! - 2 * 20.0, 40), ); } @@ -209,23 +209,23 @@ class _StakingOptionsState extends State { style: Theme.of(context).inputDecorationTheme.hintStyle, ), icon: Container( - margin: const EdgeInsets.symmetric(horizontal: 10.0), + margin: const EdgeInsets.symmetric(horizontal: 10), child: Icon( SimpleLineIcons.arrow_down, - size: 10.0, + size: 10, color: Theme.of(context).inputDecorationTheme.hintStyle!.color, ), ), value: _selectedStakeDuration, items: _durations .map( - (duration) => DropdownMenuItem( + (Duration duration) => DropdownMenuItem( value: duration, child: Text( '${duration.inSeconds ~/ stakeTimeUnitSec} $stakeUnitDurationName' '${(duration.inSeconds ~/ stakeTimeUnitSec) > 1 ? 's' : ''}', style: Theme.of(context).textTheme.bodyLarge!.copyWith( - fontSize: 12.0, + fontSize: 12, color: _selectedStakeDuration?.inDays == duration.inDays ? AppColors.znnColor : null, @@ -234,7 +234,7 @@ class _StakingOptionsState extends State { ), ) .toList(), - onChanged: (value) { + onChanged: (Duration? value) { setState(() { _selectedStakeDuration = value; }); diff --git a/lib/widgets/modular_widgets/staking_widgets/staking_rewards.dart b/lib/widgets/modular_widgets/staking_widgets/staking_rewards.dart index 1e2a4cf2..ddb7c539 100644 --- a/lib/widgets/modular_widgets/staking_widgets/staking_rewards.dart +++ b/lib/widgets/modular_widgets/staking_widgets/staking_rewards.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class StakingRewards extends StatefulWidget { - final StakingRewardsHistoryBloc stakingRewardsHistoryBloc; const StakingRewards({ required this.stakingRewardsHistoryBloc, - Key? key, - }) : super(key: key); + super.key, + }); + final StakingRewardsHistoryBloc stakingRewardsHistoryBloc; @override State createState() { @@ -26,7 +26,7 @@ class _StakingRewardsState extends State { 'your staking entries', childBuilder: () => Padding( padding: const EdgeInsets.all( - 16.0, + 16, ), child: _getStreamBody(), ), @@ -36,7 +36,7 @@ class _StakingRewardsState extends State { Widget _getStreamBody() { return StreamBuilder( stream: widget.stakingRewardsHistoryBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } diff --git a/lib/widgets/modular_widgets/token_widgets/create_token.dart b/lib/widgets/modular_widgets/token_widgets/create_token.dart index f4ee7968..8dd1dba2 100644 --- a/lib/widgets/modular_widgets/token_widgets/create_token.dart +++ b/lib/widgets/modular_widgets/token_widgets/create_token.dart @@ -5,12 +5,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class CreateToken extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const CreateToken({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() { @@ -24,28 +24,28 @@ class _CreateTokenState extends State { return CardScaffold( title: 'Create Token', description: 'Create a token following the ZTS specification', - childBuilder: () => _getWidgetBody(), + childBuilder: _getWidgetBody, ); } Widget _getWidgetBody() { return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Lottie.asset( 'assets/lottie/ic_anim_zts.json', - width: 128.0, - height: 128.0, + width: 128, + height: 128, repeat: false, ), Container( - padding: const EdgeInsets.symmetric(horizontal: 48.0, vertical: 12.0), + padding: const EdgeInsets.symmetric(horizontal: 48, vertical: 12), child: SyriusElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute( - builder: (context) => StepperScreen( + builder: (BuildContext context) => StepperScreen( stepper: const TokenStepper(), onStepperNotificationSeeMorePressed: widget.onStepperNotificationSeeMorePressed, @@ -72,7 +72,7 @@ class _CreateTokenState extends State { child: const Icon( Icons.add, color: Colors.white, - size: 15.0, + size: 15, ), ); } diff --git a/lib/widgets/modular_widgets/token_widgets/token_balance.dart b/lib/widgets/modular_widgets/token_widgets/token_balance.dart index b5c7f1b0..58d185c6 100644 --- a/lib/widgets/modular_widgets/token_widgets/token_balance.dart +++ b/lib/widgets/modular_widgets/token_widgets/token_balance.dart @@ -7,7 +7,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TokenBalance extends StatefulWidget { - const TokenBalance({Key? key}) : super(key: key); + const TokenBalance({super.key}); @override State createState() { @@ -16,7 +16,7 @@ class TokenBalance extends StatefulWidget { } class _TokenBalanceState extends State { - List _newTokenIds = []; + List _newTokenIds = []; @override void initState() { @@ -29,9 +29,9 @@ class _TokenBalanceState extends State { _newTokenIds.clear(); } _newTokenIds = accountInfo.balanceInfoList!.fold( - [], - (previousValue, element) { - if (![kZnnCoin.tokenStandard, kQsrCoin.tokenStandard] + [], + (List previousValue, BalanceInfoListItem element) { + if (![kZnnCoin.tokenStandard, kQsrCoin.tokenStandard] .contains(element.token!.tokenStandard)) { previousValue.add(element); } @@ -48,7 +48,7 @@ class _TokenBalanceState extends State { 'currently hold in your wallet', childBuilder: () => StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -72,7 +72,7 @@ class _TokenBalanceState extends State { Widget _getWidgetBody(AccountInfo? accountInfo) { return Column( - children: [ + children: [ kVerticalSpacing, Expanded(child: _getNewTokensGridViewStatus(accountInfo)), ], @@ -81,7 +81,7 @@ class _TokenBalanceState extends State { Widget _getTokenStatus(String formattedAmount, String tokenSymbol) { return Row( - children: [ + children: [ Text( '$formattedAmount $tokenSymbol', style: Theme.of(context).textTheme.bodyLarge, @@ -97,28 +97,28 @@ class _TokenBalanceState extends State { gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 100 / 20, - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, + crossAxisSpacing: 10, + mainAxisSpacing: 10, ), - itemBuilder: (context, index) => Padding( - padding: const EdgeInsets.all(8.0), + itemBuilder: (BuildContext context, int index) => Padding( + padding: const EdgeInsets.all(8), child: Marquee( child: FormattedAmountWithTooltip( amount: _newTokenIds[index] .balance! .addDecimals(_newTokenIds[index].token!.decimals), tokenSymbol: _newTokenIds[index].token!.symbol, - builder: (amount, symbol) => Row( + builder: (String amount, String symbol) => Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text( '● ', style: Theme.of(context).textTheme.bodyLarge!.copyWith( color: ColorUtils.getTokenColor( - _newTokenIds[index].token!.tokenStandard), + _newTokenIds[index].token!.tokenStandard,), ), ), - _getTokenStatus(amount, symbol) + _getTokenStatus(amount, symbol), ], ), ), diff --git a/lib/widgets/modular_widgets/token_widgets/token_card.dart b/lib/widgets/modular_widgets/token_widgets/token_card.dart index a3c7b7b3..1a9375c7 100644 --- a/lib/widgets/modular_widgets/token_widgets/token_card.dart +++ b/lib/widgets/modular_widgets/token_widgets/token_card.dart @@ -26,14 +26,14 @@ enum TokenCardBackVersion { } class TokenCard extends StatefulWidget { - final Token token; - final VoidCallback _favoritesCallback; const TokenCard( this.token, this._favoritesCallback, { - Key? key, - }) : super(key: key); + super.key, + }); + final Token token; + final VoidCallback _favoritesCallback; @override State createState() => _TokenCardState(); @@ -75,9 +75,6 @@ class _TokenCardState extends State { key: _cardKey, rotateSide: RotateSide.right, animationDuration: const Duration(milliseconds: 500), - axis: FlipAxis.vertical, - disableSplashEffect: false, - onTapFlipping: false, controller: _flipCardController, frontWidget: _getFrontOfCard(), backWidget: _getBackOfCard(), @@ -91,16 +88,16 @@ class _TokenCardState extends State { Widget _getBackOfCard() { return Container( padding: const EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 10.0, + horizontal: 20, + vertical: 10, ), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), color: Theme.of(context).colorScheme.primaryContainer, ), child: StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -112,35 +109,35 @@ class _TokenCardState extends State { } return const SyriusLoadingWidget(); }, - )); + ),); } Container _getFrontOfCard() { return Container( padding: const EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 10.0, + horizontal: 20, + vertical: 10, ), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), color: Theme.of(context).colorScheme.primaryContainer, ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Container( - height: 5.0, - width: 5.0, + height: 5, + width: 5, decoration: BoxDecoration( shape: BoxShape.circle, color: ColorUtils.getTokenColor(widget.token.tokenStandard), ), ), const SizedBox( - width: 5.0, + width: 5, ), Tooltip( message: '${widget.token.name}: ${widget.token.symbol}', @@ -150,18 +147,18 @@ class _TokenCardState extends State { ), ), const SizedBox( - width: 5.0, + width: 5, ), ], ), Row( - children: [ + children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: Marquee( child: Text( @@ -178,10 +175,10 @@ class _TokenCardState extends State { ], ), const SizedBox( - height: 5.0, + height: 5, ), Wrap( - children: [ + children: [ if (kDefaultAddressList .contains(widget.token.owner.toString())) _getTokenOptionIconButton( @@ -238,7 +235,6 @@ class _TokenCardState extends State { _getTokenOptionIconButton( tooltip: 'Utility token', mouseCursor: SystemMouseCursors.basic, - onPressed: null, iconData: Icons.settings, ), TokenFavorite( @@ -248,7 +244,7 @@ class _TokenCardState extends State { ], ), const SizedBox( - height: 10.0, + height: 10, ), Text( '${widget.token.decimals} decimals', @@ -257,14 +253,14 @@ class _TokenCardState extends State { ], ), ), - _getAnimatedChart(widget.token) + _getAnimatedChart(widget.token), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Row( - children: [ + children: [ Text( kDefaultAddressList.contains(widget.token.owner.toString()) ? kAddressLabelMap[widget.token.owner.toString()]! @@ -276,8 +272,8 @@ class _TokenCardState extends State { ), RawMaterialButton( constraints: const BoxConstraints( - minWidth: 40.0, - minHeight: 40.0, + minWidth: 40, + minHeight: 40, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), @@ -285,8 +281,8 @@ class _TokenCardState extends State { child: Tooltip( message: 'Visit ${widget.token.domain}', child: Container( - height: 25.0, - width: 25.0, + height: 25, + width: 25, padding: const EdgeInsets.all(4), decoration: const BoxDecoration( shape: BoxShape.circle, @@ -294,12 +290,12 @@ class _TokenCardState extends State { ), child: const Icon( Icons.open_in_new, - size: 13.0, + size: 13, color: AppColors.darkHintTextColor, ), ), ), - ) + ), ], ), ], @@ -327,9 +323,9 @@ class _TokenCardState extends State { : mouseCursor, tooltip: tooltip, padding: EdgeInsets.zero, - splashRadius: 18.0, + splashRadius: 18, onPressed: onPressed, - iconSize: 25.0, + iconSize: 25, icon: Icon( iconData, color: isOwner != null @@ -343,27 +339,27 @@ class _TokenCardState extends State { } Widget _getAnimatedChart(Token token) { - BigInt totalSupply = token.totalSupply; + final BigInt totalSupply = token.totalSupply; - BigInt maxSupply = token.maxSupply; + final BigInt maxSupply = token.maxSupply; return Stack( alignment: Alignment.center, - children: [ + children: [ SizedBox( - height: 100.0, - width: 100.0, + height: 100, + width: 100, child: StandardPieChart( - sections: [ + sections: [ PieChartSectionData( showTitle: false, - radius: 5.0, + radius: 5, value: totalSupply / maxSupply, color: ColorUtils.getTokenColor(widget.token.tokenStandard), ), PieChartSectionData( showTitle: false, - radius: 5.0, + radius: 5, value: (maxSupply - totalSupply) / maxSupply, color: Colors.white12, ), @@ -371,12 +367,12 @@ class _TokenCardState extends State { ), ), SizedBox( - width: 70.0, + width: 70, child: Marquee( child: FormattedAmountWithTooltip( amount: totalSupply.addDecimals(token.decimals), tokenSymbol: token.symbol, - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( '$formattedAmount $tokenSymbol', style: Theme.of(context).textTheme.bodyMedium, textAlign: TextAlign.center, @@ -395,7 +391,7 @@ class _TokenCardState extends State { return ListView( shrinkWrap: true, - children: [ + children: [ Form( key: _burnAmountKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -407,30 +403,28 @@ class _TokenCardState extends State { _burnAmountController.text, ), controller: _burnAmountController, - validator: (value) => InputValidators.correctValue( - value, _burnMaxAmount, widget.token.decimals, BigInt.zero), + validator: (String? value) => InputValidators.correctValue( + value, _burnMaxAmount, widget.token.decimals, BigInt.zero,), suffixIcon: _getAmountSuffix(), - suffixIconConstraints: const BoxConstraints(maxWidth: 50.0), + suffixIconConstraints: const BoxConstraints(maxWidth: 50), hintText: 'Amount', - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), ), StepperUtils.getBalanceWidget(widget.token, accountInfo), Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Column( - children: [ + children: [ _getBurnButtonViewModel(), const SizedBox( - height: 10.0, + height: 10, ), StepperButton( text: 'Go back', - onPressed: () { - _flipCard(); - }, + onPressed: _flipCard, ), ], ), @@ -442,9 +436,9 @@ class _TokenCardState extends State { Widget _getBurnButtonViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (BurnTokenBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate event) { setState(() { _burnAmountKey.currentState?.reset(); _burnAmountController.clear(); @@ -462,13 +456,13 @@ class _TokenCardState extends State { }, ); }, - builder: (_, model, __) => _getBurnButton(model), - viewModelBuilder: () => BurnTokenBloc(), + builder: (_, BurnTokenBloc model, __) => _getBurnButton(model), + viewModelBuilder: BurnTokenBloc.new, ); } Future _sendBurnSuccessfulNotification( - AccountBlockTemplate event) async { + AccountBlockTemplate event,) async { await sl.get().addNotification( WalletNotification( title: 'Successfully burned ${event.amount.addDecimals( @@ -478,7 +472,7 @@ class _TokenCardState extends State { details: 'You have successfully burned the requested amount: ' '${event.amount.addDecimals( widget.token.decimals, - )} ${widget.token.symbol} ${event.hash.toString()}', + )} ${widget.token.symbol} ${event.hash}', type: NotificationType.burnToken, ), ); @@ -490,14 +484,14 @@ class _TokenCardState extends State { onPressed: _burnMaxAmount > BigInt.zero && _burnAmountController.text.isNotEmpty && InputValidators.correctValue(_burnAmountController.text, - _burnMaxAmount, widget.token.decimals, BigInt.zero) == + _burnMaxAmount, widget.token.decimals, BigInt.zero,) == null ? () { _burnButtonKey.currentState?.animateForward(); model.burnToken( widget.token, _burnAmountController.text - .extractDecimals(widget.token.decimals)); + .extractDecimals(widget.token.decimals),); } : null, key: _burnButtonKey, @@ -506,7 +500,7 @@ class _TokenCardState extends State { Widget _getAmountSuffix() { return Row( - children: [ + children: [ AmountSuffixMaxWidget( onPressed: _onMaxPressed, context: context, @@ -534,25 +528,25 @@ class _TokenCardState extends State { } Widget _getMintBackOfCard(AccountInfo? accountInfo) { - _mintMaxAmount = (widget.token.maxSupply - widget.token.totalSupply); + _mintMaxAmount = widget.token.maxSupply - widget.token.totalSupply; return ListView( shrinkWrap: true, - children: [ + children: [ Form( key: _beneficiaryAddressKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[0-9a-z]')), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9a-z]')), ], controller: _beneficiaryAddressController, hintText: 'Beneficiary address', - contentLeftPadding: 20.0, - validator: (value) => InputValidators.checkAddress(value), + contentLeftPadding: 20, + validator: InputValidators.checkAddress, ), ), StepperUtils.getBalanceWidget(widget.token, accountInfo!), @@ -560,37 +554,35 @@ class _TokenCardState extends State { key: _mintAmountKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( _mintAmountController.text, ), controller: _mintAmountController, - validator: (value) => InputValidators.correctValue( - value, _mintMaxAmount, widget.token.decimals, BigInt.zero), + validator: (String? value) => InputValidators.correctValue( + value, _mintMaxAmount, widget.token.decimals, BigInt.zero,), suffixIcon: _getAmountSuffix(), - suffixIconConstraints: const BoxConstraints(maxWidth: 50.0), + suffixIconConstraints: const BoxConstraints(maxWidth: 50), hintText: 'Amount', - contentLeftPadding: 20.0, + contentLeftPadding: 20, ), ), kVerticalSpacing, Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Column( - children: [ + children: [ _getMintButtonViewModel(), const SizedBox( - height: 10.0, + height: 10, ), StepperButton( text: 'Go back', - onPressed: () { - _flipCard(); - }, + onPressed: _flipCard, ), ], ), @@ -602,8 +594,8 @@ class _TokenCardState extends State { Widget _getMintButtonViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { - model.stream.listen((event) { + onViewModelReady: (MintTokenBloc model) { + model.stream.listen((AccountBlockTemplate event) { setState(() { _beneficiaryAddressKey.currentState!.reset(); _mintAmountKey.currentState!.reset(); @@ -618,15 +610,15 @@ class _TokenCardState extends State { 'Error while trying to mint ${widget.token.symbol}}', ); _mintButtonKey.currentState!.animateReverse(); - }); + },); }, - builder: (_, model, __) => _getMintButton(model), - viewModelBuilder: () => MintTokenBloc(), + builder: (_, MintTokenBloc model, __) => _getMintButton(model), + viewModelBuilder: MintTokenBloc.new, ); } Future _sendMintSuccessfulNotification( - AccountBlockTemplate event) async { + AccountBlockTemplate event,) async { await sl.get().addNotification( WalletNotification( title: 'Successfully minted ${event.amount.addDecimals( @@ -636,7 +628,7 @@ class _TokenCardState extends State { details: 'You have successfully minted the requested amount: ' '${event.amount.addDecimals( widget.token.decimals, - )} ${widget.token.symbol} ${event.hash.toString()}', + )} ${widget.token.symbol} ${event.hash}', type: NotificationType.paymentSent, ), ); @@ -651,7 +643,7 @@ class _TokenCardState extends State { _mintMaxAmount > BigInt.zero && _mintAmountController.text.isNotEmpty && InputValidators.correctValue(_mintAmountController.text, - _mintMaxAmount, widget.token.decimals, BigInt.zero) == + _mintMaxAmount, widget.token.decimals, BigInt.zero,) == null ? () { _mintButtonKey.currentState!.animateForward(); @@ -677,7 +669,7 @@ class _TokenCardState extends State { Widget _getTransferOwnershipBackOfCard() { return ListView( shrinkWrap: true, - children: [ + children: [ Form( key: _newOwnerAddressKey, autovalidateMode: AutovalidateMode.onUserInteraction, @@ -685,31 +677,29 @@ class _TokenCardState extends State { onChanged: (String value) { setState(() {}); }, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[0-9a-z]')), + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9a-z]')), ], controller: _newOwnerAddressController, hintText: 'New owner address', - contentLeftPadding: 20.0, - validator: (value) => InputValidators.checkAddress(value), + contentLeftPadding: 20, + validator: InputValidators.checkAddress, ), ), kVerticalSpacing, Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Column( - children: [ + children: [ _getTransferOwnershipButtonViewModel(), const SizedBox( - height: 10.0, + height: 10, ), StepperButton( text: 'Go back', - onPressed: () { - _flipCard(); - }, + onPressed: _flipCard, ), ], ), @@ -724,7 +714,7 @@ class _TokenCardState extends State { case TokenCardBackVersion.burn: return _getBurnBackOfCard(balanceMap[kSelectedAddress!]!); case TokenCardBackVersion.mint: - return _getMintBackOfCard(balanceMap[kSelectedAddress!]!); + return _getMintBackOfCard(balanceMap[kSelectedAddress!]); case TokenCardBackVersion.transferOwnership: return _getTransferOwnershipBackOfCard(); } @@ -732,8 +722,8 @@ class _TokenCardState extends State { Widget _getTransferOwnershipButtonViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { - model.stream.listen((event) { + onViewModelReady: (TransferOwnershipBloc model) { + model.stream.listen((AccountBlockTemplate event) { _sendTransferSuccessfulNotification(); if (mounted) { setState(() { @@ -748,11 +738,11 @@ class _TokenCardState extends State { error, 'Error while trying to transfer token ownership', ); - }); + },); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, TransferOwnershipBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getTransferOwnershipButton(model); } @@ -765,7 +755,7 @@ class _TokenCardState extends State { return _getTransferOwnershipButton(model); }, ), - viewModelBuilder: () => TransferOwnershipBloc(), + viewModelBuilder: TransferOwnershipBloc.new, ); } diff --git a/lib/widgets/modular_widgets/token_widgets/token_favorite.dart b/lib/widgets/modular_widgets/token_widgets/token_favorite.dart index 85c238d2..b7e41f8e 100644 --- a/lib/widgets/modular_widgets/token_widgets/token_favorite.dart +++ b/lib/widgets/modular_widgets/token_widgets/token_favorite.dart @@ -10,14 +10,14 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TokenFavorite extends StatefulWidget { - final Token token; - final VoidCallback _tokenFavoritesCallback; const TokenFavorite( this.token, this._tokenFavoritesCallback, { - Key? key, - }) : super(key: key); + super.key, + }); + final Token token; + final VoidCallback _tokenFavoritesCallback; @override State createState() => _TokenFavoriteState(); @@ -36,13 +36,13 @@ class _TokenFavoriteState extends State { color: Colors.transparent, child: _showLoading ? const SyriusLoadingWidget( - size: 15.0, + size: 15, ) : IconButton( padding: EdgeInsets.zero, - splashRadius: 18.0, + splashRadius: 18, onPressed: _onFavoriteIconPressed, - iconSize: 30.0, + iconSize: 30, icon: Icon( _getFavoriteIcons(), color: _getIconColor(), @@ -63,13 +63,13 @@ class _TokenFavoriteState extends State { _showLoading = true; }); _favoriteTokensBox.add(widget.token.tokenStandard.toString()).then( - (value) async { + (int value) async { await sl.get().addNotification( WalletNotification( title: '${widget.token.name} token has been added to favorites', details: 'Token ${widget.token.name} with symbol ' '${widget.token.name} and ZTS ' - '${widget.token.tokenStandard.toString()}', + '${widget.token.tokenStandard}', timestamp: DateTime.now().millisecondsSinceEpoch, type: NotificationType.addedTokenFavourite, ), @@ -88,7 +88,7 @@ class _TokenFavoriteState extends State { ); } - void _removeTokenFromFavorites() async { + Future _removeTokenFromFavorites() async { setState(() { _showLoading = true; }); @@ -106,7 +106,7 @@ class _TokenFavoriteState extends State { 'from favorites', details: 'Token ${widget.token.name} with symbol ' '${widget.token.name} and ZTS ' - '${widget.token.tokenStandard.toString()}', + '${widget.token.tokenStandard}', timestamp: DateTime.now().millisecondsSinceEpoch, type: NotificationType.addedTokenFavourite, ), diff --git a/lib/widgets/modular_widgets/token_widgets/token_map.dart b/lib/widgets/modular_widgets/token_widgets/token_map.dart index ef75db13..d423811d 100644 --- a/lib/widgets/modular_widgets/token_widgets/token_map.dart +++ b/lib/widgets/modular_widgets/token_widgets/token_map.dart @@ -9,7 +9,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TokenMap extends StatefulWidget { - const TokenMap({Key? key}) : super(key: key); + const TokenMap({super.key}); @override State createState() { @@ -42,14 +42,14 @@ class _TokenMapState extends State { const Duration(seconds: 1), ) .distinct() - .listen((text) { + .listen((String text) { _bloc.onSearchInputChangedSink.add(text); }); - _pagingController.addPageRequestListener((pageKey) { + _pagingController.addPageRequestListener((int pageKey) { _bloc.onPageRequestSink.add(pageKey); }); _blocListingStateSubscription = _bloc.onNewListingState.listen( - (listingState) { + (InfiniteScrollBlocListingState listingState) { _pagingController.value = PagingState( nextPageKey: listingState.nextPageKey, error: listingState.error, @@ -75,9 +75,9 @@ class _TokenMapState extends State { Widget _getWidgetBody(TokenMapBloc bloc) { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( - children: [ + children: [ InputField( controller: _searchKeyWordController, hintText: 'Search token by symbol', @@ -101,7 +101,7 @@ class _TokenMapState extends State { crossAxisCount: 2, ), builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (_, token, __) => TokenCard( + itemBuilder: (_, Token token, __) => TokenCard( token, () { bloc.refreshResults(); diff --git a/lib/widgets/modular_widgets/token_widgets/token_stepper.dart b/lib/widgets/modular_widgets/token_widgets/token_stepper.dart index 83d03515..860e55b4 100644 --- a/lib/widgets/modular_widgets/token_widgets/token_stepper.dart +++ b/lib/widgets/modular_widgets/token_widgets/token_stepper.dart @@ -30,7 +30,7 @@ enum TokenStepperStep { } class TokenStepper extends StatefulWidget { - const TokenStepper({Key? key}) : super(key: key); + const TokenStepper({super.key}); @override State createState() { @@ -92,7 +92,7 @@ class _TokenStepperState extends State { Widget build(BuildContext context) { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -115,9 +115,8 @@ class _TokenStepperState extends State { actions: _actionMap, shortcuts: _shortcutMap, child: Column( - children: [ + children: [ Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Form( @@ -125,7 +124,7 @@ class _TokenStepperState extends State { autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( thisNode: _focusNodes[0], - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _tokenNameController, @@ -138,14 +137,14 @@ class _TokenStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ Expanded( child: Form( key: _tokenSymbolKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( thisNode: _focusNodes[1], - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _tokenSymbolController, @@ -162,7 +161,7 @@ class _TokenStepperState extends State { autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( thisNode: _focusNodes[2], - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _tokenDomainController, @@ -171,7 +170,7 @@ class _TokenStepperState extends State { ), ), const SizedBox( - height: 25.0, + height: 25, ), _getTokenDetailsActionButtons(), ], @@ -197,7 +196,7 @@ class _TokenStepperState extends State { activeColor: AppColors.ztsColor, currentStep: _currentStep.index, onStepTapped: (int index) {}, - steps: [ + steps: [ StepperUtils.getMaterialStep( stepTitle: 'Token creation: Plasma check', stepContent: _getPlasmaCheckFutureBuilder(), @@ -281,7 +280,7 @@ class _TokenStepperState extends State { Widget _getPlasmaCheckFutureBuilder() { return FutureBuilder( future: zenon!.embedded.plasma.get(Address.parse(kSelectedAddress!)), - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { @@ -295,28 +294,27 @@ class _TokenStepperState extends State { Widget _getPlasmaCheckBody(PlasmaInfo plasmaInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'More Plasma is required to perform complex transactions. Please fuse enough QSR before proceeding.', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( - height: 25.0, + height: 25, ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), ), const SizedBox( - width: 25.0, + width: 25, ), PlasmaIcon(plasmaInfo), ], ), const SizedBox( - height: 25.0, + height: 25, ), StepperButton( text: 'Next', @@ -344,16 +342,16 @@ class _TokenStepperState extends State { Widget _getIssueTokenStepContent(BuildContext context) { return Container( - margin: const EdgeInsets.only(bottom: 25.0), + margin: const EdgeInsets.only(bottom: 25), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Checkbox( activeColor: AppColors.ztsColor, value: _isUtility, - onChanged: (value) { + onChanged: (bool? value) { setState(() { _isUtility = value!; }); @@ -364,9 +362,9 @@ class _TokenStepperState extends State { style: Theme.of(context).inputDecorationTheme.hintStyle, ), const SizedBox( - width: 3.0, + width: 3, ), - const Icon(Icons.settings, size: 15.0, color: AppColors.ztsColor), + const Icon(Icons.settings, size: 15, color: AppColors.ztsColor), const StandardTooltipIcon( 'Token status: utility or ' 'non-utility (e.g. security token)', @@ -376,7 +374,7 @@ class _TokenStepperState extends State { ], ), Padding( - padding: const EdgeInsets.only(top: 25.0, bottom: 25.0, left: 15.0), + padding: const EdgeInsets.only(top: 25, bottom: 25, left: 15), child: DottedBorderInfoWidget( text: 'You will need to burn ' '${tokenZtsIssueFeeInZnn.addDecimals( @@ -387,18 +385,18 @@ class _TokenStepperState extends State { ), ), Padding( - padding: const EdgeInsets.only(left: 15.0), + padding: const EdgeInsets.only(left: 15), child: Row( - children: [ + children: [ Visibility( visible: (_createButtonKey.currentState?.btnState ?? ButtonState.idle) == ButtonState.idle, child: Row( - children: [ + children: [ _getStepBackButton(), const SizedBox( - width: 25.0, + width: 25, ), ], ), @@ -426,15 +424,15 @@ class _TokenStepperState extends State { AccountInfo accountInfo, ) { return Column( - children: [ + children: [ Padding( - padding: const EdgeInsets.only(bottom: 20.0), + padding: const EdgeInsets.only(bottom: 20), child: CustomSlider( activeColor: AppColors.ztsColor, - description: 'Number of decimals: ${_selectedNumDecimals.toInt()}', - startValue: 0.0, - min: 0.0, - maxValue: 18.0, + description: 'Number of decimals: $_selectedNumDecimals', + startValue: 0, + min: 0, + maxValue: 18, callback: (double value) { setState(() { _selectedNumDecimals = value.toInt(); @@ -445,9 +443,8 @@ class _TokenStepperState extends State { Visibility( visible: _isMintable, child: Container( - margin: const EdgeInsets.only(bottom: 15.0), + margin: const EdgeInsets.only(bottom: 15), child: Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Form( @@ -457,7 +454,7 @@ class _TokenStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _maxSupplyController.text, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _maxSupplyController, @@ -466,12 +463,11 @@ class _TokenStepperState extends State { ? (String? value) => InputValidators.correctValue( value, kBigP255m1, - _selectedNumDecimals.toInt(), + _selectedNumDecimals, kMinTokenTotalMaxSupply, canBeEqualToMin: true, ) - : (String? value) => - InputValidators.isMaxSupplyZero(value), + : InputValidators.isMaxSupplyZero, ), ), ), @@ -480,7 +476,6 @@ class _TokenStepperState extends State { ), ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Form( @@ -490,12 +485,12 @@ class _TokenStepperState extends State { inputFormatters: FormatUtils.getAmountTextInputFormatters( _totalSupplyController.text, ), - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _totalSupplyController, hintText: 'Total supply', - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, _isMintable ? _maxSupplyController.text.isNotEmpty @@ -503,7 +498,7 @@ class _TokenStepperState extends State { .extractDecimals(_selectedNumDecimals) : kBigP255m1 : kBigP255m1, - _selectedNumDecimals.toInt(), + _selectedNumDecimals, _isMintable ? BigInt.zero : kMinTokenTotalMaxSupply, canBeEqualToMin: true, ), @@ -520,12 +515,12 @@ class _TokenStepperState extends State { Row _getTokenMetricsActionButtons() { return Row( - children: [ + children: [ Row( - children: [ + children: [ _getStepBackButton(), const SizedBox( - width: 25.0, + width: 25, ), _getTokenMetricsContinueButton(), ], @@ -554,28 +549,27 @@ class _TokenStepperState extends State { Widget _getBody(BuildContext context, AccountInfo accountInfo) { return Stack( - children: [ + children: [ ListView( - children: [ + children: [ _getMaterialStepper(context, accountInfo), Padding( padding: const EdgeInsets.only( - top: 50.0, - bottom: 20.0, + top: 50, + bottom: 20, ), child: Visibility( visible: (_lastCompletedStep?.index ?? -1) == _numSteps - 1, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ StepperButton.icon( label: 'Create another Token', onPressed: _onCreateAnotherTokenPressed, iconData: Icons.refresh, - context: context, ), const SizedBox( - width: 80.0, + width: 80, ), _getViewTokensButton(), ], @@ -587,10 +581,10 @@ class _TokenStepperState extends State { Visibility( visible: (_lastCompletedStep?.index ?? -1) == _numSteps - 1, child: Positioned( - right: 50.0, + right: 50, child: SizedBox( - width: 400.0, - height: 400.0, + width: 400, + height: 400, child: Center( child: Lottie.asset( 'assets/lottie/ic_anim_zts.json', @@ -626,22 +620,19 @@ class _TokenStepperState extends State { _tokenDomainKey = GlobalKey(); _tokenDomainController = TextEditingController(); _lastCompletedStep = null; - setState(() { - _initStepperControllers(); - }); + setState(_initStepperControllers); } Widget _getTokenCreationStepContent(AccountInfo accountInfo) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( 'This will be your issuance address', style: Theme.of(context).textTheme.headlineSmall, ), kVerticalSpacing, Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: DisabledAddressField(_addressController), @@ -698,7 +689,7 @@ class _TokenStepperState extends State { void _onTokenMetricsContinuePressed() { if ((!_isMintable || _maxSupplyKey.currentState!.validate()) && _totalSupplyKey.currentState!.validate()) { - _tokenStepperData.decimals = _selectedNumDecimals.toInt(); + _tokenStepperData.decimals = _selectedNumDecimals; _tokenStepperData.totalSupply = _totalSupplyController.text.extractDecimals(_selectedNumDecimals); _tokenStepperData.isMintable = _isMintable; @@ -712,9 +703,9 @@ class _TokenStepperState extends State { Widget _getIssueTokenViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (IssueTokenBloc model) { model.stream.listen( - (response) { + (AccountBlockTemplate response) { _createButtonKey.currentState?.animateReverse(); _saveProgressAndNavigateToNextStep(TokenStepperStep.issueToken); }, @@ -727,8 +718,8 @@ class _TokenStepperState extends State { }, ); }, - builder: (_, model, __) => _getCreateButton(model), - viewModelBuilder: () => IssueTokenBloc(), + builder: (_, IssueTokenBloc model, __) => _getCreateButton(model), + viewModelBuilder: IssueTokenBloc.new, ); } @@ -746,10 +737,10 @@ class _TokenStepperState extends State { Widget _getTokenDetailsActionButtons() { return Row( - children: [ + children: [ _getStepBackButton(), const SizedBox( - width: 25.0, + width: 25, ), _getTokenDetailsContinueButton(), ], @@ -791,7 +782,7 @@ class _TokenStepperState extends State { ? InputValidators.correctValue( _maxSupplyController.text, kBigP255m1, - _selectedNumDecimals.toInt(), + _selectedNumDecimals, kMinTokenTotalMaxSupply, canBeEqualToMin: true, ) == @@ -801,9 +792,9 @@ class _TokenStepperState extends State { _totalSupplyController.text, _isMintable ? _maxSupplyController.text - .extractDecimals(_selectedNumDecimals.toInt()) + .extractDecimals(_selectedNumDecimals) : kBigP255m1, - _selectedNumDecimals.toInt(), + _selectedNumDecimals, _isMintable ? BigInt.zero : kMinTokenTotalMaxSupply, canBeEqualToMin: true, ) == @@ -811,13 +802,13 @@ class _TokenStepperState extends State { void _initFocusNodes(int length) => _focusNodes = List.generate( length, - (index) => FocusNode(), + (int index) => FocusNode(), ); void _changeFocusToNextNode() { - int indexOfFocusedNode = _focusNodes.indexOf( + final int indexOfFocusedNode = _focusNodes.indexOf( _focusNodes.firstWhere( - (node) => node.hasFocus, + (FocusNode node) => node.hasFocus, ), ); if (indexOfFocusedNode + 1 < _focusNodes.length) { @@ -829,16 +820,16 @@ class _TokenStepperState extends State { Widget _getTokenMintableAndBurnableStepContent() { return Column( - children: [ + children: [ Row( - children: [ + children: [ const SizedBox( - width: 20.0, + width: 20, ), Checkbox( activeColor: AppColors.ztsColor, value: _isMintable, - onChanged: (value) { + onChanged: (bool? value) { setState(() { if (value! && _totalSupplyController.text.isNotEmpty) { _maxSupplyController.text = _totalSupplyController.text; @@ -859,14 +850,14 @@ class _TokenStepperState extends State { ], ), Row( - children: [ + children: [ const SizedBox( - width: 20.0, + width: 20, ), Checkbox( activeColor: AppColors.ztsColor, value: _isBurnable, - onChanged: (value) { + onChanged: (bool? value) { setState(() { _isBurnable = value!; }); @@ -878,7 +869,7 @@ class _TokenStepperState extends State { ), const Icon( Icons.whatshot, - size: 15.0, + size: 15, color: AppColors.ztsColor, ), const StandardTooltipIcon( @@ -890,10 +881,10 @@ class _TokenStepperState extends State { ), kVerticalSpacing, Row( - children: [ + children: [ _getStepBackButton(), const SizedBox( - width: 25.0, + width: 25, ), StepperButton( text: 'Continue', diff --git a/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions.dart b/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions.dart index ab690491..b096f034 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions.dart @@ -13,12 +13,12 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; enum LatestTransactionsVersion { standard, dashboard, token } class LatestTransactions extends StatefulWidget { - final LatestTransactionsVersion version; const LatestTransactions({ - Key? key, + super.key, this.version = LatestTransactionsVersion.standard, - }) : super(key: key); + }); + final LatestTransactionsVersion version; @override State createState() => _LatestTransactionsState(); @@ -68,21 +68,15 @@ class _LatestTransactionsState extends State { bool isSelected, AccountBlock transactionBlock, ) { - AccountBlock infoBlock = + final AccountBlock infoBlock = BlockUtils.isReceiveBlock(transactionBlock.blockType) ? transactionBlock.pairedAccountBlock! : transactionBlock; - return [ - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.address, context), - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), - isSelected - ? InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), - flex: 2) - : InfiniteScrollTableCell.withText( + return [ + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) else WidgetUtils.getTextAddressTableCell(infoBlock.address, context), + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) else WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), + if (isSelected) InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), + flex: 2,) else InfiniteScrollTableCell.withText( context, infoBlock.hash.toShortString(), flex: 2, @@ -97,7 +91,7 @@ class _LatestTransactionsState extends State { infoBlock.token?.decimals ?? 0, ), tokenSymbol: infoBlock.token?.symbol ?? '', - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( formattedAmount, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -105,29 +99,29 @@ class _LatestTransactionsState extends State { ), ), ), - )), + ),), InfiniteScrollTableCell.withText( context, infoBlock.confirmationDetail?.momentumTimestamp == null ? 'Pending' : FormatUtils.formatData( - infoBlock.confirmationDetail!.momentumTimestamp * 1000), + infoBlock.confirmationDetail!.momentumTimestamp * 1000,), ), InfiniteScrollTableCell(Align( alignment: Alignment.centerLeft, - child: _getTransactionTypeIcon(transactionBlock))), + child: _getTransactionTypeIcon(transactionBlock),),), InfiniteScrollTableCell( Align( alignment: Alignment.centerLeft, child: infoBlock.token != null ? _showTokenSymbol(infoBlock) - : Container()), + : Container(),), ), ]; } List _getHeaderColumnsForTransferWidget() { - return [ + return [ InfiniteScrollTableHeaderColumn( columnName: 'Sender', onSortArrowsPressed: _onSortArrowsPressed, @@ -167,14 +161,14 @@ class _LatestTransactionsState extends State { return const Icon( MaterialCommunityIcons.arrow_up, color: AppColors.darkHintTextColor, - size: 20.0, + size: 20, ); } if (BlockUtils.isReceiveBlock(block.blockType)) { return const Icon( MaterialCommunityIcons.arrow_down, color: AppColors.lightHintTextColor, - size: 20.0, + size: 20, ); } return Text( @@ -194,7 +188,7 @@ class _LatestTransactionsState extends State { backgroundColor: ColorUtils.getTokenColor(block.tokenStandard), label: Text(block.token?.symbol ?? ''), side: BorderSide.none, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap)); + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,),); } void _onSortArrowsPressed(String columnName) { @@ -202,78 +196,71 @@ class _LatestTransactionsState extends State { case 'Sender': _sortAscending ? _transactions!.sort( - (a, b) => a.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.address.toString().compareTo( b.address.toString(), ), ) : _transactions!.sort( - (a, b) => b.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.address.toString().compareTo( a.address.toString(), ), ); - break; case 'Receiver': _sortAscending ? _transactions!.sort( - (a, b) => a.toAddress.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.toAddress.toString().compareTo( b.toAddress.toString(), ), ) - : _transactions!.sort((a, b) => - b.toAddress.toString().compareTo(a.toAddress.toString())); - break; + : _transactions!.sort((AccountBlock a, AccountBlock b) => + b.toAddress.toString().compareTo(a.toAddress.toString()),); case 'Hash': _sortAscending ? _transactions!.sort( - (a, b) => a.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.hash.toString().compareTo( b.hash.toString(), ), ) : _transactions!.sort( - (a, b) => b.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.hash.toString().compareTo( a.hash.toString(), ), ); - break; case 'Amount': _sortAscending - ? _transactions!.sort((a, b) => a.amount.compareTo(b.amount)) - : _transactions!.sort((a, b) => b.amount.compareTo(a.amount)); - break; + ? _transactions!.sort((AccountBlock a, AccountBlock b) => a.amount.compareTo(b.amount)) + : _transactions!.sort((AccountBlock a, AccountBlock b) => b.amount.compareTo(a.amount)); case 'Date': _sortAscending ? _transactions!.sort( - (a, b) => a.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => a.confirmationDetail!.momentumTimestamp.compareTo( b.confirmationDetail!.momentumTimestamp, - )) + ),) : _transactions!.sort( - (a, b) => b.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => b.confirmationDetail!.momentumTimestamp.compareTo( a.confirmationDetail!.momentumTimestamp, - )); - break; + ),); case 'Type': _sortAscending - ? _transactions!.sort((a, b) => a.blockType.compareTo(b.blockType)) - : _transactions!.sort((a, b) => b.blockType.compareTo(a.blockType)); - break; + ? _transactions!.sort((AccountBlock a, AccountBlock b) => a.blockType.compareTo(b.blockType)) + : _transactions!.sort((AccountBlock a, AccountBlock b) => b.blockType.compareTo(a.blockType)); case 'Assets': _sortAscending ? _transactions!.sort( - (a, b) => a.token!.symbol.compareTo(b.token!.symbol), + (AccountBlock a, AccountBlock b) => a.token!.symbol.compareTo(b.token!.symbol), ) : _transactions!.sort( - (a, b) => b.token!.symbol.compareTo(a.token!.symbol), + (AccountBlock a, AccountBlock b) => b.token!.symbol.compareTo(a.token!.symbol), ); - break; default: _sortAscending ? _transactions!.sort( - (a, b) => a.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.tokenStandard.toString().compareTo( b.tokenStandard.toString(), ), ) : _transactions!.sort( - (a, b) => b.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.tokenStandard.toString().compareTo( a.tokenStandard.toString(), ), ); @@ -292,7 +279,7 @@ class _LatestTransactionsState extends State { } List _getHeaderColumnsForDashboardWidget() { - return [ + return [ InfiniteScrollTableHeaderColumn( columnName: 'Sender', onSortArrowsPressed: _onSortArrowsPressed, @@ -321,15 +308,13 @@ class _LatestTransactionsState extends State { bool isSelected, AccountBlock transactionBlock, ) { - AccountBlock infoBlock = + final AccountBlock infoBlock = BlockUtils.isReceiveBlock(transactionBlock.blockType) ? transactionBlock.pairedAccountBlock! : transactionBlock; - return [ - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.address, context), + return [ + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) else WidgetUtils.getTextAddressTableCell(infoBlock.address, context), InfiniteScrollTableCell( Padding( padding: const EdgeInsets.only(right: 10), @@ -341,7 +326,7 @@ class _LatestTransactionsState extends State { infoBlock.token?.decimals ?? 0, ), tokenSymbol: infoBlock.token?.symbol ?? '', - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( formattedAmount, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -361,16 +346,15 @@ class _LatestTransactionsState extends State { ), InfiniteScrollTableCell( Align( - alignment: Alignment.center, - child: _getTransactionTypeIcon(transactionBlock)), + child: _getTransactionTypeIcon(transactionBlock),), ), InfiniteScrollTableCell( Align( alignment: Alignment.centerLeft, child: infoBlock.token != null ? _showTokenSymbol(infoBlock) - : Container()), - ) + : Container(),), + ), ]; } diff --git a/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions_transfer_widget.dart b/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions_transfer_widget.dart index 30f40160..b60fec95 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions_transfer_widget.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/latest_transactions/latest_transactions_transfer_widget.dart @@ -13,12 +13,12 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; enum LatestTransactionsVersion { standard, dashboard, token } class LatestTransactions extends StatefulWidget { - final LatestTransactionsVersion version; const LatestTransactions({ - Key? key, + super.key, this.version = LatestTransactionsVersion.standard, - }) : super(key: key); + }); + final LatestTransactionsVersion version; @override State createState() => _LatestTransactionsState(); @@ -68,21 +68,15 @@ class _LatestTransactionsState extends State { bool isSelected, AccountBlock transactionBlock, ) { - AccountBlock infoBlock = + final AccountBlock infoBlock = BlockUtils.isReceiveBlock(transactionBlock.blockType) ? transactionBlock.pairedAccountBlock! : transactionBlock; - return [ - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.address, context), - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), - isSelected - ? InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), - flex: 2) - : InfiniteScrollTableCell.withText( + return [ + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) else WidgetUtils.getTextAddressTableCell(infoBlock.address, context), + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) else WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), + if (isSelected) InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), + flex: 2,) else InfiniteScrollTableCell.withText( context, infoBlock.hash.toShortString(), flex: 2, @@ -97,7 +91,7 @@ class _LatestTransactionsState extends State { infoBlock.token?.decimals ?? 0, ), tokenSymbol: infoBlock.token?.symbol ?? '', - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( formattedAmount, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -105,13 +99,13 @@ class _LatestTransactionsState extends State { ), ), ), - )), + ),), InfiniteScrollTableCell.withText( context, infoBlock.confirmationDetail?.momentumTimestamp == null ? 'Pending' : _formatData( - infoBlock.confirmationDetail!.momentumTimestamp * 1000), + infoBlock.confirmationDetail!.momentumTimestamp * 1000,), ), InfiniteScrollTableCell(_getTransactionTypeIcon(transactionBlock)), InfiniteScrollTableCell( @@ -121,7 +115,7 @@ class _LatestTransactionsState extends State { } List _getHeaderColumnsForTransferWidget() { - return [ + return [ InfiniteScrollTableHeaderColumn( columnName: 'Sender', onSortArrowsPressed: _onSortArrowsPressed, @@ -158,7 +152,7 @@ class _LatestTransactionsState extends State { } String _formatData(int transactionMillis) { - int currentMillis = DateTime.now().millisecondsSinceEpoch; + final int currentMillis = DateTime.now().millisecondsSinceEpoch; if (currentMillis - transactionMillis <= const Duration(days: 1).inMilliseconds) { return _formatDataShort(currentMillis - transactionMillis); @@ -167,7 +161,7 @@ class _LatestTransactionsState extends State { } String _formatDataShort(int i) { - Duration duration = Duration(milliseconds: i); + final Duration duration = Duration(milliseconds: i); if (duration.inHours > 0) { return '${duration.inHours} h ago'; } @@ -182,14 +176,14 @@ class _LatestTransactionsState extends State { return const Icon( MaterialCommunityIcons.arrow_up, color: AppColors.darkHintTextColor, - size: 20.0, + size: 20, ); } if (BlockUtils.isReceiveBlock(block.blockType)) { return const Icon( MaterialCommunityIcons.arrow_down, color: AppColors.lightHintTextColor, - size: 20.0, + size: 20, ); } return Text( @@ -209,7 +203,7 @@ class _LatestTransactionsState extends State { backgroundColor: ColorUtils.getTokenColor(block.tokenStandard), label: Text(block.token?.symbol ?? ''), side: BorderSide.none, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap)); + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,),); } void _onSortArrowsPressed(String columnName) { @@ -217,78 +211,71 @@ class _LatestTransactionsState extends State { case 'Sender': _sortAscending ? _transactions!.sort( - (a, b) => a.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.address.toString().compareTo( b.address.toString(), ), ) : _transactions!.sort( - (a, b) => b.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.address.toString().compareTo( a.address.toString(), ), ); - break; case 'Receiver': _sortAscending ? _transactions!.sort( - (a, b) => a.toAddress.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.toAddress.toString().compareTo( b.toAddress.toString(), ), ) - : _transactions!.sort((a, b) => - b.toAddress.toString().compareTo(a.toAddress.toString())); - break; + : _transactions!.sort((AccountBlock a, AccountBlock b) => + b.toAddress.toString().compareTo(a.toAddress.toString()),); case 'Hash': _sortAscending ? _transactions!.sort( - (a, b) => a.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.hash.toString().compareTo( b.hash.toString(), ), ) : _transactions!.sort( - (a, b) => b.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.hash.toString().compareTo( a.hash.toString(), ), ); - break; case 'Amount': _sortAscending - ? _transactions!.sort((a, b) => a.amount.compareTo(b.amount)) - : _transactions!.sort((a, b) => b.amount.compareTo(a.amount)); - break; + ? _transactions!.sort((AccountBlock a, AccountBlock b) => a.amount.compareTo(b.amount)) + : _transactions!.sort((AccountBlock a, AccountBlock b) => b.amount.compareTo(a.amount)); case 'Date': _sortAscending ? _transactions!.sort( - (a, b) => a.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => a.confirmationDetail!.momentumTimestamp.compareTo( b.confirmationDetail!.momentumTimestamp, - )) + ),) : _transactions!.sort( - (a, b) => b.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => b.confirmationDetail!.momentumTimestamp.compareTo( a.confirmationDetail!.momentumTimestamp, - )); - break; + ),); case 'Type': _sortAscending - ? _transactions!.sort((a, b) => a.blockType.compareTo(b.blockType)) - : _transactions!.sort((a, b) => b.blockType.compareTo(a.blockType)); - break; + ? _transactions!.sort((AccountBlock a, AccountBlock b) => a.blockType.compareTo(b.blockType)) + : _transactions!.sort((AccountBlock a, AccountBlock b) => b.blockType.compareTo(a.blockType)); case 'Assets': _sortAscending ? _transactions!.sort( - (a, b) => a.token!.symbol.compareTo(b.token!.symbol), + (AccountBlock a, AccountBlock b) => a.token!.symbol.compareTo(b.token!.symbol), ) : _transactions!.sort( - (a, b) => b.token!.symbol.compareTo(a.token!.symbol), + (AccountBlock a, AccountBlock b) => b.token!.symbol.compareTo(a.token!.symbol), ); - break; default: _sortAscending ? _transactions!.sort( - (a, b) => a.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.tokenStandard.toString().compareTo( b.tokenStandard.toString(), ), ) : _transactions!.sort( - (a, b) => b.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.tokenStandard.toString().compareTo( a.tokenStandard.toString(), ), ); @@ -307,7 +294,7 @@ class _LatestTransactionsState extends State { } List _getHeaderColumnsForDashboardWidget() { - return [ + return [ InfiniteScrollTableHeaderColumn( columnName: 'Sender', onSortArrowsPressed: _onSortArrowsPressed, @@ -337,15 +324,13 @@ class _LatestTransactionsState extends State { bool isSelected, AccountBlock transactionBlock, ) { - AccountBlock infoBlock = + final AccountBlock infoBlock = BlockUtils.isReceiveBlock(transactionBlock.blockType) ? transactionBlock.pairedAccountBlock! : transactionBlock; - return [ - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.address, context), + return [ + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) else WidgetUtils.getTextAddressTableCell(infoBlock.address, context), InfiniteScrollTableCell( Padding( padding: const EdgeInsets.only(right: 10), @@ -357,7 +342,7 @@ class _LatestTransactionsState extends State { infoBlock.token?.decimals ?? 0, ), tokenSymbol: infoBlock.token?.symbol ?? '', - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( formattedAmount, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -378,7 +363,7 @@ class _LatestTransactionsState extends State { InfiniteScrollTableCell(_getTransactionTypeIcon(transactionBlock)), InfiniteScrollTableCell( infoBlock.token != null ? _showTokenSymbol(infoBlock) : Container(), - ) + ), ]; } diff --git a/lib/widgets/modular_widgets/transfer_widgets/pending_transactions/pending_transactions.dart b/lib/widgets/modular_widgets/transfer_widgets/pending_transactions/pending_transactions.dart index f72c973d..2bcd6102 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/pending_transactions/pending_transactions.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/pending_transactions/pending_transactions.dart @@ -14,8 +14,8 @@ import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PendingTransactions extends StatefulWidget { const PendingTransactions({ - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _PendingTransactionsState(); @@ -53,21 +53,15 @@ class _PendingTransactionsState extends State { _getCellsForPendingTransactions(isSelected, transaction); List _getCellsForPendingTransactions( - bool isSelected, AccountBlock transaction) { - AccountBlock infoBlock = BlockUtils.isReceiveBlock(transaction.blockType) + bool isSelected, AccountBlock transaction,) { + final AccountBlock infoBlock = BlockUtils.isReceiveBlock(transaction.blockType) ? transaction.pairedAccountBlock! : transaction; - return [ - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.address, context), - isSelected - ? WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) - : WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), - isSelected - ? InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), - flex: 2) - : InfiniteScrollTableCell.withText( + return [ + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.address, context) else WidgetUtils.getTextAddressTableCell(infoBlock.address, context), + if (isSelected) WidgetUtils.getMarqueeAddressTableCell(infoBlock.toAddress, context) else WidgetUtils.getTextAddressTableCell(infoBlock.toAddress, context), + if (isSelected) InfiniteScrollTableCell.withMarquee(infoBlock.hash.toString(), + flex: 2,) else InfiniteScrollTableCell.withText( context, infoBlock.hash.toShortString(), flex: 2, @@ -82,7 +76,7 @@ class _PendingTransactionsState extends State { infoBlock.token?.decimals ?? 0, ), tokenSymbol: infoBlock.token?.symbol ?? '', - builder: (formattedAmount, tokenSymbol) => Text( + builder: (String formattedAmount, String tokenSymbol) => Text( formattedAmount, style: Theme.of(context).textTheme.titleMedium!.copyWith( color: AppColors.subtitleColor, @@ -90,29 +84,29 @@ class _PendingTransactionsState extends State { ), ), ), - )), + ),), InfiniteScrollTableCell.withText( context, infoBlock.confirmationDetail?.momentumTimestamp == null ? 'Pending' : FormatUtils.formatData( - infoBlock.confirmationDetail!.momentumTimestamp * 1000), + infoBlock.confirmationDetail!.momentumTimestamp * 1000,), ), InfiniteScrollTableCell( Align( alignment: Alignment.centerLeft, child: infoBlock.token != null ? _showTokenSymbol(infoBlock) - : Container()), + : Container(),), ), InfiniteScrollTableCell( - _getReceiveContainer(isSelected, infoBlock, _bloc)), + _getReceiveContainer(isSelected, infoBlock, _bloc),), ]; } List _getHeaderColumnsForPendingTransactions() { - return [ + return [ InfiniteScrollTableHeaderColumn( columnName: 'Sender', onSortArrowsPressed: _onSortArrowsPressed, @@ -151,73 +145,67 @@ class _PendingTransactionsState extends State { case 'Sender': _sortAscending ? _transactions!.sort( - (a, b) => a.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.address.toString().compareTo( b.address.toString(), ), ) : _transactions!.sort( - (a, b) => b.address.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.address.toString().compareTo( a.address.toString(), ), ); - break; case 'Receiver': _sortAscending ? _transactions!.sort( - (a, b) => a.toAddress.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.toAddress.toString().compareTo( b.toAddress.toString(), ), ) - : _transactions!.sort((a, b) => - b.toAddress.toString().compareTo(a.toAddress.toString())); - break; + : _transactions!.sort((AccountBlock a, AccountBlock b) => + b.toAddress.toString().compareTo(a.toAddress.toString()),); case 'Hash': _sortAscending ? _transactions!.sort( - (a, b) => a.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.hash.toString().compareTo( b.hash.toString(), ), ) : _transactions!.sort( - (a, b) => b.hash.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.hash.toString().compareTo( a.hash.toString(), ), ); - break; case 'Amount': _sortAscending - ? _transactions!.sort((a, b) => a.amount.compareTo(b.amount)) - : _transactions!.sort((a, b) => b.amount.compareTo(a.amount)); - break; + ? _transactions!.sort((AccountBlock a, AccountBlock b) => a.amount.compareTo(b.amount)) + : _transactions!.sort((AccountBlock a, AccountBlock b) => b.amount.compareTo(a.amount)); case 'Date': _sortAscending ? _transactions!.sort( - (a, b) => a.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => a.confirmationDetail!.momentumTimestamp.compareTo( b.confirmationDetail!.momentumTimestamp, - )) + ),) : _transactions!.sort( - (a, b) => b.confirmationDetail!.momentumTimestamp.compareTo( + (AccountBlock a, AccountBlock b) => b.confirmationDetail!.momentumTimestamp.compareTo( a.confirmationDetail!.momentumTimestamp, - )); - break; + ),); case 'Assets': _sortAscending ? _transactions!.sort( - (a, b) => a.token!.symbol.compareTo(b.token!.symbol), + (AccountBlock a, AccountBlock b) => a.token!.symbol.compareTo(b.token!.symbol), ) : _transactions!.sort( - (a, b) => b.token!.symbol.compareTo(a.token!.symbol), + (AccountBlock a, AccountBlock b) => b.token!.symbol.compareTo(a.token!.symbol), ); - break; default: _sortAscending ? _transactions!.sort( - (a, b) => a.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => a.tokenStandard.toString().compareTo( b.tokenStandard.toString(), ), ) : _transactions!.sort( - (a, b) => b.tokenStandard.toString().compareTo( + (AccountBlock a, AccountBlock b) => b.tokenStandard.toString().compareTo( a.tokenStandard.toString(), ), ); @@ -236,7 +224,7 @@ class _PendingTransactionsState extends State { ) { return Align( alignment: Alignment.centerLeft, - child: _getReceiveButtonViewModel(model, isSelected, transaction)); + child: _getReceiveButtonViewModel(model, isSelected, transaction),); } Widget _getReceiveButtonViewModel( @@ -245,24 +233,24 @@ class _PendingTransactionsState extends State { AccountBlock transactionItem, ) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (ReceiveTransactionBloc model) { model.stream.listen( - (event) { + (AccountBlockTemplate? event) { if (event != null) { transactionModel.refreshResults(); } }, onError: (error) async { await NotificationUtils.sendNotificationError( - error, 'Error while receiving transaction'); + error, 'Error while receiving transaction',); }, ); }, - builder: (_, model, __) => _getReceiveButton( + builder: (_, ReceiveTransactionBloc model, __) => _getReceiveButton( model, transactionItem.hash.toString(), ), - viewModelBuilder: () => ReceiveTransactionBloc(), + viewModelBuilder: ReceiveTransactionBloc.new, ); } @@ -271,7 +259,7 @@ class _PendingTransactionsState extends State { String transactionHash, ) { return MaterialIconButton( - size: 25.0, + size: 25, iconData: Icons.download_for_offline, onPressed: () { _onReceivePressed(model, transactionHash); @@ -291,7 +279,7 @@ class _PendingTransactionsState extends State { backgroundColor: ColorUtils.getTokenColor(block.tokenStandard), label: Text(block.token?.symbol ?? ''), side: BorderSide.none, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap)); + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,),); } @override diff --git a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_large.dart b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_large.dart index 88adeb04..817f4401 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_large.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_large.dart @@ -12,14 +12,13 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ReceiveLargeCard extends StatefulWidget { - final bool? extendIcon; - final VoidCallback onCollapseClicked; const ReceiveLargeCard({ - Key? key, + required this.onCollapseClicked, super.key, this.extendIcon, - required this.onCollapseClicked, - }) : super(key: key); + }); + final bool? extendIcon; + final VoidCallback onCollapseClicked; @override State createState() => _ReceiveLargeCardState(); @@ -36,7 +35,7 @@ class _ReceiveLargeCardState extends State { String? _selectedSelfAddress = kSelectedAddress; Token _selectedToken = kDualCoin.first; - final List _tokens = []; + final List _tokens = []; final Box _recipientAddressBox = Hive.box(kRecipientAddressBox); @@ -55,14 +54,14 @@ class _ReceiveLargeCardState extends State { title: 'Receive', titleFontSize: Theme.of(context).textTheme.headlineSmall!.fontSize, description: 'Manage receiving funds', - childBuilder: () => _getTokensStreamBuilder(), + childBuilder: _getTokensStreamBuilder, ); } Widget _getTokensStreamBuilder() { return StreamBuilder?>( stream: _tokensBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -82,8 +81,8 @@ class _ReceiveLargeCardState extends State { return Container( margin: const EdgeInsets.only( - right: 20.0, - top: 20.0, + right: 20, + top: 20, ), child: Form( key: _formKey, @@ -96,7 +95,7 @@ class _ReceiveLargeCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox( - width: 20.0, + width: 20, ), ReceiveQrImage( data: _getQrString(), @@ -105,11 +104,10 @@ class _ReceiveLargeCardState extends State { context: context, ), const SizedBox( - width: 20.0, + width: 20, ), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ @@ -128,12 +126,12 @@ class _ReceiveLargeCardState extends State { key: _amountKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, kBigP255m1, _selectedToken.decimals, - BigInt.zero), - onChanged: (value) => setState(() {}), + BigInt.zero,), + onChanged: (String value) => setState(() {}), inputFormatters: FormatUtils.getAmountTextInputFormatters( _amountController.text, @@ -142,10 +140,10 @@ class _ReceiveLargeCardState extends State { suffixIcon: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ _getCoinDropdown(), const SizedBox( - width: 15.0, + width: 15, ), ], ), @@ -158,7 +156,6 @@ class _ReceiveLargeCardState extends State { ], ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ Visibility( visible: widget.extendIcon!, @@ -198,7 +195,7 @@ class _ReceiveLargeCardState extends State { Widget _getDefaultAddressDropdown() { return AddressesDropdown( _selectedSelfAddress, - (value) => setState( + (String? value) => setState( () { _selectedToken = kDualCoin.first; _selectedSelfAddress = value; @@ -211,7 +208,7 @@ class _ReceiveLargeCardState extends State { Widget _getCoinDropdown() => CoinDropdown( _tokens, _selectedToken, - (value) { + (Token? value) { if (_selectedToken.tokenStandard != value!.tokenStandard) { setState( () { @@ -227,7 +224,7 @@ class _ReceiveLargeCardState extends State { _tokens.clear(); } _tokens.addAll(kDualCoin); - for (var element in tokens) { + for (final Token element in tokens) { if (!_tokens.contains(element)) { _tokens.add(element); } diff --git a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_medium.dart b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_medium.dart index 75031601..ef6815c1 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_medium.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_medium.dart @@ -12,10 +12,9 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ReceiveMediumCard extends StatefulWidget { - final VoidCallback onExpandClicked; - const ReceiveMediumCard({Key? key, required this.onExpandClicked}) - : super(key: key); + const ReceiveMediumCard({required this.onExpandClicked, super.key}); + final VoidCallback onExpandClicked; @override State createState() => _ReceiveMediumCardState(); @@ -31,7 +30,7 @@ class _ReceiveMediumCardState extends State { Token _selectedToken = kDualCoin.first; - final List _tokens = []; + final List _tokens = []; final GlobalKey _amountKey = GlobalKey(); @@ -52,14 +51,14 @@ class _ReceiveMediumCardState extends State { title: 'Receive', titleFontSize: Theme.of(context).textTheme.headlineSmall!.fontSize, description: 'Manage receiving funds', - childBuilder: () => _getTokensStreamBuilder(), + childBuilder: _getTokensStreamBuilder, ); } Widget _getTokensStreamBuilder() { return StreamBuilder?>( stream: _tokensBloc.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -70,7 +69,7 @@ class _ReceiveMediumCardState extends State { return const SyriusLoadingWidget(); } return const SyriusLoadingWidget(); - }); + },); } Widget _getWidgetBody(BuildContext context, List tokens) { @@ -78,8 +77,8 @@ class _ReceiveMediumCardState extends State { return Container( margin: const EdgeInsets.only( - right: 20.0, - top: 20.0, + right: 20, + top: 20, ), child: Form( key: _formKey, @@ -92,7 +91,7 @@ class _ReceiveMediumCardState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const SizedBox( - width: 20.0, + width: 20, ), ReceiveQrImage( data: _getQrString(), @@ -101,14 +100,14 @@ class _ReceiveMediumCardState extends State { context: context, ), const SizedBox( - width: 20.0, + width: 20, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - children: [ + children: [ Expanded( child: _getDefaultAddressDropdown(), ), @@ -123,12 +122,12 @@ class _ReceiveMediumCardState extends State { key: _amountKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, kBigP255m1, _selectedToken.decimals, - BigInt.zero), - onChanged: (value) => setState(() {}), + BigInt.zero,), + onChanged: (String value) => setState(() {}), inputFormatters: FormatUtils.getAmountTextInputFormatters( _amountController.text, @@ -137,10 +136,10 @@ class _ReceiveMediumCardState extends State { suffixIcon: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ _getCoinDropdown(), const SizedBox( - width: 15.0, + width: 15, ), ], ), @@ -153,10 +152,9 @@ class _ReceiveMediumCardState extends State { ], ), const SizedBox( - height: 35.0, + height: 35, ), Row( - mainAxisAlignment: MainAxisAlignment.start, children: [ TransferToggleCardSizeButton( onPressed: widget.onExpandClicked, @@ -193,7 +191,7 @@ class _ReceiveMediumCardState extends State { Widget _getDefaultAddressDropdown() { return AddressesDropdown( _selectedSelfAddress, - (value) => setState(() { + (String? value) => setState(() { _selectedSelfAddress = value; }), ); @@ -202,7 +200,7 @@ class _ReceiveMediumCardState extends State { Widget _getCoinDropdown() => CoinDropdown( _tokens.toList(), _selectedToken, - (value) { + (Token? value) { if (_selectedToken != value) { setState( () { @@ -218,7 +216,7 @@ class _ReceiveMediumCardState extends State { _tokens.clear(); } _tokens.addAll(kDualCoin); - for (var element in tokens) { + for (final Token element in tokens) { if (!_tokens.contains(element)) { _tokens.add(element); } diff --git a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_small.dart b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_small.dart index d1a9a507..5cc279d6 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/receive/receive_small.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/receive/receive_small.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class ReceiveSmallCard extends StatefulWidget { - final VoidCallback onPressed; const ReceiveSmallCard( this.onPressed, { - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onPressed; @override State createState() => _ReceiveSmallCardState(); @@ -24,20 +24,19 @@ class _ReceiveSmallCardState extends State { decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular( - 15.0, + 15, ), ), child: const Column( - crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( SimpleLineIcons.arrow_down_circle, - size: 60.0, + size: 60, color: AppColors.lightHintTextColor, ), SizedBox( - height: 20.0, + height: 20, ), TransferIconLegend( legendText: '● Receive', diff --git a/lib/widgets/modular_widgets/transfer_widgets/send/send_large.dart b/lib/widgets/modular_widgets/transfer_widgets/send/send_large.dart index 536422a6..1fce39f7 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/send/send_large.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/send/send_large.dart @@ -17,16 +17,16 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SendLargeCard extends StatefulWidget { - final double? cardWidth; - final bool? extendIcon; - final VoidCallback? onCollapsePressed; const SendLargeCard({ - Key? key, + super.key, this.cardWidth, this.extendIcon, this.onCollapsePressed, - }) : super(key: key); + }); + final double? cardWidth; + final bool? extendIcon; + final VoidCallback? onCollapsePressed; @override State createState() => _SendLargeCardState(); @@ -41,7 +41,7 @@ class _SendLargeCardState extends State { final GlobalKey _sendPaymentButtonKey = GlobalKey(); - final List _tokensWithBalance = []; + final List _tokensWithBalance = []; Token _selectedToken = kDualCoin.first; @@ -60,14 +60,14 @@ class _SendLargeCardState extends State { title: 'Send', titleFontSize: Theme.of(context).textTheme.headlineSmall!.fontSize, description: 'Manage sending funds', - childBuilder: () => _getBalanceStreamBuilder(), + childBuilder: _getBalanceStreamBuilder, ); } Widget _getBalanceStreamBuilder() { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -91,23 +91,23 @@ class _SendLargeCardState extends State { Widget _getBody(BuildContext context, AccountInfo accountInfo) { return Container( margin: const EdgeInsets.only( - left: 20.0, - top: 20.0, + left: 20, + top: 20, ), child: ListView( shrinkWrap: true, children: [ Container( - margin: const EdgeInsets.only(right: 20.0), + margin: const EdgeInsets.only(right: 20), child: Form( key: _recipientKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _recipientController, - validator: (value) => InputValidators.checkAddress(value), + validator: InputValidators.checkAddress, suffixIcon: RawMaterialButton( shape: const CircleBorder(), onPressed: () { @@ -119,12 +119,12 @@ class _SendLargeCardState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'Recipient Address', ), @@ -137,25 +137,25 @@ class _SendLargeCardState extends State { Expanded( flex: 8, child: Container( - margin: const EdgeInsets.only(right: 20.0), + margin: const EdgeInsets.only(right: 20), child: Form( key: _amountKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( _amountController.text, ), controller: _amountController, - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, accountInfo.getBalance( _selectedToken.tokenStandard, ), _selectedToken.decimals, - BigInt.zero), + BigInt.zero,), suffixIcon: _getAmountSuffix(accountInfo), hintText: 'Amount', ), @@ -165,17 +165,17 @@ class _SendLargeCardState extends State { ], ), const SizedBox( - height: 5.0, + height: 5, ), Padding( - padding: const EdgeInsets.only(left: 10.0), + padding: const EdgeInsets.only(left: 10), child: Text( 'Send from', style: Theme.of(context).inputDecorationTheme.hintStyle, ), ), const SizedBox( - height: 5.0, + height: 5, ), Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -184,22 +184,22 @@ class _SendLargeCardState extends State { child: _getDefaultAddressDropdown(), ), Container( - width: 10.0, + width: 10, ), _getSendPaymentViewModel(accountInfo), const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Padding( padding: const EdgeInsets.only( - left: 10.0, - top: 10.0, + left: 10, + top: 10, ), child: AvailableBalance( _selectedToken, @@ -212,9 +212,9 @@ class _SendLargeCardState extends State { onPressed: widget.onCollapsePressed, iconData: Icons.navigate_before, ), - ) + ), ], - ) + ), ], ), ); @@ -239,17 +239,17 @@ class _SendLargeCardState extends State { return Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, - children: [ + children: [ _getCoinDropdown(), const SizedBox( - width: 5.0, + width: 5, ), AmountSuffixMaxWidget( onPressed: () => _onMaxPressed(accountInfo), context: context, ), const SizedBox( - width: 15.0, + width: 15, ), ], ); @@ -261,7 +261,6 @@ class _SendLargeCardState extends State { fromAddress: _selectedSelfAddress, toAddress: _recipientController.text, amount: _amountController.text.extractDecimals(_selectedToken.decimals), - data: null, token: _selectedToken, ); } @@ -269,7 +268,7 @@ class _SendLargeCardState extends State { Widget _getDefaultAddressDropdown() { return AddressesDropdown( _selectedSelfAddress, - (value) => setState( + (String? value) => setState( () { _selectedSelfAddress = value; _selectedToken = kDualCoin.first; @@ -284,7 +283,7 @@ class _SendLargeCardState extends State { Widget _getCoinDropdown() => CoinDropdown( _tokensWithBalance, _selectedToken, - (value) { + (Token? value) { if (_selectedToken != value) { setState( () { @@ -296,7 +295,7 @@ class _SendLargeCardState extends State { ); void _onMaxPressed(AccountInfo accountInfo) { - BigInt maxBalance = accountInfo.getBalance( + final BigInt maxBalance = accountInfo.getBalance( _selectedToken.tokenStandard, ); @@ -312,9 +311,9 @@ class _SendLargeCardState extends State { Widget _getSendPaymentViewModel(AccountInfo? accountInfo) { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (SendPaymentBloc model) { model.stream.listen( - (event) async { + (AccountBlockTemplate? event) async { if (event is AccountBlockTemplate) { await _sendConfirmationNotification(); setState(() { @@ -332,21 +331,21 @@ class _SendLargeCardState extends State { }, ); }, - builder: (_, model, __) => SendPaymentButton( + builder: (_, SendPaymentBloc model, __) => SendPaymentButton( onPressed: _hasBalance(accountInfo!) && _isInputValid(accountInfo) ? () => _onSendPaymentPressed(model) : null, - minimumSize: const Size(50.0, 48.0), + minimumSize: const Size(50, 48), key: _sendPaymentButtonKey, ), - viewModelBuilder: () => SendPaymentBloc(), + viewModelBuilder: SendPaymentBloc.new, ); } Future _sendErrorNotification(error) async { await NotificationUtils.sendNotificationError( error, - 'Couldn\'t send ${_amountController.text} ' + "Couldn't send ${_amountController.text} " '${_selectedToken.symbol} ' 'to ${_recipientController.text}', ); @@ -361,7 +360,6 @@ class _SendLargeCardState extends State { details: 'Sent ${_amountController.text} ${_selectedToken.symbol} ' 'from ${ZenonAddressUtils.getLabel(_selectedSelfAddress!)} to ${ZenonAddressUtils.getLabel(_recipientController.text)}', type: NotificationType.paymentSent, - id: null, ), ); } @@ -373,7 +371,7 @@ class _SendLargeCardState extends State { BigInt.zero; void _addTokensWithBalance(AccountInfo accountInfo) { - for (var balanceInfo in accountInfo.balanceInfoList!) { + for (final BalanceInfoListItem balanceInfo in accountInfo.balanceInfoList!) { if (balanceInfo.balance! > BigInt.zero && !_tokensWithBalance.contains(balanceInfo.token)) { _tokensWithBalance.add(balanceInfo.token); diff --git a/lib/widgets/modular_widgets/transfer_widgets/send/send_medium.dart b/lib/widgets/modular_widgets/transfer_widgets/send/send_medium.dart index ed4dc6e5..a6444467 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/send/send_medium.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/send/send_medium.dart @@ -17,12 +17,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SendMediumCard extends StatefulWidget { - final VoidCallback onExpandClicked; const SendMediumCard({ required this.onExpandClicked, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onExpandClicked; @override State createState() => _SendMediumCardState(); @@ -37,7 +37,7 @@ class _SendMediumCardState extends State { Token _selectedToken = kDualCoin.first; - final List _tokensWithBalance = []; + final List _tokensWithBalance = []; final FocusNode _recipientFocusNode = FocusNode(); @@ -56,14 +56,14 @@ class _SendMediumCardState extends State { title: 'Send', titleFontSize: Theme.of(context).textTheme.headlineSmall!.fontSize, description: 'Manage sending funds', - childBuilder: () => _getBalanceStreamBuilder(), + childBuilder: _getBalanceStreamBuilder, ); } Widget _getBalanceStreamBuilder() { return StreamBuilder?>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot?> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } @@ -87,23 +87,23 @@ class _SendMediumCardState extends State { Widget _getBody(BuildContext context, AccountInfo accountInfo) { return Container( margin: const EdgeInsets.only( - left: 20.0, - top: 20.0, + left: 20, + top: 20, ), child: ListView( shrinkWrap: true, children: [ Container( - margin: const EdgeInsets.only(right: 20.0), + margin: const EdgeInsets.only(right: 20), child: Form( key: _recipientKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, thisNode: _recipientFocusNode, - validator: (value) => InputValidators.checkAddress(value), + validator: InputValidators.checkAddress, controller: _recipientController, suffixIcon: RawMaterialButton( shape: const CircleBorder(), @@ -116,12 +116,12 @@ class _SendMediumCardState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'Recipient Address', ), @@ -129,18 +129,18 @@ class _SendMediumCardState extends State { ), kVerticalSpacing, Container( - margin: const EdgeInsets.only(right: 20.0), + margin: const EdgeInsets.only(right: 20), child: Form( key: _amountKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( _amountController.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, accountInfo.getBalance( _selectedToken.tokenStandard, @@ -195,7 +195,6 @@ class _SendMediumCardState extends State { fromAddress: kSelectedAddress, toAddress: _recipientController.text, amount: _amountController.text.extractDecimals(_selectedToken.decimals), - data: null, token: _selectedToken, ); } @@ -204,17 +203,17 @@ class _SendMediumCardState extends State { return Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, - children: [ + children: [ _getCoinDropdown(), const SizedBox( - width: 5.0, + width: 5, ), AmountSuffixMaxWidget( onPressed: () => _onMaxPressed(accountInfo), context: context, ), const SizedBox( - width: 15.0, + width: 15, ), ], ); @@ -223,7 +222,7 @@ class _SendMediumCardState extends State { Widget _getCoinDropdown() => CoinDropdown( _tokensWithBalance, _selectedToken, - (value) { + (Token? value) { if (_selectedToken != value) { setState( () { @@ -235,7 +234,7 @@ class _SendMediumCardState extends State { ); void _onMaxPressed(AccountInfo accountInfo) { - BigInt maxBalance = accountInfo.getBalance( + final BigInt maxBalance = accountInfo.getBalance( _selectedToken.tokenStandard, ); @@ -252,9 +251,9 @@ class _SendMediumCardState extends State { Widget _getSendPaymentViewModel(AccountInfo? accountInfo) { return ViewModelBuilder.reactive( fireOnViewModelReadyOnce: true, - onViewModelReady: (model) { + onViewModelReady: (SendPaymentBloc model) { model.stream.listen( - (event) async { + (AccountBlockTemplate? event) async { if (event is AccountBlockTemplate) { await _sendConfirmationNotification(); setState(() { @@ -272,20 +271,20 @@ class _SendMediumCardState extends State { }, ); }, - builder: (_, model, __) => SendPaymentButton( + builder: (_, SendPaymentBloc model, __) => SendPaymentButton( onPressed: _hasBalance(accountInfo!) && _isInputValid(accountInfo) ? () => _onSendPaymentPressed(model) : null, key: _sendPaymentButtonKey, ), - viewModelBuilder: () => SendPaymentBloc(), + viewModelBuilder: SendPaymentBloc.new, ); } Future _sendErrorNotification(error) async { await NotificationUtils.sendNotificationError( error, - 'Couldn\'t send ${_amountController.text} ${_selectedToken.symbol} ' + "Couldn't send ${_amountController.text} ${_selectedToken.symbol} " 'to ${_recipientController.text}', ); } @@ -299,7 +298,6 @@ class _SendMediumCardState extends State { details: 'Sent ${_amountController.text} ${_selectedToken.symbol} ' 'from ${ZenonAddressUtils.getLabel(kSelectedAddress!)} to ${ZenonAddressUtils.getLabel(_recipientController.text)}', type: NotificationType.paymentSent, - id: null, ), ); } @@ -311,7 +309,7 @@ class _SendMediumCardState extends State { BigInt.zero; void _addTokensWithBalance(AccountInfo accountInfo) { - for (var balanceInfo in accountInfo.balanceInfoList!) { + for (final BalanceInfoListItem balanceInfo in accountInfo.balanceInfoList!) { if (balanceInfo.balance! > BigInt.zero && !_tokensWithBalance.contains(balanceInfo.token)) { _tokensWithBalance.add(balanceInfo.token); diff --git a/lib/widgets/modular_widgets/transfer_widgets/send/send_small.dart b/lib/widgets/modular_widgets/transfer_widgets/send/send_small.dart index bac6ed87..ccaedbb9 100644 --- a/lib/widgets/modular_widgets/transfer_widgets/send/send_small.dart +++ b/lib/widgets/modular_widgets/transfer_widgets/send/send_small.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SendSmallCard extends StatefulWidget { - final VoidCallback onClicked; const SendSmallCard( this.onClicked, { - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onClicked; @override State createState() => _SendSmallCardState(); @@ -24,24 +24,23 @@ class _SendSmallCardState extends State { decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular( - 15.0, + 15, ), ), child: Container( padding: const EdgeInsets.all( - 20.0, + 20, ), child: const Column( - crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( SimpleLineIcons.arrow_up_circle, - size: 60.0, + size: 60, color: AppColors.darkHintTextColor, ), SizedBox( - height: 20.0, + height: 20, ), TransferIconLegend( legendText: '● Send', diff --git a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_camera_card.dart b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_camera_card.dart index d61c74eb..6baa92f9 100644 --- a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_camera_card.dart +++ b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_camera_card.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:logging/logging.dart'; import 'package:wallet_connect_uri_validator/wallet_connect_uri_validator.dart'; +import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/services/i_web3wallet_service.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; @@ -16,7 +17,7 @@ const String _kWidgetDescription = 'Scan a WalletConnect QR code using the built-in camera of this device'; class WalletConnectCameraCard extends StatefulWidget { - const WalletConnectCameraCard({Key? key}) : super(key: key); + const WalletConnectCameraCard({super.key}); @override State createState() => @@ -34,43 +35,42 @@ class _WalletConnectCameraCardState extends State { return CardScaffold( title: _kWidgetTitle, description: _kWidgetDescription, - childBuilder: () => _getCardBody(), + childBuilder: _getCardBody, ); } Widget _getCardBody() { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ const CircleAvatar( - radius: 60.0, + radius: 60, backgroundColor: Colors.white12, child: Icon( Icons.camera_alt_outlined, color: AppColors.znnColor, - size: 60.0, + size: 60, ), ), - Platform.isMacOS - ? MyOutlinedButton( + if (Platform.isMacOS) MyOutlinedButton( text: 'Scan QR', onPressed: () async { await Navigator.of(context).push( MaterialPageRoute( - builder: (context) => AiBarcodeScanner( - validator: (capture) => _filterBarcodes(capture) != null, - onDetect: (value) async { + builder: (BuildContext context) => AiBarcodeScanner( + validator: (BarcodeCapture capture) => _filterBarcodes(capture) != null, + onDetect: (BarcodeCapture value) async { Logger('WalletConnectCameraCard').log( Level.INFO, 'onDetect', value.toString(), ); - final wcService = sl.get(); + final IWeb3WalletService wcService = sl.get(); final Barcode? barcode = _filterBarcodes(value); if (barcode != null) { - final pairingInfo = await wcService.pair( + final PairingInfo pairingInfo = await wcService.pair( Uri.parse(value.barcodes.first.displayValue!), ); Logger('WalletConnectCameraCard').log( @@ -89,7 +89,7 @@ class _WalletConnectCameraCardState extends State { facing: CameraFacing.front, detectionSpeed: DetectionSpeed.noDuplicates, ), - errorBuilder: (p0, p1, p2) { + errorBuilder: (BuildContext p0, MobileScannerException p1, Widget? p2) { // Pop navigator and close camera after 10 seconds Timer(const Duration(seconds: 10), () { Navigator.pop(context); @@ -97,11 +97,11 @@ class _WalletConnectCameraCardState extends State { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Text('${p1.errorCode}', style: Theme.of(context) .textTheme - .bodyMedium), + .bodyMedium,), Container(height: 16), const Icon( MaterialCommunityIcons.camera_off, @@ -117,8 +117,7 @@ class _WalletConnectCameraCardState extends State { ); }, minimumSize: kLoadingButtonMinSize, - ) - : Text( + ) else Text( 'Only MacOS is supported at the moment', style: Theme.of(context).textTheme.bodyLarge, ), @@ -144,7 +143,7 @@ class _WalletConnectCameraCardState extends State { /// A BarcodeCapture can contain multiple barcodes. This function returns /// the first valid WC barcode Barcode? _filterBarcodes(BarcodeCapture capture) { - for (final barcode in capture.barcodes) { + for (final Barcode barcode in capture.barcodes) { final String? uri = barcode.displayValue; if (uri != null) { if (!canParseWalletConnectUri(uri)) { diff --git a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_pairing_list_card.dart b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_pairing_list_card.dart index 4a87a9da..7be2bdb2 100644 --- a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_pairing_list_card.dart +++ b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_pairing_list_card.dart @@ -17,7 +17,7 @@ const String _kWidgetDescription = 'securely over the Internet'; class WalletConnectPairingsCard extends StatefulWidget { - const WalletConnectPairingsCard({Key? key}) : super(key: key); + const WalletConnectPairingsCard({super.key}); @override State createState() => @@ -38,8 +38,8 @@ class _WalletConnectPairingsCardState extends State { return CardScaffold( title: _kWidgetTitle, description: _kWidgetDescription, - childBuilder: () => _getCardBody(), - onRefreshPressed: () => _pairingsBloc.refreshResults(), + childBuilder: _getCardBody, + onRefreshPressed: _pairingsBloc.refreshResults, ); } @@ -51,7 +51,7 @@ class _WalletConnectPairingsCardState extends State { return InfiniteScrollTable( disposeBloc: false, bloc: _pairingsBloc, - headerColumns: const [ + headerColumns: const [ InfiniteScrollTableHeaderColumn( columnName: 'Name', ), @@ -72,8 +72,8 @@ class _WalletConnectPairingsCardState extends State { columnName: '', ), ], - generateRowCells: (pairingInfo, bool isSelected) { - return [ + generateRowCells: (PairingInfo pairingInfo, bool isSelected) { + return [ InfiniteScrollTableCell.withText( context, pairingInfo.peerMetadata?.name ?? 'Empty', @@ -82,17 +82,15 @@ class _WalletConnectPairingsCardState extends State { _buildTableUrlWidget(pairingInfo), flex: 2, ), - isSelected - ? InfiniteScrollTableCell.withMarquee( + if (isSelected) InfiniteScrollTableCell.withMarquee( pairingInfo.topic, - ) - : InfiniteScrollTableCell.withText( + ) else InfiniteScrollTableCell.withText( context, pairingInfo.topic.short, ), InfiniteScrollTableCell.withText( context, - _formatExpiryDateTime(pairingInfo.expiry).toString(), + _formatExpiryDateTime(pairingInfo.expiry), ), InfiniteScrollTableCell.withText( context, @@ -115,7 +113,7 @@ class _WalletConnectPairingsCardState extends State { Row _buildTableUrlWidget(PairingInfo pairingInfo) { return Row( - children: [ + children: [ Text(pairingInfo.peerMetadata?.url ?? 'Empty'), Visibility( visible: pairingInfo.peerMetadata?.url != null, @@ -128,7 +126,7 @@ class _WalletConnectPairingsCardState extends State { } String _formatExpiryDateTime(int expirySeconds) { - final expiryDateTime = + final DateTime expiryDateTime = DateTime.fromMillisecondsSinceEpoch(expirySeconds * 1000); return DateFormat('MMM dd, y HH:mm:ss').format(expiryDateTime); diff --git a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_qr_card.dart b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_qr_card.dart index c6fa0f36..d41ffd09 100644 --- a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_qr_card.dart +++ b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_qr_card.dart @@ -7,6 +7,7 @@ import 'package:path/path.dart' as path; import 'package:pretty_qr_code/pretty_qr_code.dart'; import 'package:screen_capturer/screen_capturer.dart'; import 'package:wallet_connect_uri_validator/wallet_connect_uri_validator.dart'; +import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; import 'package:window_manager/window_manager.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; @@ -23,10 +24,10 @@ const String _kWidgetDescription = 'Scan the WalletConnect QR code using an on-screen QR scanner. ' 'This requires the screen recording permission'; -final screenCapturer = ScreenCapturer.instance; +final ScreenCapturer screenCapturer = ScreenCapturer.instance; class WalletConnectQrCard extends StatefulWidget { - const WalletConnectQrCard({Key? key}) : super(key: key); + const WalletConnectQrCard({super.key}); @override State createState() => _WalletConnectQrCardState(); @@ -38,30 +39,30 @@ class _WalletConnectQrCardState extends State { ); CapturedData? _lastCapturedData; - final _uriKey = GlobalKey(); + final GlobalKey _uriKey = GlobalKey(); @override Widget build(BuildContext context) { return CardScaffold( title: _kWidgetTitle, description: _kWidgetDescription, - childBuilder: () => _getCardBody(), + childBuilder: _getCardBody, ); } Widget _getCardBody() { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ Container( height: 130, width: 130, - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - borderRadius: BorderRadius.circular(15.0), + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(15), ), child: PrettyQrView.data( data: 'Scan the WalletConnect QR from the dApp', @@ -74,14 +75,14 @@ class _WalletConnectQrCardState extends State { scale: 0.3, padding: EdgeInsets.only(top: 10, bottom: 10), image: AssetImage( - 'assets/images/qr_code_child_image_znn.png'))), + 'assets/images/qr_code_child_image_znn.png',),),), errorCorrectLevel: QrErrorCorrectLevel.H, ), ), MyOutlinedButton( text: 'Scan QR', onPressed: () { - checkPermissionForMacOS().then((value) { + checkPermissionForMacOS().then((bool value) { if (value) { windowManager.minimize().then( (value) => _handleClickCapture(CaptureMode.region), @@ -98,8 +99,8 @@ class _WalletConnectQrCardState extends State { Future _pairWithDapp(Uri uri) async { try { - final wcService = sl.get(); - final pairingInfo = await wcService.pair(uri); + final IWeb3WalletService wcService = sl.get(); + final PairingInfo pairingInfo = await wcService.pair(uri); Logger('WalletConnectPairingCard') .log(Level.INFO, 'pairing info', pairingInfo.toJson()); _uriController = TextEditingController(); @@ -110,37 +111,36 @@ class _WalletConnectQrCardState extends State { } } - void _handleClickCapture(CaptureMode mode) async { + Future _handleClickCapture(CaptureMode mode) async { try { - Directory walletConnectDirectory = Directory( - path.join(znnDefaultPaths.cache.path, walletConnectDirName)); + final Directory walletConnectDirectory = Directory( + path.join(znnDefaultPaths.cache.path, walletConnectDirName),); if (!walletConnectDirectory.existsSync()) { walletConnectDirectory.createSync(recursive: true); } - String screenshotName = + final String screenshotName = 'screenshot-${DateTime.now().millisecondsSinceEpoch}'; - final imagePath = await File( - '${walletConnectDirectory.absolute.path}${path.separator}$screenshotName.png') + final File imagePath = await File( + '${walletConnectDirectory.absolute.path}${path.separator}$screenshotName.png',) .create(); _lastCapturedData = await screenCapturer.capture( mode: mode, imagePath: imagePath.absolute.path, - silent: true, ); if (_lastCapturedData != null) { - var image = img.decodePng(imagePath.readAsBytesSync())!; + final img.Image image = img.decodePng(imagePath.readAsBytesSync())!; - LuminanceSource source = RGBLuminanceSource( - image.width, image.height, image.getBytes().buffer.asInt32List()); - var bitmap = BinaryBitmap(HybridBinarizer(source)); + final LuminanceSource source = RGBLuminanceSource( + image.width, image.height, image.getBytes().buffer.asInt32List(),); + final BinaryBitmap bitmap = BinaryBitmap(HybridBinarizer(source)); - var reader = QRCodeReader(); - var result = reader.decode(bitmap); + final QRCodeReader reader = QRCodeReader(); + final Result result = reader.decode(bitmap); if (result.rawBytes!.isNotEmpty) { if (result.text.isNotEmpty && @@ -153,7 +153,7 @@ class _WalletConnectQrCardState extends State { title: 'Invalid QR code', timestamp: DateTime.now().millisecondsSinceEpoch, details: 'Please scan a valid WalletConnect QR code', - type: NotificationType.error)); + type: NotificationType.error,),); } } else { await windowManager.show(); @@ -161,7 +161,7 @@ class _WalletConnectQrCardState extends State { title: 'QR code scan failed', timestamp: DateTime.now().millisecondsSinceEpoch, details: 'Please scan a valid WalletConnect QR code', - type: NotificationType.error)); + type: NotificationType.error,),); } await _pairWithDapp(Uri.parse(result.text)); } else { @@ -186,7 +186,7 @@ class _WalletConnectQrCardState extends State { timestamp: DateTime.now().millisecondsSinceEpoch, details: 'Screen Recording permission is required to scan and process the on-screen WalletConnect QR code', - type: NotificationType.generatingPlasma)); + type: NotificationType.generatingPlasma,),); return false; } return true; @@ -195,7 +195,7 @@ class _WalletConnectQrCardState extends State { } Future _requestAccessForMacOS() async { - bool isAccessAllowed = await ScreenCapturer.instance.isAccessAllowed(); + final bool isAccessAllowed = await ScreenCapturer.instance.isAccessAllowed(); if (!isAccessAllowed) { await ScreenCapturer.instance.requestAccess(); } diff --git a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_session_list_card.dart b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_session_list_card.dart index 44b097db..f8a3a013 100644 --- a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_session_list_card.dart +++ b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_session_list_card.dart @@ -8,12 +8,12 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; const String _kWidgetTitle = 'WalletConnect Sessions List'; const String _kWidgetDescription = - 'A session refers to a live connection between a user\'s wallet and a dApp ' + "A session refers to a live connection between a user's wallet and a dApp " 'A session allows the dApp to communicate with the wallet ' 'securely over the Internet'; class WalletConnectSessionsCard extends StatefulWidget { - const WalletConnectSessionsCard({Key? key}) : super(key: key); + const WalletConnectSessionsCard({super.key}); @override State createState() => @@ -29,8 +29,8 @@ class _WalletConnectSessionsCardState extends State { return CardScaffold( title: _kWidgetTitle, description: _kWidgetDescription, - childBuilder: () => _getCardBody(), - onRefreshPressed: () => _sessionsBloc.refreshResults(), + childBuilder: _getCardBody, + onRefreshPressed: _sessionsBloc.refreshResults, ); } @@ -42,7 +42,7 @@ class _WalletConnectSessionsCardState extends State { return InfiniteScrollTable( disposeBloc: false, bloc: _sessionsBloc, - headerColumns: const [ + headerColumns: const [ InfiniteScrollTableHeaderColumn( columnName: 'Name', ), @@ -63,8 +63,8 @@ class _WalletConnectSessionsCardState extends State { columnName: 'Acknowledged', ), ], - generateRowCells: (sessionData, bool isSelected) { - return [ + generateRowCells: (SessionData sessionData, bool isSelected) { + return [ InfiniteScrollTableCell.withText( context, sessionData.peer.metadata.name, @@ -73,25 +73,21 @@ class _WalletConnectSessionsCardState extends State { _buildTableUrlWidget(sessionData.peer.metadata.url), flex: 2, ), - isSelected - ? InfiniteScrollTableCell.withMarquee( + if (isSelected) InfiniteScrollTableCell.withMarquee( sessionData.pairingTopic, - ) - : InfiniteScrollTableCell.withText( + ) else InfiniteScrollTableCell.withText( context, sessionData.pairingTopic.short, ), - isSelected - ? InfiniteScrollTableCell.withMarquee( + if (isSelected) InfiniteScrollTableCell.withMarquee( sessionData.topic, - ) - : InfiniteScrollTableCell.withText( + ) else InfiniteScrollTableCell.withText( context, sessionData.topic.short, ), InfiniteScrollTableCell.withText( context, - _formatExpiryDateTime(sessionData.expiry).toString(), + _formatExpiryDateTime(sessionData.expiry), ), InfiniteScrollTableCell.withText( context, @@ -104,7 +100,7 @@ class _WalletConnectSessionsCardState extends State { Row _buildTableUrlWidget(String? peerUrl) { return Row( - children: [ + children: [ Text(peerUrl ?? 'Empty'), Visibility( visible: peerUrl != null, @@ -117,7 +113,7 @@ class _WalletConnectSessionsCardState extends State { } String _formatExpiryDateTime(int expirySeconds) { - final expiryDateTime = + final DateTime expiryDateTime = DateTime.fromMillisecondsSinceEpoch(expirySeconds * 1000); return DateFormat('MMM dd, y HH:mm:ss').format(expiryDateTime); diff --git a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_uri_card.dart b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_uri_card.dart index a4268130..bd3c23b7 100644 --- a/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_uri_card.dart +++ b/lib/widgets/modular_widgets/wallet_connect_widgets/wallet_connect_uri_card.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:wallet_connect_uri_validator/wallet_connect_uri_validator.dart'; +import 'package:walletconnect_flutter_v2/apis/core/pairing/utils/pairing_models.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:zenon_syrius_wallet_flutter/services/i_web3wallet_service.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; @@ -10,7 +11,7 @@ const String _kWidgetTitle = 'WalletConnect Link'; const String _kWidgetDescription = 'Paste the WalletConnect link here'; class WalletConnectUriCard extends StatefulWidget { - const WalletConnectUriCard({Key? key}) : super(key: key); + const WalletConnectUriCard({super.key}); @override State createState() => _WalletConnectUriCardState(); @@ -21,34 +22,34 @@ class _WalletConnectUriCardState extends State { text: kLastWalletConnectUriNotifier.value, ); - final _uriKey = GlobalKey(); + final GlobalKey _uriKey = GlobalKey(); @override Widget build(BuildContext context) { return CardScaffold( title: _kWidgetTitle, description: _kWidgetDescription, - childBuilder: () => _getCardBody(), + childBuilder: _getCardBody, ); } Widget _getCardBody() { return Padding( - padding: const EdgeInsets.all(15.0), + padding: const EdgeInsets.all(15), child: ValueListenableBuilder( - builder: (_, value, child) { + builder: (_, String? value, Widget? child) { if (value != null) { _uriController.text = value; kLastWalletConnectUriNotifier.value = null; } return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ + children: [ SizedBox( - height: 120.0, + height: 120, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ const CircleAvatar( backgroundColor: Colors.white12, child: Icon( @@ -60,14 +61,14 @@ class _WalletConnectUriCardState extends State { key: _uriKey, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - validator: (value) { + validator: (String? value) { if (WalletConnectUri.tryParse(value ?? '') != null) { return null; } else { return 'URI invalid'; } }, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, controller: _uriController, @@ -83,12 +84,12 @@ class _WalletConnectUriCardState extends State { child: const Icon( Icons.content_paste, color: AppColors.darkHintTextColor, - size: 15.0, + size: 15, ), ), suffixIconConstraints: const BoxConstraints( - maxWidth: 45.0, - maxHeight: 20.0, + maxWidth: 45, + maxHeight: 20, ), hintText: 'WalletConnect URI', ), @@ -118,7 +119,7 @@ class _WalletConnectUriCardState extends State { Future _pairWithDapp(Uri uri) async { try { - final pairingInfo = await sl.get().pair(uri); + final PairingInfo pairingInfo = await sl.get().pair(uri); Logger('WalletConnectPairingCard') .log(Level.INFO, 'pairing info', pairingInfo.toJson()); _uriController = TextEditingController(); diff --git a/lib/widgets/reusable_widgets/accelerator_project_details.dart b/lib/widgets/reusable_widgets/accelerator_project_details.dart index fcb4fd3b..b4a9d3bf 100644 --- a/lib/widgets/reusable_widgets/accelerator_project_details.dart +++ b/lib/widgets/reusable_widgets/accelerator_project_details.dart @@ -6,11 +6,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AcceleratorProjectDetails extends StatelessWidget { - final Address? owner; - final Hash? hash; - final int? creationTimestamp; - final AcceleratorProjectStatus? acceleratorProjectStatus; - final bool isPhase; const AcceleratorProjectDetails({ this.owner, @@ -18,18 +13,23 @@ class AcceleratorProjectDetails extends StatelessWidget { this.creationTimestamp, this.acceleratorProjectStatus, this.isPhase = false, - Key? key, - }) : super(key: key); + super.key, + }); + final Address? owner; + final Hash? hash; + final int? creationTimestamp; + final AcceleratorProjectStatus? acceleratorProjectStatus; + final bool isPhase; @override Widget build(BuildContext context) { - List children = []; + final List children = []; if (owner != null) { children.add(Text( _getOwnerDetails(), style: Theme.of(context).inputDecorationTheme.hintStyle, - )); + ),); } if (hash != null) { @@ -45,36 +45,33 @@ class AcceleratorProjectDetails extends StatelessWidget { children.add(Text( 'Created ${_formatData(creationTimestamp! * 1000)}', style: Theme.of(context).inputDecorationTheme.hintStyle, - )); + ),); if (!isPhase && acceleratorProjectStatus != null && acceleratorProjectStatus == AcceleratorProjectStatus.voting) { children.add(Text( _getTimeUntilVotingCloses(), style: Theme.of(context).inputDecorationTheme.hintStyle, - )); + ),); } } return Row( children: children.zip(List.generate( children.length - 1, - (index) => Text( + (int index) => Text( ' ● ', style: Theme.of(context).inputDecorationTheme.hintStyle, ), - )), + ),), ); } String _formatData(int transactionMillis) { - int currentMillis = DateTime.now().millisecondsSinceEpoch; + final int currentMillis = DateTime.now().millisecondsSinceEpoch; if (currentMillis - transactionMillis <= const Duration( days: 1, - minutes: 0, - seconds: 0, - milliseconds: 0, ).inMilliseconds) { return _formatDataShort(currentMillis - transactionMillis); } @@ -82,7 +79,7 @@ class AcceleratorProjectDetails extends StatelessWidget { } String _formatDataShort(int i) { - Duration duration = Duration(milliseconds: i); + final Duration duration = Duration(milliseconds: i); if (duration.inHours > 0) { return '${duration.inHours} h ago'; } @@ -93,12 +90,12 @@ class AcceleratorProjectDetails extends StatelessWidget { } String _getTimeUntilVotingCloses() { - String prefix = 'Voting closes in '; + const String prefix = 'Voting closes in '; String suffix = ''; - DateTime creationDate = + final DateTime creationDate = DateTime.fromMillisecondsSinceEpoch((creationTimestamp ?? 0) * 1000); - DateTime votingEnds = creationDate.add(kProjectVotingPeriod); - Duration difference = votingEnds.difference(DateTime.now()); + final DateTime votingEnds = creationDate.add(kProjectVotingPeriod); + final Duration difference = votingEnds.difference(DateTime.now()); if (difference.isNegative) { return 'Voting closed'; } diff --git a/lib/widgets/reusable_widgets/access_wallet_fluid_cell.dart b/lib/widgets/reusable_widgets/access_wallet_fluid_cell.dart index c969c65c..3247aa34 100644 --- a/lib/widgets/reusable_widgets/access_wallet_fluid_cell.dart +++ b/lib/widgets/reusable_widgets/access_wallet_fluid_cell.dart @@ -5,13 +5,8 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class AccessWalletFluidCell extends FluidCell { - final VoidCallback? onPressed; - final String buttonIconLocation; - final String buttonText; - final BuildContext context; AccessWalletFluidCell({ - Key? key, required this.onPressed, required this.buttonIconLocation, required this.buttonText, @@ -28,11 +23,11 @@ class AccessWalletFluidCell extends FluidCell { disabledColor: Theme.of(context).colorScheme.secondary.withOpacity( 0.7, ), - padding: const EdgeInsets.all(50.0), + padding: const EdgeInsets.all(50), color: Theme.of(context).colorScheme.secondaryContainer, hoverColor: Theme.of(context).colorScheme.secondary, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), + borderRadius: BorderRadius.circular(12), side: const BorderSide(color: Colors.transparent), ), onPressed: onPressed, @@ -40,19 +35,19 @@ class AccessWalletFluidCell extends FluidCell { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( - width: 70.0, - height: 70.0, + width: 70, + height: 70, color: Colors.transparent, child: SvgPicture.asset( buttonIconLocation, colorFilter: const ColorFilter.mode( - AppColors.znnColor, BlendMode.srcIn), + AppColors.znnColor, BlendMode.srcIn,), ), ), Padding( padding: const EdgeInsets.only( - left: 40.0, - right: 40.0, + left: 40, + right: 40, ), child: Text( buttonText, @@ -64,4 +59,8 @@ class AccessWalletFluidCell extends FluidCell { ), ), ); + final VoidCallback? onPressed; + final String buttonIconLocation; + final String buttonText; + final BuildContext context; } diff --git a/lib/widgets/reusable_widgets/amount_info_column.dart b/lib/widgets/reusable_widgets/amount_info_column.dart index f703c9dd..b2ed845f 100644 --- a/lib/widgets/reusable_widgets/amount_info_column.dart +++ b/lib/widgets/reusable_widgets/amount_info_column.dart @@ -1,26 +1,25 @@ import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class AmountInfoColumn extends Column { - final String amount; - final String tokenSymbol; - final BuildContext context; AmountInfoColumn({ - Key? key, - required this.context, - required this.amount, - required this.tokenSymbol, + required this.context, required this.amount, required this.tokenSymbol, super.key, }) : super( - key: key, - children: [ + children: [ Text( tokenSymbol, - style: Theme.of(context).textTheme.bodyLarge, + style: Theme.of(context).textTheme.titleSmall, ), Text( amount, - style: Theme.of(context).textTheme.titleSmall, + style: Theme.of(context).textTheme.labelSmall?.copyWith( + color: AppColors.subtitleColor, + ), ), ], ); + final String amount; + final String tokenSymbol; + final BuildContext context; } diff --git a/lib/widgets/reusable_widgets/available_balance.dart b/lib/widgets/reusable_widgets/available_balance.dart index a7b32e2b..28688ce9 100644 --- a/lib/widgets/reusable_widgets/available_balance.dart +++ b/lib/widgets/reusable_widgets/available_balance.dart @@ -3,14 +3,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AvailableBalance extends StatelessWidget { - final Token token; - final AccountInfo accountInfo; const AvailableBalance( this.token, this.accountInfo, { - Key? key, - }) : super(key: key); + super.key, + }); + final Token token; + final AccountInfo accountInfo; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/bullet_point_card.dart b/lib/widgets/reusable_widgets/bullet_point_card.dart index f2f5914d..0876563c 100644 --- a/lib/widgets/reusable_widgets/bullet_point_card.dart +++ b/lib/widgets/reusable_widgets/bullet_point_card.dart @@ -3,18 +3,18 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; class BulletPointCard extends StatelessWidget { - final List bulletPoints; const BulletPointCard({ required this.bulletPoints, - Key? key, - }) : super(key: key); + super.key, + }); + final List bulletPoints; static TextSpan textSpan(String text, {List? children}) { return TextSpan( text: text, - style: const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), - children: children); + style: const TextStyle(fontSize: 14, color: AppColors.subtitleColor), + children: children,); } @override @@ -22,28 +22,28 @@ class BulletPointCard extends StatelessWidget { return Container( decoration: BoxDecoration( color: Theme.of(context).hoverColor, - borderRadius: const BorderRadius.all(Radius.circular(8.0)), + borderRadius: const BorderRadius.all(Radius.circular(8)), ), child: Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: bulletPoints - .map((e) => Row( - children: [ + .map((RichText e) => Row( + children: [ const Text('●', style: TextStyle( - fontSize: 14.0, color: AppColors.subtitleColor)), - const SizedBox(width: 10.0), - Expanded(child: e) + fontSize: 14, color: AppColors.subtitleColor,),), + const SizedBox(width: 10), + Expanded(child: e), ], - )) + ),) .toList() .zip( List.generate( bulletPoints.length - 1, - (index) => const SizedBox( - height: 15.0, + (int index) => const SizedBox( + height: 15, ), ), ), diff --git a/lib/widgets/reusable_widgets/buttons/elevated_button.dart b/lib/widgets/reusable_widgets/buttons/elevated_button.dart index b2753d8e..8ff745a7 100644 --- a/lib/widgets/reusable_widgets/buttons/elevated_button.dart +++ b/lib/widgets/reusable_widgets/buttons/elevated_button.dart @@ -3,11 +3,6 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class SyriusElevatedButton extends StatefulWidget { - final String text; - final Color initialFillColor; - final VoidCallback? onPressed; - final Widget? icon; - final ButtonStyle? style; const SyriusElevatedButton({ required this.text, @@ -15,8 +10,13 @@ class SyriusElevatedButton extends StatefulWidget { this.icon, this.initialFillColor = AppColors.qsrColor, this.style, - Key? key, - }) : super(key: key); + super.key, + }); + final String text; + final Color initialFillColor; + final VoidCallback? onPressed; + final Widget? icon; + final ButtonStyle? style; @override State createState() { @@ -33,7 +33,7 @@ class SyriusElevatedButton extends StatefulWidget { child: const Icon( MaterialCommunityIcons.plus, color: Colors.white, - size: 15.0, + size: 15, ), ); } @@ -47,20 +47,20 @@ class _SyriusElevatedButtonState extends State { style: widget.style, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Visibility( visible: widget.icon != null, child: Container( alignment: Alignment.center, - height: 20.0, - width: 20.0, + height: 20, + width: 20, child: widget.icon, ), ), Visibility( visible: widget.icon != null, child: const SizedBox( - width: 5.0, + width: 5, ), ), Text( diff --git a/lib/widgets/reusable_widgets/buttons/instruction_button.dart b/lib/widgets/reusable_widgets/buttons/instruction_button.dart index f56b652a..c4f9c89c 100644 --- a/lib/widgets/reusable_widgets/buttons/instruction_button.dart +++ b/lib/widgets/reusable_widgets/buttons/instruction_button.dart @@ -3,12 +3,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_info_text.dart'; class InstructionButton extends StatefulWidget { - final String text; - final bool isEnabled; - final bool isLoading; - final VoidCallback onPressed; - final String? instructionText; - final String? loadingText; const InstructionButton({ required this.text, @@ -17,8 +11,14 @@ class InstructionButton extends StatefulWidget { required this.onPressed, this.instructionText, this.loadingText, - Key? key, - }) : super(key: key); + super.key, + }); + final String text; + final bool isEnabled; + final bool isLoading; + final VoidCallback onPressed; + final String? instructionText; + final String? loadingText; @override State createState() => _InstructionButtonState(); diff --git a/lib/widgets/reusable_widgets/buttons/loading_button.dart b/lib/widgets/reusable_widgets/buttons/loading_button.dart index 28fe64ea..505fc82c 100644 --- a/lib/widgets/reusable_widgets/buttons/loading_button.dart +++ b/lib/widgets/reusable_widgets/buttons/loading_button.dart @@ -9,16 +9,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; enum ButtonState { busy, idle } class LoadingButton extends StatefulWidget { - final Size minimumSize; - final double minWidth; - final VoidCallback? onPressed; - final String? text; - final Widget? child; - final Color? outlineColor; - final EdgeInsets paddingAroundChild; - final double borderWidth; - final double circularBorderRadius; - final TextStyle? textStyle; const LoadingButton({ required this.onPressed, @@ -47,7 +37,7 @@ class LoadingButton extends StatefulWidget { onPressed: onPressed, label: text, key: key, - minimumSize: const Size(90.0, 25.0), + minimumSize: const Size(90, 25), textStyle: textStyle, outlineColor: outlineColor, icon: icon, @@ -64,7 +54,7 @@ class LoadingButton extends StatefulWidget { onPressed: onPressed, text: text, key: key, - minimumSize: const Size(80.0, 25.0), + minimumSize: const Size(80, 25), textStyle: textStyle, outlineColor: outlineColor, ); @@ -79,7 +69,6 @@ class LoadingButton extends StatefulWidget { text: text, minimumSize: kSettingsButtonMinSize, key: key, - paddingAroundChild: EdgeInsets.zero, textStyle: kBodyMediumTextStyle, ); @@ -91,7 +80,7 @@ class LoadingButton extends StatefulWidget { LoadingButton( onPressed: onPressed, text: text, - minimumSize: const Size(360.0, 40.0), + minimumSize: const Size(360, 40), key: key, ); @@ -115,7 +104,7 @@ class LoadingButton extends StatefulWidget { required Widget icon, required Key key, String label = '', - Size minimumSize = const Size(50.0, 50.0), + Size minimumSize = const Size(50, 50), Color? outlineColor, TextStyle? textStyle, }) => @@ -128,7 +117,7 @@ class LoadingButton extends StatefulWidget { child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ icon, SizedBox( width: label.isNotEmpty ? 10.0 : 0.0, @@ -140,6 +129,16 @@ class LoadingButton extends StatefulWidget { ], ), ); + final Size minimumSize; + final double minWidth; + final VoidCallback? onPressed; + final String? text; + final Widget? child; + final Color? outlineColor; + final EdgeInsets paddingAroundChild; + final double borderWidth; + final double circularBorderRadius; + final TextStyle? textStyle; @override LoadingButtonState createState() => LoadingButtonState(); @@ -154,7 +153,7 @@ class LoadingButtonState extends State ButtonState btnState = ButtonState.idle; final GlobalKey _outlineButtonKey = GlobalKey(); - double _minWidth = 0.0; + double _minWidth = 0; double get minWidth => _minWidth; @@ -177,7 +176,7 @@ class LoadingButtonState extends State ), ); - _animation = Tween(begin: 0.0, end: 1.0).animate( + _animation = Tween(begin: 0, end: 1).animate( CurvedAnimation( parent: _animationController, curve: Curves.easeInOutCirc, @@ -185,7 +184,7 @@ class LoadingButtonState extends State ), ); - _animation.addStatusListener((status) { + _animation.addStatusListener((AnimationStatus status) { if (status == AnimationStatus.dismissed) { setState(() { btnState = ButtonState.idle; @@ -207,7 +206,7 @@ class LoadingButtonState extends State Widget build(BuildContext context) { return AnimatedBuilder( animation: _animationController, - builder: (context, child) { + builder: (BuildContext context, Widget? child) { return buttonBody(); }, ); @@ -219,7 +218,7 @@ class LoadingButtonState extends State borderWidth: widget.borderWidth, outlineColor: widget.outlineColor, minimumSize: Size( - lerpWidth(widget.minimumSize.width, minWidth, _animation.value), + lerpWidth(widget.minimumSize.width, minWidth, _animation.value)!, widget.minimumSize.height, ), onPressed: btnState == ButtonState.idle ? widget.onPressed : null, @@ -228,15 +227,15 @@ class LoadingButtonState extends State widget.circularBorderRadius, widget.minimumSize.height / 2, _animation.value, - )!, + ), padding: widget.paddingAroundChild, child: btnState == ButtonState.idle ? widget.child ?? Text(widget.text!) : const SizedBox( - width: 15.0, - height: 15.0, + width: 15, + height: 15, child: CircularProgressIndicator( - strokeWidth: 1.0, + strokeWidth: 1, valueColor: AlwaysStoppedAnimation(AppColors.znnColor), ), ), @@ -258,7 +257,7 @@ class LoadingButtonState extends State } } - lerpWidth(a, b, t) { + double? lerpWidth(double a, double b, double t) { if (a == 0.0 || b == 0.0) { return null; } else { diff --git a/lib/widgets/reusable_widgets/buttons/material_icon_button.dart b/lib/widgets/reusable_widgets/buttons/material_icon_button.dart index 5f67b3d6..87f72d62 100644 --- a/lib/widgets/reusable_widgets/buttons/material_icon_button.dart +++ b/lib/widgets/reusable_widgets/buttons/material_icon_button.dart @@ -2,13 +2,6 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class MaterialIconButton extends StatelessWidget { - final Color iconColor; - final Color? hoverColor; - final double padding; - final MaterialTapTargetSize materialTapTargetSize; - final VoidCallback onPressed; - final IconData iconData; - final double size; const MaterialIconButton({ required this.onPressed, @@ -18,8 +11,15 @@ class MaterialIconButton extends StatelessWidget { this.hoverColor, this.padding = 8.0, this.materialTapTargetSize = MaterialTapTargetSize.padded, - Key? key, - }) : super(key: key); + super.key, + }); + final Color iconColor; + final Color? hoverColor; + final double padding; + final MaterialTapTargetSize materialTapTargetSize; + final VoidCallback onPressed; + final IconData iconData; + final double size; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/buttons/onboarding_button.dart b/lib/widgets/reusable_widgets/buttons/onboarding_button.dart index d3366505..81b2bb5f 100644 --- a/lib/widgets/reusable_widgets/buttons/onboarding_button.dart +++ b/lib/widgets/reusable_widgets/buttons/onboarding_button.dart @@ -3,13 +3,10 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class OnboardingButton extends MyOutlinedButton { const OnboardingButton({ - required VoidCallback? onPressed, - required String text, - Key? key, + required super.onPressed, + required String super.text, + super.key, }) : super( - key: key, - onPressed: onPressed, - text: text, - minimumSize: const Size(360.0, 40.0), + minimumSize: const Size(360, 40), ); } diff --git a/lib/widgets/reusable_widgets/buttons/outlined_button.dart b/lib/widgets/reusable_widgets/buttons/outlined_button.dart index 0083d47c..a33feeab 100644 --- a/lib/widgets/reusable_widgets/buttons/outlined_button.dart +++ b/lib/widgets/reusable_widgets/buttons/outlined_button.dart @@ -4,19 +4,9 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class MyOutlinedButton extends StatefulWidget { - final String? text; - final TextStyle? textStyle; - final Color? outlineColor; - final VoidCallback? onPressed; - final Size? minimumSize; - final Widget? child; - final double borderWidth; - final double? circularBorderRadius; - final Color? textColor; - final EdgeInsets? padding; const MyOutlinedButton({ - this.text, + required this.onPressed, this.text, this.textStyle, this.outlineColor, this.minimumSize, @@ -25,9 +15,8 @@ class MyOutlinedButton extends StatefulWidget { this.circularBorderRadius, this.textColor, this.padding, - required this.onPressed, - Key? key, - }) : super(key: key); + super.key, + }); factory MyOutlinedButton.icon({ required VoidCallback? onPressed, @@ -43,6 +32,16 @@ class MyOutlinedButton extends StatefulWidget { outlineColor: outlineColor, key: key, ); + final String? text; + final TextStyle? textStyle; + final Color? outlineColor; + final VoidCallback? onPressed; + final Size? minimumSize; + final Widget? child; + final double borderWidth; + final double? circularBorderRadius; + final Color? textColor; + final EdgeInsets? padding; @override MyOutlinedButtonState createState() => MyOutlinedButtonState(); @@ -73,9 +72,9 @@ class MyOutlinedButtonState extends State { ) : null, ).copyWith( - side: MaterialStateProperty.resolveWith( - (states) { - if (states.contains(MaterialState.disabled)) { + side: WidgetStateProperty.resolveWith( + (Set states) { + if (states.contains(WidgetState.disabled)) { return BorderSide( color: AppColors.lightSecondaryContainer, width: widget.borderWidth, @@ -99,7 +98,7 @@ class MyOutlinedButtonState extends State { ), child: _showLoading ? const SyriusLoadingWidget( - size: 25.0, + size: 25, ) : widget.text != null ? Text( @@ -122,13 +121,9 @@ class _MyOutlinedButtonWithIcon extends MyOutlinedButton { _MyOutlinedButtonWithIcon({ required String label, required Widget icon, - Color? outlineColor, - required VoidCallback? onPressed, - Key? key, + required super.onPressed, super.outlineColor, + super.key, }) : super( - onPressed: onPressed, - outlineColor: outlineColor, - key: key, child: _MyOutlinedButtonWithIconChild( label: label, icon: icon, @@ -137,22 +132,22 @@ class _MyOutlinedButtonWithIcon extends MyOutlinedButton { } class _MyOutlinedButtonWithIconChild extends StatelessWidget { - final String label; - final Widget icon; const _MyOutlinedButtonWithIconChild({ required this.label, required this.icon, }); + final String label; + final Widget icon; @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ icon, const SizedBox( - width: 15.0, + width: 15, ), Text(label), ], diff --git a/lib/widgets/reusable_widgets/buttons/send_payment_button.dart b/lib/widgets/reusable_widgets/buttons/send_payment_button.dart index 7241e5d5..470d25c9 100644 --- a/lib/widgets/reusable_widgets/buttons/send_payment_button.dart +++ b/lib/widgets/reusable_widgets/buttons/send_payment_button.dart @@ -4,27 +4,21 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SendPaymentButton extends LoadingButton { const SendPaymentButton({ - required VoidCallback? onPressed, - required Key key, - String text = 'Send', - Color? outlineColor, - Size minimumSize = const Size(100.0, 40.0), + required super.onPressed, + required super.key, + String super.text = 'Send', + super.outlineColor, + super.minimumSize = const Size(100, 40), }) : super( - onPressed: onPressed, - text: text, - key: key, - minimumSize: minimumSize, - outlineColor: outlineColor, paddingAroundChild: const EdgeInsets.symmetric( - horizontal: 10.0, + horizontal: 10, ), ); factory SendPaymentButton.error({ required VoidCallback? onPressed, required Key key, - String text = 'Retry', - Size minimumSize = const Size(150.0, 40.0), + Size minimumSize = const Size(150, 40), }) => SendPaymentButton( onPressed: onPressed, diff --git a/lib/widgets/reusable_widgets/buttons/settings_button.dart b/lib/widgets/reusable_widgets/buttons/settings_button.dart index 68113888..d08d7cbb 100644 --- a/lib/widgets/reusable_widgets/buttons/settings_button.dart +++ b/lib/widgets/reusable_widgets/buttons/settings_button.dart @@ -1,17 +1,13 @@ -import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_theme.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SettingsButton extends MyOutlinedButton { const SettingsButton({ - required VoidCallback? onPressed, - required String text, - Key? key, + required super.onPressed, + required String super.text, + super.key, }) : super( - key: key, - onPressed: onPressed, - text: text, textStyle: kBodyMediumTextStyle, minimumSize: kSettingsButtonMinSize, ); diff --git a/lib/widgets/reusable_widgets/buttons/stepper_button.dart b/lib/widgets/reusable_widgets/buttons/stepper_button.dart index 9df760cd..49b1a5d7 100644 --- a/lib/widgets/reusable_widgets/buttons/stepper_button.dart +++ b/lib/widgets/reusable_widgets/buttons/stepper_button.dart @@ -3,29 +3,21 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class StepperButton extends MyOutlinedButton { const StepperButton({ - required VoidCallback? onPressed, - String? text, - Color? outlineColor, - Widget? child, - Key? key, + required super.onPressed, + super.text, + super.outlineColor, + super.child, + super.key, }) : super( - key: key, - onPressed: onPressed, - text: text, - outlineColor: outlineColor, - minimumSize: const Size(120.0, 40.0), - child: child, + minimumSize: const Size(120, 40), ); factory StepperButton.icon({ required String label, required IconData iconData, - required context, required VoidCallback onPressed, - Color? outlineColor, }) => _MyStepperButtonWithIcon( - context: context, onPressed: onPressed, label: label, iconData: iconData, @@ -36,12 +28,8 @@ class _MyStepperButtonWithIcon extends StepperButton { _MyStepperButtonWithIcon({ required String label, required IconData iconData, - required VoidCallback onPressed, - required BuildContext context, - Color? outlineColor, + required VoidCallback super.onPressed, }) : super( - onPressed: onPressed, - outlineColor: outlineColor, child: _MyStepperButtonWithIconChild( label: label, iconData: iconData, @@ -50,26 +38,26 @@ class _MyStepperButtonWithIcon extends StepperButton { } class _MyStepperButtonWithIconChild extends StatelessWidget { - final String label; - final IconData iconData; const _MyStepperButtonWithIconChild({ required this.label, required this.iconData, }); + final String label; + final IconData iconData; @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ Text(label), const SizedBox( - width: 10.0, + width: 10, ), Icon( iconData, - size: 17.0, + size: 17, color: Theme.of(context).textTheme.headlineSmall!.color, ), ], diff --git a/lib/widgets/reusable_widgets/buttons/transfer_toggle_card_size_button.dart b/lib/widgets/reusable_widgets/buttons/transfer_toggle_card_size_button.dart index ceeeab76..4679da9b 100644 --- a/lib/widgets/reusable_widgets/buttons/transfer_toggle_card_size_button.dart +++ b/lib/widgets/reusable_widgets/buttons/transfer_toggle_card_size_button.dart @@ -4,20 +4,20 @@ import 'package:zenon_syrius_wallet_flutter/main.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class TransferToggleCardSizeButton extends StatelessWidget { - final VoidCallback? onPressed; - final IconData iconData; const TransferToggleCardSizeButton({ required this.onPressed, required this.iconData, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback? onPressed; + final IconData iconData; @override Widget build(BuildContext context) { return StreamBuilder( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getButton(context, onPressed); } else if (snapshot.hasData) { @@ -42,7 +42,7 @@ class TransferToggleCardSizeButton extends StatelessWidget { return RawMaterialButton( constraints: const BoxConstraints.tightForFinite(), padding: const EdgeInsets.all( - 20.0, + 20, ), shape: const CircleBorder(), onPressed: onButtonPressed, diff --git a/lib/widgets/reusable_widgets/cancel_timer.dart b/lib/widgets/reusable_widgets/cancel_timer.dart index 578dcc1b..5b8f1d54 100644 --- a/lib/widgets/reusable_widgets/cancel_timer.dart +++ b/lib/widgets/reusable_widgets/cancel_timer.dart @@ -3,16 +3,16 @@ import 'dart:async'; import 'package:flutter/material.dart'; class CancelTimer extends StatefulWidget { - final Duration timerDuration; - final Color borderColor; - final VoidCallback onTimeFinishedCallback; const CancelTimer( this.timerDuration, this.borderColor, { required this.onTimeFinishedCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final Duration timerDuration; + final Color borderColor; + final VoidCallback onTimeFinishedCallback; @override State createState() => _CancelTimerState(); @@ -32,11 +32,11 @@ class _CancelTimerState extends State { const Duration( seconds: 1, ), - (v) { + (Timer v) { if (mounted && _currentDuration > const Duration( - seconds: 0, + )) { setState(() { _currentDuration = _currentDuration - @@ -56,7 +56,7 @@ class _CancelTimerState extends State { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular( - 5.0, + 5, ), border: Border.all( color: _borderColor, @@ -64,8 +64,8 @@ class _CancelTimerState extends State { ), child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 5.0, + horizontal: 10, + vertical: 5, ), child: Text( _currentDuration.toString().split('.').first, diff --git a/lib/widgets/reusable_widgets/chart/chart_legend.dart b/lib/widgets/reusable_widgets/chart/chart_legend.dart index cd3e263e..59c2a39f 100644 --- a/lib/widgets/reusable_widgets/chart/chart_legend.dart +++ b/lib/widgets/reusable_widgets/chart/chart_legend.dart @@ -1,22 +1,21 @@ import 'package:flutter/material.dart'; class ChartLegend extends StatelessWidget { - final Color dotColor; - final String mainText; - final Widget? detailsWidget; const ChartLegend({ required this.dotColor, required this.mainText, this.detailsWidget, - Key? key, - }) : super(key: key); + super.key, + }); + final Color dotColor; + final String mainText; + final Widget? detailsWidget; @override Widget build(BuildContext context) { return Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ Text( '● ', style: Theme.of(context).textTheme.bodyLarge!.copyWith( @@ -28,7 +27,7 @@ class ChartLegend extends StatelessWidget { style: Theme.of(context).textTheme.bodyMedium, ), const SizedBox( - width: 5.0, + width: 5, ), if (detailsWidget != null) Expanded( diff --git a/lib/widgets/reusable_widgets/chart/standard_chart.dart b/lib/widgets/reusable_widgets/chart/standard_chart.dart index 15396644..0fd800e2 100644 --- a/lib/widgets/reusable_widgets/chart/standard_chart.dart +++ b/lib/widgets/reusable_widgets/chart/standard_chart.dart @@ -1,55 +1,53 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/format_utils.dart'; class StandardChart extends StatelessWidget { - final double? yValuesInterval; - final double maxX; - final double maxY; - final List lineBarsData; - final String lineBarDotSymbol; - final DateTime titlesReferenceDate; - final bool convertLeftSideTitlesToInt; const StandardChart({ - required this.yValuesInterval, required this.maxY, required this.lineBarsData, required this.titlesReferenceDate, this.maxX = kStandardChartNumDays - 1, this.lineBarDotSymbol = '', this.convertLeftSideTitlesToInt = false, - Key? key, - }) : super(key: key); + super.key, + }); + final double maxX; + final double maxY; + final List lineBarsData; + final String lineBarDotSymbol; + final DateTime titlesReferenceDate; + final bool convertLeftSideTitlesToInt; @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.only( - left: 5.0, - right: 20.0, - top: 20.0, - bottom: 10.0, + left: 5, + right: 20, + top: 20, + bottom: 10, ), child: LineChart( LineChartData( lineTouchData: LineTouchData( - enabled: true, touchTooltipData: LineTouchTooltipData( fitInsideHorizontally: true, - tooltipMargin: 14.0, - tooltipPadding: const EdgeInsets.all(4.0), - tooltipRoundedRadius: 6.0, + tooltipMargin: 14, + tooltipPadding: const EdgeInsets.all(4), + tooltipRoundedRadius: 6, getTooltipColor: (LineBarSpot lineBarSpot) => - Theme.of(context).colorScheme.background, - getTooltipItems: (touchedSpots) { + context.themeData.colorScheme.surface, + getTooltipItems: (List touchedSpots) { return touchedSpots.map( (LineBarSpot touchedSpot) { - final textStyle = TextStyle( + final TextStyle textStyle = TextStyle( color: touchedSpot.bar.color, fontWeight: FontWeight.bold, - fontSize: 14.0, + fontSize: 14, ); return LineTooltipItem( '${touchedSpot.y == touchedSpot.y.toInt() ? touchedSpot.y.toInt() : touchedSpot.y} ' @@ -64,67 +62,46 @@ class StandardChart extends StatelessWidget { gridData: FlGridData( show: false, drawVerticalLine: false, - drawHorizontalLine: true, getDrawingHorizontalLine: (_) { return const FlLine( - strokeWidth: 1.0, + strokeWidth: 1, color: Colors.black87, - dashArray: [3, 3], + dashArray: [3, 3], ); }, ), titlesData: FlTitlesData( bottomTitles: AxisTitles( sideTitles: SideTitles( - getTitlesWidget: (value, titleMeta) => Padding( - padding: const EdgeInsets.only(top: 8.0), + getTitlesWidget: (double value, TitleMeta titleMeta) => Padding( + padding: const EdgeInsets.only(top: 8), child: Text( FormatUtils.formatDate( FormatUtils.subtractDaysFromDate( - value.toInt(), titlesReferenceDate), + value.toInt(), titlesReferenceDate,), dateFormat: 'd MMM', ), - style: Theme.of(context).textTheme.titleSmall!, + style: Theme.of(context).textTheme.labelMedium, ), ), showTitles: true, - reservedSize: 22.0, - interval: 1.0, + interval: 1, ), ), - leftTitles: AxisTitles( + leftTitles: const AxisTitles( sideTitles: SideTitles( - interval: yValuesInterval, showTitles: true, - getTitlesWidget: (value, _) => Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - value != 0 - ? convertLeftSideTitlesToInt - ? '${value.toInt()}' - : value.toStringAsFixed(2) - : '', - style: Theme.of(context).textTheme.titleSmall!, - ), - ), - reservedSize: 26.0, - ), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles( - showTitles: false, + reservedSize: 32, ), ), - topTitles: const AxisTitles( - sideTitles: SideTitles( - showTitles: false, - )), + rightTitles: const AxisTitles(), + topTitles: const AxisTitles(), ), borderData: FlBorderData(show: false), - minX: 0.0, + minX: 0, maxX: maxX, maxY: maxY, - minY: 0.0, + minY: 0, lineBarsData: lineBarsData, ), ), diff --git a/lib/widgets/reusable_widgets/chart/standard_line_chart_bar_data.dart b/lib/widgets/reusable_widgets/chart/standard_line_chart_bar_data.dart index 92e34146..35aacfb4 100644 --- a/lib/widgets/reusable_widgets/chart/standard_line_chart_bar_data.dart +++ b/lib/widgets/reusable_widgets/chart/standard_line_chart_bar_data.dart @@ -7,8 +7,8 @@ class StandardLineChartBarData extends LineChartBarData { required List? spots, }) : super( color: color, - barWidth: 3.0, + barWidth: 3, isStrokeCapRound: true, - spots: spots ?? const [] + spots: spots ?? const [], ); } diff --git a/lib/widgets/reusable_widgets/chart/standard_pie_chart.dart b/lib/widgets/reusable_widgets/chart/standard_pie_chart.dart index aa08fb75..9e36c8b9 100644 --- a/lib/widgets/reusable_widgets/chart/standard_pie_chart.dart +++ b/lib/widgets/reusable_widgets/chart/standard_pie_chart.dart @@ -2,21 +2,16 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; class StandardPieChart extends PieChart { - final List sections; - final void Function(PieTouchedSection?)? onChartSectionTouched; - final double? centerSpaceRadius; - final double sectionsSpace; StandardPieChart({ - Key? key, - required this.sections, + required this.sections, Key? key, this.sectionsSpace = 0.0, this.centerSpaceRadius, this.onChartSectionTouched, }) : super( PieChartData( pieTouchData: PieTouchData( - touchCallback: (event, pieTouchResponse) { + touchCallback: (FlTouchEvent event, PieTouchResponse? pieTouchResponse) { if (!event.isInterestedForInteractions || pieTouchResponse == null || pieTouchResponse.touchedSection == null) { @@ -24,7 +19,7 @@ class StandardPieChart extends PieChart { return; } onChartSectionTouched?.call( - pieTouchResponse.touchedSection!, + pieTouchResponse.touchedSection, ); }, ), @@ -37,4 +32,8 @@ class StandardPieChart extends PieChart { ), key: key, ); + final List sections; + final void Function(PieTouchedSection?)? onChartSectionTouched; + final double? centerSpaceRadius; + final double sectionsSpace; } diff --git a/lib/widgets/reusable_widgets/context_menu_region.dart b/lib/widgets/reusable_widgets/context_menu_region.dart index f5f7b305..630f03a5 100644 --- a/lib/widgets/reusable_widgets/context_menu_region.dart +++ b/lib/widgets/reusable_widgets/context_menu_region.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; typedef ContextMenuBuilder = Widget Function( - BuildContext context, Offset offset); + BuildContext context, Offset offset,); /// Shows and hides the context menu based on user gestures. /// @@ -10,10 +10,8 @@ typedef ContextMenuBuilder = Widget Function( class ContextMenuRegion extends StatefulWidget { /// Creates an instance of [ContextMenuRegion]. const ContextMenuRegion({ - Key? key, - required this.child, - required this.contextMenuBuilder, - }) : super(key: key); + required this.child, required this.contextMenuBuilder, super.key, + }); /// Builds the context menu. final ContextMenuBuilder contextMenuBuilder; @@ -67,7 +65,7 @@ class _ContextMenuRegionState extends State { void _show(Offset position) { _contextMenuController.show( context: context, - contextMenuBuilder: (context) { + contextMenuBuilder: (BuildContext context) { return widget.contextMenuBuilder(context, position); }, ); diff --git a/lib/widgets/reusable_widgets/custom_expandable_panel.dart b/lib/widgets/reusable_widgets/custom_expandable_panel.dart index bd4f582d..f9074e7b 100644 --- a/lib/widgets/reusable_widgets/custom_expandable_panel.dart +++ b/lib/widgets/reusable_widgets/custom_expandable_panel.dart @@ -3,14 +3,14 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class CustomExpandablePanel extends StatefulWidget { - final String header; - final Widget expandedChild; const CustomExpandablePanel( this.header, this.expandedChild, { - Key? key, - }) : super(key: key); + super.key, + }); + final String header; + final Widget expandedChild; @override State createState() => _CustomExpandablePanelState(); @@ -39,7 +39,7 @@ class _CustomExpandablePanelState extends State { collapsed: Container(), header: Padding( padding: const EdgeInsets.only( - left: 15.0, + left: 15, ), child: Text( widget.header, @@ -48,8 +48,8 @@ class _CustomExpandablePanelState extends State { ), expanded: Padding( padding: const EdgeInsets.symmetric( - vertical: 5.0, - horizontal: 15.0, + vertical: 5, + horizontal: 15, ), child: widget.expandedChild, ), diff --git a/lib/widgets/reusable_widgets/custom_material_stepper.dart b/lib/widgets/reusable_widgets/custom_material_stepper.dart index b45313b7..4bb52b65 100644 --- a/lib/widgets/reusable_widgets/custom_material_stepper.dart +++ b/lib/widgets/reusable_widgets/custom_material_stepper.dart @@ -35,7 +35,7 @@ enum StepperType { } const TextStyle _kStepStyle = TextStyle( - fontSize: 23.0, + fontSize: 23, color: Colors.white, fontWeight: FontWeight.w400, ); @@ -45,7 +45,7 @@ const Color _kCircleActiveLight = Colors.white; const Color _kCircleActiveDark = Colors.black87; const Color _kDisabledLight = Colors.black38; const Color _kDisabledDark = Colors.white38; -const double _kStepSize = 40.0; +const double _kStepSize = 40; const double _kTriangleHeight = _kStepSize * 0.866025; // Triangle height. sqrt(3.0) / 2.0 @@ -64,8 +64,7 @@ class Step { /// The [title], [content], and [state] arguments must not be null. const Step({ required this.title, - this.subtitle, - required this.content, + required this.content, this.subtitle, this.state = StepState.indexed, this.isActive = false, }); @@ -114,8 +113,7 @@ class Stepper extends StatefulWidget { /// /// The [steps], [type], and [currentStep] arguments must not be null. const Stepper({ - Key? key, - required this.steps, + required this.steps, super.key, this.physics, this.type = StepperType.vertical, this.currentStep = 0, @@ -124,8 +122,7 @@ class Stepper extends StatefulWidget { this.onStepCancel, this.controlsBuilder, this.activeColor = AppColors.znnColor, - }) : assert(0 <= currentStep && currentStep < steps.length), - super(key: key); + }) : assert(0 <= currentStep && currentStep < steps.length); /// The color of the circle next to the name of the step when the step /// is selected or completed @@ -268,7 +265,7 @@ class _StepperState extends State with TickerProviderStateMixin { Widget _buildLine(bool visible) { return Container( width: visible ? 2.0 : 0.0, - height: 16.0, + height: 16, color: AppColors.darkSecondary, ); } @@ -290,13 +287,13 @@ class _StepperState extends State with TickerProviderStateMixin { return Icon( Icons.edit, color: isDarkActive ? _kCircleActiveDark : _kCircleActiveLight, - size: 18.0, + size: 18, ); case StepState.complete: return Icon( Icons.check, color: isDarkActive ? _kCircleActiveDark : _kCircleActiveLight, - size: 18.0, + size: 18, ); case StepState.error: return const Text('!', style: _kStepStyle); @@ -305,7 +302,7 @@ class _StepperState extends State with TickerProviderStateMixin { Widget _buildCircle(int index, bool oldState) { return Container( - margin: const EdgeInsets.symmetric(vertical: 8.0), + margin: const EdgeInsets.symmetric(vertical: 8), width: _kStepSize, height: _kStepSize, child: AnimatedContainer( @@ -321,7 +318,7 @@ class _StepperState extends State with TickerProviderStateMixin { ), child: Center( child: _buildCircleChild( - index, oldState && widget.steps[index].state == StepState.error), + index, oldState && widget.steps[index].state == StepState.error,), ), ), ); @@ -329,7 +326,7 @@ class _StepperState extends State with TickerProviderStateMixin { Widget _buildTriangle(int index, bool oldState) { return Container( - margin: const EdgeInsets.symmetric(vertical: 8.0), + margin: const EdgeInsets.symmetric(vertical: 8), width: _kStepSize, height: _kStepSize, child: Center( @@ -343,9 +340,9 @@ class _StepperState extends State with TickerProviderStateMixin { ), child: Align( alignment: const Alignment( - 0.0, 0.8), // 0.8 looks better than the geometrical 0.33. + 0, 0.8,), // 0.8 looks better than the geometrical 0.33. child: _buildCircleChild(index, - oldState && widget.steps[index].state != StepState.error), + oldState && widget.steps[index].state != StepState.error,), ), ), ), @@ -358,8 +355,8 @@ class _StepperState extends State with TickerProviderStateMixin { return AnimatedCrossFade( firstChild: _buildCircle(index, true), secondChild: _buildTriangle(index, true), - firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn), - secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn), + firstCurve: const Interval(0, 0.6, curve: Curves.fastOutSlowIn), + secondCurve: const Interval(0.4, 1, curve: Curves.fastOutSlowIn), sizeCurve: Curves.fastOutSlowIn, crossFadeState: widget.steps[index].state == StepState.error ? CrossFadeState.showSecond @@ -377,7 +374,7 @@ class _StepperState extends State with TickerProviderStateMixin { Widget _buildVerticalControls() { return const SizedBox( - height: 0.0, + height: 0, ); } @@ -430,7 +427,7 @@ class _StepperState extends State with TickerProviderStateMixin { ), if (widget.steps[index].subtitle != null) Container( - margin: const EdgeInsets.only(top: 2.0), + margin: const EdgeInsets.only(top: 2), child: AnimatedDefaultTextStyle( style: _subtitleStyle(index)!, duration: kThemeAnimationDuration, @@ -444,7 +441,7 @@ class _StepperState extends State with TickerProviderStateMixin { Widget _buildVerticalHeader(int index) { return Container( - margin: const EdgeInsets.symmetric(horizontal: 24.0), + margin: const EdgeInsets.symmetric(horizontal: 24), child: Row( children: [ Column( @@ -458,9 +455,9 @@ class _StepperState extends State with TickerProviderStateMixin { ), Expanded( child: Container( - margin: const EdgeInsetsDirectional.only(start: 12.0), + margin: const EdgeInsetsDirectional.only(start: 12), child: _buildHeaderText(index), - )), + ),), ], ), ); @@ -470,11 +467,11 @@ class _StepperState extends State with TickerProviderStateMixin { return Stack( children: [ PositionedDirectional( - start: 32.0, - top: 0.0, - bottom: 0.0, + start: 32, + top: 0, + bottom: 0, child: SizedBox( - width: 24.0, + width: 24, child: Center( child: SizedBox( width: _isLast(index) ? 0.0 : 2.0, @@ -486,12 +483,11 @@ class _StepperState extends State with TickerProviderStateMixin { ), ), AnimatedCrossFade( - firstChild: Container(height: 0.0), + firstChild: Container(height: 0), secondChild: Container( margin: const EdgeInsetsDirectional.only( - start: 40.0, - end: 24.0, - bottom: 0.0, + start: 40, + end: 24, ), child: Column( children: [ @@ -499,13 +495,13 @@ class _StepperState extends State with TickerProviderStateMixin { visible: index == widget.steps.length - 1 ? widget.steps[index].state != StepState.complete : true, - child: widget.steps[index].content), + child: widget.steps[index].content,), _buildVerticalControls(), ], ), ), - firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn), - secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn), + firstCurve: const Interval(0, 0.6, curve: Curves.fastOutSlowIn), + secondCurve: const Interval(0.4, 1, curve: Curves.fastOutSlowIn), sizeCurve: Curves.fastOutSlowIn, crossFadeState: _isCurrent(index) ? CrossFadeState.showSecond @@ -526,10 +522,10 @@ class _StepperState extends State with TickerProviderStateMixin { key: _keys[i], children: [ InkWell( - overlayColor: MaterialStateProperty.resolveWith((states) => - states.contains(MaterialState.hovered) + overlayColor: WidgetStateProperty.resolveWith((Set states) => + states.contains(WidgetState.hovered) ? Colors.transparent - : null), + : null,), onTap: widget.steps[i].state != StepState.disabled ? () { // In the vertical case we need to scroll to the newly tapped @@ -568,13 +564,13 @@ class _StepperState extends State with TickerProviderStateMixin { child: Row( children: [ SizedBox( - height: 72.0, + height: 72, child: Center( child: _buildIcon(i), ), ), Container( - margin: const EdgeInsetsDirectional.only(start: 12.0), + margin: const EdgeInsetsDirectional.only(start: 12), child: _buildHeaderText(i), ), ], @@ -583,8 +579,8 @@ class _StepperState extends State with TickerProviderStateMixin { if (!_isLast(i)) Expanded( child: Container( - margin: const EdgeInsets.symmetric(horizontal: 8.0), - height: 1.0, + margin: const EdgeInsets.symmetric(horizontal: 8), + height: 1, color: Colors.grey.shade400, ), ), @@ -594,9 +590,9 @@ class _StepperState extends State with TickerProviderStateMixin { return Column( children: [ Material( - elevation: 2.0, + elevation: 2, child: Container( - margin: const EdgeInsets.symmetric(horizontal: 24.0), + margin: const EdgeInsets.symmetric(horizontal: 24), child: Row( children: children, ), @@ -605,7 +601,7 @@ class _StepperState extends State with TickerProviderStateMixin { Expanded( child: ListView( physics: widget.physics, - padding: const EdgeInsets.all(24.0), + padding: const EdgeInsets.all(24), children: [ Visibility( visible: widget.currentStep == widget.steps.length - 1 @@ -671,9 +667,9 @@ class _TrianglePainter extends CustomPainter { final double halfBase = size.width / 2.0; final double height = size.height; final List points = [ - Offset(0.0, height), + Offset(0, height), Offset(base, height), - Offset(halfBase, 0.0), + Offset(halfBase, 0), ]; canvas.drawPath( diff --git a/lib/widgets/reusable_widgets/custom_slider.dart b/lib/widgets/reusable_widgets/custom_slider.dart index fa4f8eff..ced248d6 100644 --- a/lib/widgets/reusable_widgets/custom_slider.dart +++ b/lib/widgets/reusable_widgets/custom_slider.dart @@ -8,11 +8,11 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; Path _downTriangle(double size, Offset thumbCenter, {bool invert = false}) { - final thumbPath = Path(); - final height = math.sqrt(3) / 2.0; - final centerHeight = size * height / 3.0; - final halfSize = size / 2.0; - final sign = invert ? -1.0 : 1.0; + final Path thumbPath = Path(); + final double height = math.sqrt(3) / 2.0; + final double centerHeight = size * height / 3.0; + final double halfSize = size / 2.0; + final double sign = invert ? -1.0 : 1.0; thumbPath.moveTo( thumbCenter.dx - halfSize, thumbCenter.dy + sign * centerHeight, @@ -35,8 +35,8 @@ Path _upTriangle(double size, Offset thumbCenter) => class _CustomThumbShape extends SliderComponentShape { const _CustomThumbShape(); - static const double _thumbSize = 4.0; - static const double _disabledThumbSize = 3.0; + static const double _thumbSize = 4; + static const double _disabledThumbSize = 3; @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { @@ -54,24 +54,22 @@ class _CustomThumbShape extends SliderComponentShape { void paint( PaintingContext context, Offset thumbCenter, { - Animation? activationAnimation, - required Animation enableAnimation, + required Animation enableAnimation, required SliderThemeData sliderTheme, Animation? activationAnimation, bool? isDiscrete, TextPainter? labelPainter, RenderBox? parentBox, - required SliderThemeData sliderTheme, TextDirection? textDirection, double? value, double? textScaleFactor, Size? sizeWithOverflow, }) { - final canvas = context.canvas; - final colorTween = ColorTween( + final Canvas canvas = context.canvas; + final ColorTween colorTween = ColorTween( begin: sliderTheme.disabledThumbColor, end: sliderTheme.thumbColor, ); - final size = _thumbSize * sizeTween.evaluate(enableAnimation); - final thumbPath = _downTriangle(size, thumbCenter); + final double size = _thumbSize * sizeTween.evaluate(enableAnimation); + final Path thumbPath = _downTriangle(size, thumbCenter); canvas.drawPath( thumbPath, Paint()..color = colorTween.evaluate(enableAnimation)!, @@ -82,9 +80,9 @@ class _CustomThumbShape extends SliderComponentShape { class _CustomValueIndicatorShape extends SliderComponentShape { const _CustomValueIndicatorShape(); - static const double _indicatorSize = 4.0; - static const double _disabledIndicatorSize = 3.0; - static const double _slideUpHeight = 40.0; + static const double _indicatorSize = 4; + static const double _disabledIndicatorSize = 3; + static const double _slideUpHeight = 40; @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { @@ -102,29 +100,27 @@ class _CustomValueIndicatorShape extends SliderComponentShape { Offset thumbCenter, { required Animation activationAnimation, required Animation enableAnimation, - bool? isDiscrete, - required TextPainter labelPainter, + required TextPainter labelPainter, required SliderThemeData sliderTheme, bool? isDiscrete, RenderBox? parentBox, - required SliderThemeData sliderTheme, TextDirection? textDirection, double? value, double? textScaleFactor, Size? sizeWithOverflow, }) { - final canvas = context.canvas; - final enableColor = ColorTween( + final Canvas canvas = context.canvas; + final ColorTween enableColor = ColorTween( begin: sliderTheme.disabledThumbColor, end: sliderTheme.valueIndicatorColor, ); - final slideUpTween = Tween( - begin: 0.0, + final Tween slideUpTween = Tween( + begin: 0, end: _slideUpHeight, ); - final size = _indicatorSize * sizeTween.evaluate(enableAnimation); - final slideUpOffset = - Offset(0.0, -slideUpTween.evaluate(activationAnimation)); - final thumbPath = _upTriangle(size, thumbCenter + slideUpOffset); - final paintColor = enableColor + final double size = _indicatorSize * sizeTween.evaluate(enableAnimation); + final Offset slideUpOffset = + Offset(0, -slideUpTween.evaluate(activationAnimation)); + final Path thumbPath = _upTriangle(size, thumbCenter + slideUpOffset); + final Color paintColor = enableColor .evaluate(enableAnimation)! .withAlpha((255.0 * activationAnimation.value).round()); canvas.drawPath( @@ -137,7 +133,7 @@ class _CustomValueIndicatorShape extends SliderComponentShape { Paint() ..color = paintColor ..style = PaintingStyle.stroke - ..strokeWidth = 2.0); + ..strokeWidth = 2.0,); labelPainter.paint( canvas, thumbCenter + @@ -148,12 +144,6 @@ class _CustomValueIndicatorShape extends SliderComponentShape { } class CustomSlider extends StatefulWidget { - final String description; - final double? startValue; - final double maxValue; - final Function callback; - final double min; - final Color activeColor; const CustomSlider({ required this.description, @@ -162,8 +152,14 @@ class CustomSlider extends StatefulWidget { required this.callback, this.min = 1.0, this.activeColor = AppColors.znnColor, - Key? key, - }) : super(key: key); + super.key, + }); + final String description; + final double? startValue; + final double maxValue; + final Function callback; + final double min; + final Color activeColor; @override State createState() => _CustomSliderState(); @@ -176,16 +172,16 @@ class _CustomSliderState extends State { Widget build(BuildContext context) { _discreteCustomValue ??= widget.startValue; - final theme = Theme.of(context); + final ThemeData theme = Theme.of(context); return Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Column( mainAxisSize: MainAxisSize.min, - children: [ + children: [ SliderTheme( data: theme.sliderTheme.copyWith( - trackHeight: 2.0, + trackHeight: 2, activeTrackColor: widget.activeColor, inactiveTrackColor: theme.colorScheme.onSurface.withOpacity(0.5), @@ -208,9 +204,9 @@ class _CustomSliderState extends State { min: widget.min, max: widget.maxValue, divisions: (widget.maxValue - widget.min).toInt(), - semanticFormatterCallback: (value) => value.round().toString(), + semanticFormatterCallback: (double value) => value.round().toString(), label: '${_discreteCustomValue!.round()}', - onChanged: (value) { + onChanged: (double value) { setState(() { _discreteCustomValue = value; widget.callback(value); diff --git a/lib/widgets/reusable_widgets/custom_table.dart b/lib/widgets/reusable_widgets/custom_table.dart index fb9fda09..169ad303 100644 --- a/lib/widgets/reusable_widgets/custom_table.dart +++ b/lib/widgets/reusable_widgets/custom_table.dart @@ -8,11 +8,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CustomTable extends StatefulWidget { - final List? items; - final List? headerColumns; - final List Function(T, bool) generateRowCells; - final VoidCallback? onShowMoreButtonPressed; - final void Function(int index)? onRowTappedCallback; const CustomTable({ required this.items, @@ -20,8 +15,13 @@ class CustomTable extends StatefulWidget { this.headerColumns, this.onShowMoreButtonPressed, this.onRowTappedCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final List? items; + final List? headerColumns; + final List Function(T, bool) generateRowCells; + final VoidCallback? onShowMoreButtonPressed; + final void Function(int index)? onRowTappedCallback; @override State createState() => _CustomTableState(); @@ -35,7 +35,7 @@ class _CustomTableState extends State> { @override Widget build(BuildContext context) { return Column( - children: [ + children: [ Visibility( visible: widget.headerColumns != null, child: _getTableHeader(), @@ -47,7 +47,7 @@ class _CustomTableState extends State> { controller: _scrollController, shrinkWrap: true, children: widget.onShowMoreButtonPressed != null - ? _getRows() + [_getShowMoreButton()] + ? _getRows() + [_getShowMoreButton()] : _getRows(), ), ), @@ -71,28 +71,27 @@ class _CustomTableState extends State> { border: Border( bottom: BorderSide( color: Theme.of(context).dividerTheme.color!, - width: 1.0, ), ), ), padding: const EdgeInsets.symmetric( - vertical: 15.0, + vertical: 15, ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + - (widget.headerColumns ?? []), + (widget.headerColumns ?? []), ), ); } Widget _getTableRow(dynamic item, int indexOfRow) { - bool isSelected = _selectedRowIndex == indexOfRow; + final bool isSelected = _selectedRowIndex == indexOfRow; return InkWell( onTap: () { @@ -120,20 +119,20 @@ class _CustomTableState extends State> { left: isSelected ? const BorderSide( color: AppColors.znnColor, - width: 2.0, + width: 2, ) : BorderSide.none, ), ), padding: const EdgeInsets.symmetric( - vertical: 15.0, + vertical: 15, ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + widget.generateRowCells(item, isSelected), @@ -165,18 +164,18 @@ class _CustomTableState extends State> { } class CustomHeaderColumn extends StatelessWidget { - final String columnName; - final Function(String)? onSortArrowsPressed; - final MainAxisAlignment contentAlign; - final int flex; const CustomHeaderColumn({ required this.columnName, this.onSortArrowsPressed, this.contentAlign = MainAxisAlignment.start, this.flex = 1, - Key? key, - }) : super(key: key); + super.key, + }); + final String columnName; + final Function(String)? onSortArrowsPressed; + final MainAxisAlignment contentAlign; + final int flex; @override Widget build(BuildContext context) { @@ -184,7 +183,7 @@ class CustomHeaderColumn extends StatelessWidget { flex: flex, child: Row( mainAxisAlignment: contentAlign, - children: [ + children: [ Text( columnName, style: Theme.of(context).textTheme.bodyMedium, @@ -195,11 +194,11 @@ class CustomHeaderColumn extends StatelessWidget { onTap: () => onSortArrowsPressed!(columnName), child: Icon( Entypo.select_arrows, - size: 15.0, + size: 15, color: Theme.of(context).iconTheme.color, ), ), - ) + ), ], ), ); @@ -207,29 +206,27 @@ class CustomHeaderColumn extends StatelessWidget { } class CustomTableCell extends StatelessWidget { - final Widget child; - final int flex; const CustomTableCell( this.child, { this.flex = 1, - Key? key, - }) : super(key: key); + super.key, + }); CustomTableCell.tooltipWithMarquee( Address address, { - Key? key, + super.key, TextStyle? textStyle, this.flex = 1, Color textColor = AppColors.subtitleColor, }) : child = Row( - children: [ + children: [ Expanded( child: Tooltip( message: address.toString(), child: Container( margin: const EdgeInsets.only( - right: 10.0, + right: 10, ), child: Marquee( child: Text( @@ -237,7 +234,7 @@ class CustomTableCell extends StatelessWidget { style: textStyle ?? TextStyle( color: textColor, - fontSize: 12.0, + fontSize: 12, ), ), ), @@ -249,25 +246,24 @@ class CustomTableCell extends StatelessWidget { materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], - ), - super(key: key); + ); CustomTableCell.withMarquee( String text, { - Key? key, + super.key, bool showCopyToClipboardIcon = true, TextStyle? textStyle, this.flex = 1, Color textColor = AppColors.subtitleColor, }) : child = Row( - children: [ + children: [ Expanded( child: Container( margin: const EdgeInsets.only( - right: 10.0, + right: 10, ), child: Marquee( child: Text( @@ -275,7 +271,7 @@ class CustomTableCell extends StatelessWidget { style: textStyle ?? TextStyle( color: textColor, - fontSize: 12.0, + fontSize: 12, ), ), ), @@ -284,32 +280,31 @@ class CustomTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( text, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), ), ], - ), - super(key: key); + ); CustomTableCell.tooltipWithText( BuildContext context, Address? address, { - Key? key, + super.key, bool showCopyToClipboardIcon = false, TextStyle? textStyle, this.flex = 1, Color textColor = AppColors.subtitleColor, TextAlign textAlign = TextAlign.start, }) : child = Row( - children: [ + children: [ Expanded( child: Tooltip( message: address.toString(), @@ -327,32 +322,31 @@ class CustomTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( address.toString(), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), ), ], - ), - super(key: key); + ); CustomTableCell.withText( BuildContext context, String text, { - Key? key, + super.key, bool showCopyToClipboardIcon = false, TextStyle? textStyle, this.flex = 1, Color textColor = AppColors.subtitleColor, TextAlign textAlign = TextAlign.start, }) : child = Row( - children: [ + children: [ Expanded( child: Text( text, @@ -366,20 +360,21 @@ class CustomTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( text, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), ), ], - ), - super(key: key); + ); + final Widget child; + final int flex; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/dialogs.dart b/lib/widgets/reusable_widgets/dialogs.dart index 4a087eaa..445125e6 100644 --- a/lib/widgets/reusable_widgets/dialogs.dart +++ b/lib/widgets/reusable_widgets/dialogs.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; -showWarningDialog({ +Future showWarningDialog({ required BuildContext context, required String title, required String description, @@ -11,22 +11,22 @@ showWarningDialog({ bool isPressed = false; await showDialog( context: context, - builder: (context) => AlertDialog( + builder: (BuildContext context) => AlertDialog( icon: const Icon( Icons.warning, - size: 24.0, + size: 24, color: Colors.orange, ), title: Text(title), content: Text(description), - actions: [ + actions: [ TextButton( onPressed: onActionButtonPressed ?? () { Navigator.pop(context); }, style: const ButtonStyle( - backgroundColor: MaterialStatePropertyAll(Colors.amber), + backgroundColor: WidgetStatePropertyAll(Colors.amber), ), child: Text( 'Cancel', @@ -40,13 +40,13 @@ showWarningDialog({ Navigator.pop(context); }, style: const ButtonStyle( - backgroundColor: MaterialStatePropertyAll(Colors.orange), + backgroundColor: WidgetStatePropertyAll(Colors.orange), ), child: Text( buttonText.isEmpty ? 'OK' : buttonText, style: Theme.of(context).textTheme.bodyMedium, ), - ) + ), ], ), barrierDismissible: false, @@ -54,7 +54,7 @@ showWarningDialog({ return isPressed; } -showDialogWithNoAndYesOptions({ +Future showDialogWithNoAndYesOptions({ required BuildContext context, required String title, required VoidCallback onYesButtonPressed, @@ -66,10 +66,10 @@ showDialogWithNoAndYesOptions({ showDialog( barrierDismissible: isBarrierDismissible, context: context, - builder: (context) => AlertDialog( + builder: (BuildContext context) => AlertDialog( title: Text(title), content: content ?? Text(description!), - actions: [ + actions: [ TextButton( onPressed: () { onNoButtonPressed?.call(); @@ -82,8 +82,8 @@ showDialogWithNoAndYesOptions({ ), TextButton( style: Theme.of(context).textButtonTheme.style!.copyWith( - backgroundColor: MaterialStateColor.resolveWith( - (states) => AppColors.errorColor), + backgroundColor: WidgetStateColor.resolveWith( + (Set states) => AppColors.errorColor,), ), onPressed: () { onYesButtonPressed.call(); @@ -98,15 +98,15 @@ showDialogWithNoAndYesOptions({ ), ); -showCustomDialog({required BuildContext context, required Widget content}) => +Future showCustomDialog({required BuildContext context, required Widget content}) => showGeneralDialog( context: context, barrierLabel: '', barrierDismissible: true, - pageBuilder: (context, Animation animation, - Animation secondaryAnimation) => + pageBuilder: (BuildContext context, Animation animation, + Animation secondaryAnimation,) => Center( child: ClipRRect( - borderRadius: BorderRadius.circular(15.0), child: content), + borderRadius: BorderRadius.circular(15), child: content,), ), ); diff --git a/lib/widgets/reusable_widgets/dotted_border_info_widget.dart b/lib/widgets/reusable_widgets/dotted_border_info_widget.dart index d379c9b2..911cb79c 100644 --- a/lib/widgets/reusable_widgets/dotted_border_info_widget.dart +++ b/lib/widgets/reusable_widgets/dotted_border_info_widget.dart @@ -4,14 +4,14 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class DottedBorderInfoWidget extends StatefulWidget { - final String text; - final Color borderColor; const DottedBorderInfoWidget({ required this.text, this.borderColor = AppColors.znnColor, - Key? key, - }) : super(key: key); + super.key, + }); + final String text; + final Color borderColor; @override State createState() => _DottedBorderInfoWidgetState(); @@ -21,19 +21,19 @@ class _DottedBorderInfoWidgetState extends State { @override Widget build(BuildContext context) { return DottedBorder( - padding: const EdgeInsets.all(5.0), + padding: const EdgeInsets.all(5), color: widget.borderColor, borderType: BorderType.RRect, - radius: const Radius.circular(6.0), - dashPattern: const [3.0], - strokeWidth: 2.0, + radius: const Radius.circular(6), + dashPattern: const [3], + strokeWidth: 2, child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( MaterialCommunityIcons.exclamation_thick, - size: 25.0, + size: 25, color: widget.borderColor, ), Flexible( @@ -44,7 +44,7 @@ class _DottedBorderInfoWidgetState extends State { ), ), const SizedBox( - width: 10.0, + width: 10, ), ], ), diff --git a/lib/widgets/reusable_widgets/dropdown/addresses_dropdown.dart b/lib/widgets/reusable_widgets/dropdown/addresses_dropdown.dart index 65546f19..da6de00f 100644 --- a/lib/widgets/reusable_widgets/dropdown/addresses_dropdown.dart +++ b/lib/widgets/reusable_widgets/dropdown/addresses_dropdown.dart @@ -4,27 +4,27 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; class AddressesDropdown extends StatelessWidget { - final Function(String?)? onChangedCallback; - final String? _selectedSelfAddress; const AddressesDropdown( this._selectedSelfAddress, this.onChangedCallback, { - Key? key, - }) : super(key: key); + super.key, + }); + final Function(String?)? onChangedCallback; + final String? _selectedSelfAddress; @override Widget build(BuildContext context) { return Tooltip( - message: _selectedSelfAddress!, + message: _selectedSelfAddress, child: FocusableActionDetector( mouseCursor: SystemMouseCursors.click, child: Container( padding: const EdgeInsets.only( - left: 10.0, + left: 10, ), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5), color: Theme.of(context).inputDecorationTheme.fillColor, ), child: DropdownButtonHideUnderline( @@ -32,14 +32,14 @@ class AddressesDropdown extends StatelessWidget { isExpanded: true, icon: Container( margin: const EdgeInsets.symmetric( - horizontal: 10.0, + horizontal: 10, ), padding: const EdgeInsets.only( right: 7.5, ), child: Icon( SimpleLineIcons.arrow_down, - size: 10.0, + size: 10, color: onChangedCallback != null ? AppColors.znnColor : AppColors.lightSecondary, diff --git a/lib/widgets/reusable_widgets/dropdown/basic_dropdown.dart b/lib/widgets/reusable_widgets/dropdown/basic_dropdown.dart index 7ee2fa1c..f4ca909a 100644 --- a/lib/widgets/reusable_widgets/dropdown/basic_dropdown.dart +++ b/lib/widgets/reusable_widgets/dropdown/basic_dropdown.dart @@ -4,26 +4,26 @@ import 'package:zenon_syrius_wallet_flutter/model/basic_dropdown_item.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class BasicDropdown extends StatelessWidget { - final String _hint; - final BasicDropdownItem? _selectedValue; - final List> _items; - final Function(BasicDropdownItem?)? onChangedCallback; const BasicDropdown( this._hint, this._selectedValue, this._items, this.onChangedCallback, { - Key? key, - }) : super(key: key); + super.key, + }); + final String _hint; + final BasicDropdownItem? _selectedValue; + final List> _items; + final Function(BasicDropdownItem?)? onChangedCallback; @override Widget build(BuildContext context) { return Container( - padding: const EdgeInsets.only(left: 10.0), + padding: const EdgeInsets.only(left: 10), decoration: BoxDecoration( color: Theme.of(context).inputDecorationTheme.fillColor, - borderRadius: BorderRadius.circular(5.0), + borderRadius: BorderRadius.circular(5), ), child: DropdownButtonHideUnderline( child: DropdownButton>( @@ -32,10 +32,10 @@ class BasicDropdown extends StatelessWidget { style: Theme.of(context).inputDecorationTheme.hintStyle, ), icon: Container( - margin: const EdgeInsets.fromLTRB(10.0, 0.0, 17.5, 0.0), + margin: const EdgeInsets.fromLTRB(10, 0, 17.5, 0), child: Icon( SimpleLineIcons.arrow_down, - size: 10.0, + size: 10, color: _selectedValue != null ? AppColors.znnColor : AppColors.lightSecondary, diff --git a/lib/widgets/reusable_widgets/dropdown/coin_dropdown.dart b/lib/widgets/reusable_widgets/dropdown/coin_dropdown.dart index 389a0170..db6fa1bc 100644 --- a/lib/widgets/reusable_widgets/dropdown/coin_dropdown.dart +++ b/lib/widgets/reusable_widgets/dropdown/coin_dropdown.dart @@ -6,16 +6,16 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class CoinDropdown extends StatelessWidget { - final Function(Token?) _onChangeCallback; - final Token _selectedToken; - final List _availableTokens; const CoinDropdown( this._availableTokens, this._selectedToken, this._onChangeCallback, { - Key? key, - }) : super(key: key); + super.key, + }); + final Function(Token?) _onChangeCallback; + final Token _selectedToken; + final List _availableTokens; @override Widget build(BuildContext context) { @@ -27,7 +27,7 @@ class CoinDropdown extends StatelessWidget { child: DropdownButton( value: _selectedToken, isDense: true, - selectedItemBuilder: (context) { + selectedItemBuilder: (BuildContext context) { return _availableTokens .map( (Token? e) => Container( @@ -39,9 +39,9 @@ class CoinDropdown extends StatelessWidget { color: ColorUtils.getTokenColor(e!.tokenStandard), ), child: Padding( - padding: const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only(left: 8), child: Row( - children: [ + children: [ Text( e.symbol, style: Theme.of(context) @@ -53,14 +53,14 @@ class CoinDropdown extends StatelessWidget { ), const Padding( padding: EdgeInsets.symmetric( - horizontal: 5.0, + horizontal: 5, ), child: Icon( SimpleLineIcons.arrow_down, - size: 8.0, + size: 8, color: Colors.white, ), - ) + ), ], ), ), diff --git a/lib/widgets/reusable_widgets/error_widget.dart b/lib/widgets/reusable_widgets/error_widget.dart index b248dd48..47b4dbee 100644 --- a/lib/widgets/reusable_widgets/error_widget.dart +++ b/lib/widgets/reusable_widgets/error_widget.dart @@ -2,27 +2,27 @@ import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; class SyriusErrorWidget extends StatelessWidget { - static const String route = 'syrius-error-widget'; - - final Object error; const SyriusErrorWidget( this.error, { - Key? key, - }) : super(key: key); + super.key, + }); + static const String route = 'syrius-error-widget'; + + final Object error; @override Widget build(BuildContext context) { return Center( child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: SingleChildScrollView( child: Column( - children: [ + children: [ Lottie.asset( 'assets/lottie/ic_anim_no_data.json', - width: 32.0, - height: 32.0, + width: 32, + height: 32, ), Text( _getErrorText(error.toString()), diff --git a/lib/widgets/reusable_widgets/exchange_rate_widget.dart b/lib/widgets/reusable_widgets/exchange_rate_widget.dart index 9e230865..014129cd 100644 --- a/lib/widgets/reusable_widgets/exchange_rate_widget.dart +++ b/lib/widgets/reusable_widgets/exchange_rate_widget.dart @@ -4,12 +4,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; class ExchangeRateWidget extends StatefulWidget { - final BigInt fromAmount; - final int fromDecimals; - final String fromSymbol; - final BigInt toAmount; - final int toDecimals; - final String toSymbol; const ExchangeRateWidget({ required this.fromAmount, @@ -18,8 +12,14 @@ class ExchangeRateWidget extends StatefulWidget { required this.toAmount, required this.toDecimals, required this.toSymbol, - Key? key, - }) : super(key: key); + super.key, + }); + final BigInt fromAmount; + final int fromDecimals; + final String fromSymbol; + final BigInt toAmount; + final int toDecimals; + final String toSymbol; @override State createState() => _ExchangeRateWidgetState(); @@ -33,14 +33,14 @@ class _ExchangeRateWidgetState extends State { return Visibility( visible: widget.fromAmount > BigInt.zero && widget.toAmount > BigInt.zero, child: Row( - children: [ + children: [ Text( _getFormattedRate(), style: - const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + const TextStyle(fontSize: 14, color: AppColors.subtitleColor), ), const SizedBox( - width: 5.0, + width: 5, ), MouseRegion( cursor: SystemMouseCursors.click, @@ -51,7 +51,7 @@ class _ExchangeRateWidgetState extends State { child: const Icon( Icons.swap_horiz, color: AppColors.subtitleColor, - size: 22.0, + size: 22, ), ), ), @@ -64,17 +64,17 @@ class _ExchangeRateWidgetState extends State { if (widget.fromAmount <= BigInt.zero || widget.toAmount <= BigInt.zero) { return '-'; } - final fromAmountWithDecimals = BigDecimal.createAndStripZerosForScale( - widget.fromAmount, widget.fromDecimals, widget.fromDecimals); - final toAmountWithDecimals = BigDecimal.createAndStripZerosForScale( - widget.toAmount, widget.toDecimals, widget.toDecimals); + final BigDecimal fromAmountWithDecimals = BigDecimal.createAndStripZerosForScale( + widget.fromAmount, widget.fromDecimals, widget.fromDecimals,); + final BigDecimal toAmountWithDecimals = BigDecimal.createAndStripZerosForScale( + widget.toAmount, widget.toDecimals, widget.toDecimals,); if (_isToggled) { - final rate = (fromAmountWithDecimals.divide(toAmountWithDecimals, - roundingMode: RoundingMode.DOWN)); + final BigDecimal rate = fromAmountWithDecimals.divide(toAmountWithDecimals, + roundingMode: RoundingMode.DOWN,); return '1 ${widget.toSymbol} = ${rate.toDouble().toStringFixedNumDecimals(5)} ${widget.fromSymbol}'; } else { - final rate = (toAmountWithDecimals.divide(fromAmountWithDecimals, - roundingMode: RoundingMode.DOWN)); + final BigDecimal rate = toAmountWithDecimals.divide(fromAmountWithDecimals, + roundingMode: RoundingMode.DOWN,); return '1 ${widget.fromSymbol} = ${rate.toDouble().toStringFixedNumDecimals(5)} ${widget.toSymbol}'; } } diff --git a/lib/widgets/reusable_widgets/formatted_amount_with_tooltip.dart b/lib/widgets/reusable_widgets/formatted_amount_with_tooltip.dart index 4b449cbc..ea4e1142 100644 --- a/lib/widgets/reusable_widgets/formatted_amount_with_tooltip.dart +++ b/lib/widgets/reusable_widgets/formatted_amount_with_tooltip.dart @@ -3,17 +3,10 @@ import 'package:intl/intl.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; class FormattedAmountWithTooltip extends Tooltip { - final String amount; - final String tokenSymbol; - final Widget Function(String, String) builder; FormattedAmountWithTooltip({ - Key? key, - required this.amount, - required this.tokenSymbol, - required this.builder, + required this.amount, required this.tokenSymbol, required this.builder, super.key, }) : super( - key: key, message: '$amount $tokenSymbol', child: builder( amount.toNum() == 0 @@ -23,6 +16,9 @@ class FormattedAmountWithTooltip extends Tooltip { : NumberFormat.compact().format(amount.toNum()).length > 8 ? '…' : NumberFormat.compact().format(amount.toNum()), - tokenSymbol), + tokenSymbol,), ); + final String amount; + final String tokenSymbol; + final Widget Function(String, String) builder; } diff --git a/lib/widgets/reusable_widgets/icons/clear_icon.dart b/lib/widgets/reusable_widgets/icons/clear_icon.dart index da2dd723..4ca46197 100644 --- a/lib/widgets/reusable_widgets/icons/clear_icon.dart +++ b/lib/widgets/reusable_widgets/icons/clear_icon.dart @@ -3,17 +3,13 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; class ClearIcon extends RawMaterialButton { ClearIcon({ - Key? key, - required VoidCallback onPressed, - required BuildContext context, + required VoidCallback super.onPressed, required BuildContext context, super.key, }) : super( - key: key, - onPressed: onPressed, shape: const CircleBorder(), child: Icon( SimpleLineIcons.close, color: Theme.of(context).colorScheme.secondary, - size: 20.0, + size: 20, ), ); } diff --git a/lib/widgets/reusable_widgets/icons/copy_to_clipboard_icon.dart b/lib/widgets/reusable_widgets/icons/copy_to_clipboard_icon.dart index 4bf0638b..58b0f7b5 100644 --- a/lib/widgets/reusable_widgets/icons/copy_to_clipboard_icon.dart +++ b/lib/widgets/reusable_widgets/icons/copy_to_clipboard_icon.dart @@ -5,12 +5,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/clipboard_utils.dart'; class CopyToClipboardIcon extends StatefulWidget { - final String? textToBeCopied; - final Color iconColor; - final Color? hoverColor; - final MaterialTapTargetSize materialTapTargetSize; - final IconData icon; - final EdgeInsets padding; const CopyToClipboardIcon( this.textToBeCopied, { @@ -18,16 +12,22 @@ class CopyToClipboardIcon extends StatefulWidget { this.hoverColor, this.materialTapTargetSize = MaterialTapTargetSize.padded, this.icon = Icons.content_copy, - this.padding = const EdgeInsets.all(8.0), - Key? key, - }) : super(key: key); + this.padding = const EdgeInsets.all(8), + super.key, + }); + final String? textToBeCopied; + final Color iconColor; + final Color? hoverColor; + final MaterialTapTargetSize materialTapTargetSize; + final IconData icon; + final EdgeInsets padding; @override State createState() => _CopyToClipboardIcon(); } class _CopyToClipboardIcon extends State { - final _iconSize = 15.0; + final double _iconSize = 15; bool _isCopied = false; @override diff --git a/lib/widgets/reusable_widgets/icons/icons.dart b/lib/widgets/reusable_widgets/icons/icons.dart index 8f4beae2..2dc39289 100644 --- a/lib/widgets/reusable_widgets/icons/icons.dart +++ b/lib/widgets/reusable_widgets/icons/icons.dart @@ -1,3 +1,3 @@ export 'copy_to_clipboard_icon.dart'; -export 'standard_tooltip_icon.dart'; export 'link_icon.dart'; +export 'standard_tooltip_icon.dart'; diff --git a/lib/widgets/reusable_widgets/icons/link_icon.dart b/lib/widgets/reusable_widgets/icons/link_icon.dart index db565b39..0fe7d2b7 100644 --- a/lib/widgets/reusable_widgets/icons/link_icon.dart +++ b/lib/widgets/reusable_widgets/icons/link_icon.dart @@ -5,27 +5,26 @@ import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; class LinkIcon extends RawMaterialButton { LinkIcon({ required String url, - Key? key}) + super.key,}) : super( - key: key, constraints: const BoxConstraints( - minWidth: 40.0, - minHeight: 40.0, + minWidth: 40, + minHeight: 40, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: const CircleBorder(), onPressed: () => NavigationUtils.openUrl(url), child: Container( - height: 25.0, - width: 25.0, - padding: const EdgeInsets.all(4.0), + height: 25, + width: 25, + padding: const EdgeInsets.all(4), decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white12, ), child: const Icon( SimpleLineIcons.link, - size: 10.0, + size: 10, color: AppColors.znnColor, ), ), diff --git a/lib/widgets/reusable_widgets/icons/standard_tooltip_icon.dart b/lib/widgets/reusable_widgets/icons/standard_tooltip_icon.dart index f01f03f8..24e9fef7 100644 --- a/lib/widgets/reusable_widgets/icons/standard_tooltip_icon.dart +++ b/lib/widgets/reusable_widgets/icons/standard_tooltip_icon.dart @@ -2,24 +2,24 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class StandardTooltipIcon extends StatelessWidget { - final String tooltipMessage; - final Color iconColor; - final IconData iconData; const StandardTooltipIcon( this.tooltipMessage, this.iconData, { this.iconColor = AppColors.znnColor, - Key? key, - }) : super(key: key); + super.key, + }); + final String tooltipMessage; + final Color iconColor; + final IconData iconData; @override Widget build(BuildContext context) { return IconButton( hoverColor: Colors.transparent, - padding: const EdgeInsets.all(4.0), + padding: const EdgeInsets.all(4), constraints: const BoxConstraints(), - iconSize: 15.0, + iconSize: 15, icon: Icon( iconData, color: iconColor, diff --git a/lib/widgets/reusable_widgets/important_text_container.dart b/lib/widgets/reusable_widgets/important_text_container.dart index 31fc8981..e8bdf224 100644 --- a/lib/widgets/reusable_widgets/important_text_container.dart +++ b/lib/widgets/reusable_widgets/important_text_container.dart @@ -2,16 +2,16 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class ImportantTextContainer extends StatelessWidget { - final String text; - final bool showBorder; - final bool isSelectable; const ImportantTextContainer({ required this.text, this.showBorder = false, this.isSelectable = false, - Key? key, - }) : super(key: key); + super.key, + }); + final String text; + final bool showBorder; + final bool isSelectable; @override Widget build(BuildContext context) { @@ -20,30 +20,29 @@ class ImportantTextContainer extends StatelessWidget { color: Theme.of(context).colorScheme.primary, border: showBorder ? Border.all( - width: 1.0, color: AppColors.errorColor, ) : null, borderRadius: const BorderRadius.all( - Radius.circular(8.0), + Radius.circular(8), ), ), child: Padding( - padding: const EdgeInsets.fromLTRB(15.0, 20.0, 15.0, 20.0), + padding: const EdgeInsets.fromLTRB(15, 20, 15, 20), child: Row( - children: [ + children: [ const Icon( Icons.info, - size: 20.0, + size: 20, color: Colors.white, ), const SizedBox( - width: 15.0, + width: 15, ), Expanded( child: isSelectable - ? SelectableText(text, style: const TextStyle(fontSize: 14.0)) - : Text(text, style: const TextStyle(fontSize: 14.0)), + ? SelectableText(text, style: const TextStyle(fontSize: 14)) + : Text(text, style: const TextStyle(fontSize: 14)), ), ], ), diff --git a/lib/widgets/reusable_widgets/infinite_scroll_table.dart b/lib/widgets/reusable_widgets/infinite_scroll_table.dart index b9b9cd8e..944f3753 100644 --- a/lib/widgets/reusable_widgets/infinite_scroll_table.dart +++ b/lib/widgets/reusable_widgets/infinite_scroll_table.dart @@ -12,11 +12,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class InfiniteScrollTable extends StatefulWidget { - final List? headerColumns; - final List Function(T, bool) generateRowCells; - final void Function(int index)? onRowTappedCallback; - final InfiniteScrollBloc bloc; - final bool disposeBloc; const InfiniteScrollTable({ required this.bloc, @@ -24,8 +19,13 @@ class InfiniteScrollTable extends StatefulWidget { this.headerColumns, this.onRowTappedCallback, this.disposeBloc = true, - Key? key, - }) : super(key: key); + super.key, + }); + final List? headerColumns; + final List Function(T, bool) generateRowCells; + final void Function(int index)? onRowTappedCallback; + final InfiniteScrollBloc bloc; + final bool disposeBloc; @override State createState() => _InfiniteScrollTableState(); @@ -42,11 +42,11 @@ class _InfiniteScrollTableState extends State> { @override void initState() { - _pagingController.addPageRequestListener((pageKey) { + _pagingController.addPageRequestListener((int pageKey) { widget.bloc.onPageRequestSink.add(pageKey); }); _blocListingStateSubscription = - widget.bloc.onNewListingState.listen((listingState) { + widget.bloc.onNewListingState.listen((InfiniteScrollBlocListingState listingState) { _pagingController.value = PagingState( nextPageKey: listingState.nextPageKey, error: listingState.error, @@ -59,7 +59,7 @@ class _InfiniteScrollTableState extends State> { @override Widget build(BuildContext context) { return Column( - children: [ + children: [ Visibility( visible: widget.headerColumns != null, child: _getTableHeader(), @@ -71,7 +71,7 @@ class _InfiniteScrollTableState extends State> { scrollController: _scrollController, pagingController: _pagingController, builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (_, item, index) => _getTableRow( + itemBuilder: (_, item, int index) => _getTableRow( item, index, ), @@ -99,28 +99,27 @@ class _InfiniteScrollTableState extends State> { border: Border( bottom: BorderSide( color: Theme.of(context).dividerTheme.color!, - width: 1.0, ), ), ), padding: const EdgeInsets.symmetric( - vertical: 15.0, + vertical: 15, ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + - (widget.headerColumns ?? []), + (widget.headerColumns ?? []), ), ); } Widget _getTableRow(dynamic item, int indexOfRow) { - bool isSelected = _selectedRowIndex == indexOfRow; + final bool isSelected = _selectedRowIndex == indexOfRow; return InkWell( onTap: () { @@ -148,20 +147,20 @@ class _InfiniteScrollTableState extends State> { left: isSelected ? const BorderSide( color: AppColors.znnColor, - width: 2.0, + width: 2, ) : BorderSide.none, ), ), padding: const EdgeInsets.symmetric( - vertical: 15.0, + vertical: 15, ), child: Row( children: List.from( - [ + [ const SizedBox( - width: 20.0, - ) + width: 20, + ), ], ) + widget.generateRowCells(item, isSelected), @@ -183,18 +182,18 @@ class _InfiniteScrollTableState extends State> { } class InfiniteScrollTableHeaderColumn extends StatelessWidget { - final String columnName; - final Function(String)? onSortArrowsPressed; - final MainAxisAlignment contentAlign; - final int flex; const InfiniteScrollTableHeaderColumn({ required this.columnName, this.onSortArrowsPressed, this.contentAlign = MainAxisAlignment.start, this.flex = 1, - Key? key, - }) : super(key: key); + super.key, + }); + final String columnName; + final Function(String)? onSortArrowsPressed; + final MainAxisAlignment contentAlign; + final int flex; @override Widget build(BuildContext context) { @@ -202,7 +201,7 @@ class InfiniteScrollTableHeaderColumn extends StatelessWidget { flex: flex, child: Row( mainAxisAlignment: contentAlign, - children: [ + children: [ Expanded( child: Text( columnName, @@ -215,11 +214,11 @@ class InfiniteScrollTableHeaderColumn extends StatelessWidget { onTap: () => onSortArrowsPressed!(columnName), child: Icon( Entypo.select_arrows, - size: 15.0, + size: 15, color: Theme.of(context).iconTheme.color, ), ), - ) + ), ], ), ); @@ -227,14 +226,12 @@ class InfiniteScrollTableHeaderColumn extends StatelessWidget { } class InfiniteScrollTableCell extends StatelessWidget { - final Widget child; - final int flex; const InfiniteScrollTableCell( this.child, { this.flex = 1, - Key? key, - }) : super(key: key); + super.key, + }); factory InfiniteScrollTableCell.tooltipWithMarquee( Address address, { @@ -245,13 +242,13 @@ class InfiniteScrollTableCell extends StatelessWidget { }) => InfiniteScrollTableCell( Row( - children: [ + children: [ Expanded( child: Tooltip( message: address.toString(), child: Container( margin: const EdgeInsets.only( - right: 10.0, + right: 10, ), child: Marquee( child: Text( @@ -259,7 +256,7 @@ class InfiniteScrollTableCell extends StatelessWidget { style: textStyle ?? TextStyle( color: textColor, - fontSize: 12.0, + fontSize: 12, ), ), ), @@ -271,7 +268,7 @@ class InfiniteScrollTableCell extends StatelessWidget { materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), @@ -289,11 +286,11 @@ class InfiniteScrollTableCell extends StatelessWidget { }) => InfiniteScrollTableCell( Row( - children: [ + children: [ Expanded( child: Container( margin: const EdgeInsets.only( - right: 10.0, + right: 10, ), child: Marquee( child: Text( @@ -301,7 +298,7 @@ class InfiniteScrollTableCell extends StatelessWidget { style: textStyle ?? TextStyle( color: textColor, - fontSize: 12.0, + fontSize: 12, ), ), ), @@ -310,13 +307,13 @@ class InfiniteScrollTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( text, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), @@ -339,7 +336,7 @@ class InfiniteScrollTableCell extends StatelessWidget { }) => InfiniteScrollTableCell( Row( - children: [ + children: [ Expanded( child: Tooltip( message: address.toString(), @@ -357,13 +354,13 @@ class InfiniteScrollTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( address.toString(), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), @@ -386,7 +383,7 @@ class InfiniteScrollTableCell extends StatelessWidget { }) => InfiniteScrollTableCell( Row( - children: [ + children: [ Expanded( child: Text( text, @@ -400,13 +397,13 @@ class InfiniteScrollTableCell extends StatelessWidget { Visibility( visible: showCopyToClipboardIcon, child: Row( - children: [ + children: [ CopyToClipboardIcon( text, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 10.0, + width: 10, ), ], ), @@ -416,6 +413,8 @@ class InfiniteScrollTableCell extends StatelessWidget { flex: flex, key: key, ); + final Widget child; + final int flex; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/input_fields/amount_input_field.dart b/lib/widgets/reusable_widgets/input_fields/amount_input_field.dart index 439bf688..63f7a948 100644 --- a/lib/widgets/reusable_widgets/input_fields/amount_input_field.dart +++ b/lib/widgets/reusable_widgets/input_fields/amount_input_field.dart @@ -10,14 +10,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/input_field import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AmountInputField extends StatefulWidget { - final TextEditingController controller; - final AccountInfo accountInfo; - final void Function(Token, bool)? onChanged; - final double? valuePadding; - final Color? textColor; - final Token? initialToken; - final String hintText; - final bool enabled; const AmountInputField({ required this.controller, @@ -28,8 +20,16 @@ class AmountInputField extends StatefulWidget { this.initialToken, this.hintText = 'Amount', this.enabled = true, - Key? key, - }) : super(key: key); + super.key, + }); + final TextEditingController controller; + final AccountInfo accountInfo; + final void Function(Token, bool)? onChanged; + final double? valuePadding; + final Color? textColor; + final Token? initialToken; + final String hintText; + final bool enabled; @override State createState() { @@ -38,7 +38,7 @@ class AmountInputField extends StatefulWidget { } class _AmountInputFieldState extends State { - final List _tokensWithBalance = []; + final List _tokensWithBalance = []; Token? _selectedToken; @override @@ -55,13 +55,13 @@ class _AmountInputFieldState extends State { key: widget.key, autovalidateMode: AutovalidateMode.onUserInteraction, child: InputField( - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputFormatters: FormatUtils.getAmountTextInputFormatters( widget.controller.text, ), - validator: (value) => InputValidators.correctValue( + validator: (String? value) => InputValidators.correctValue( value, widget.accountInfo.getBalance( _selectedToken!.tokenStandard, @@ -85,38 +85,38 @@ class _AmountInputFieldState extends State { return Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, - children: [ + children: [ _getCoinDropdown(), const SizedBox( - width: 5.0, + width: 5, ), AmountSuffixMaxWidget( - onPressed: () => _onMaxPressed(), + onPressed: _onMaxPressed, context: context, ), const SizedBox( - width: 5.0, + width: 5, ), ], ); } void _onMaxPressed() => setState(() { - final maxBalance = widget.accountInfo.getBalance( + final BigInt maxBalance = widget.accountInfo.getBalance( _selectedToken!.tokenStandard, ); widget.controller.text = - maxBalance.addDecimals(_selectedToken!.decimals).toString(); + maxBalance.addDecimals(_selectedToken!.decimals); }); Widget _getCoinDropdown() => CoinDropdown( _tokensWithBalance, _selectedToken!, - (value) { + (Token? value) { if (_selectedToken != value) { setState( () { - _selectedToken = value!; + _selectedToken = value; _isInputValid(); widget.onChanged!(_selectedToken!, _isInputValid()); }, @@ -126,7 +126,7 @@ class _AmountInputFieldState extends State { ); void _addTokensWithBalance() { - for (var balanceInfo in widget.accountInfo.balanceInfoList!) { + for (final BalanceInfoListItem balanceInfo in widget.accountInfo.balanceInfoList!) { if (balanceInfo.balance! > BigInt.zero && !_tokensWithBalance.contains(balanceInfo.token)) { _tokensWithBalance.add(balanceInfo.token); diff --git a/lib/widgets/reusable_widgets/input_fields/amount_suffix_widgets.dart b/lib/widgets/reusable_widgets/input_fields/amount_suffix_widgets.dart index 4466c9e6..53ad0a9c 100644 --- a/lib/widgets/reusable_widgets/input_fields/amount_suffix_widgets.dart +++ b/lib/widgets/reusable_widgets/input_fields/amount_suffix_widgets.dart @@ -5,20 +5,20 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AmountSuffixWidgets extends StatelessWidget { - final Token tokenId; - final VoidCallback? onMaxPressed; const AmountSuffixWidgets( this.tokenId, { this.onMaxPressed, - Key? key, - }) : super(key: key); + super.key, + }); + final Token tokenId; + final VoidCallback? onMaxPressed; @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, - children: [ + children: [ AmountSuffixTokenSymbolWidget( token: tokenId, context: context, @@ -39,9 +39,8 @@ class AmountSuffixTokenSymbolWidget extends Container { AmountSuffixTokenSymbolWidget({ required Token token, required BuildContext context, - Key? key, + super.key, }) : super( - key: key, height: kAmountSuffixHeight, width: kAmountSuffixWidth, alignment: Alignment.center, @@ -65,9 +64,8 @@ class AmountSuffixMaxWidget extends InkWell { AmountSuffixMaxWidget({ required VoidCallback onPressed, required BuildContext context, - Key? key, + super.key, }) : super( - key: key, onTap: onPressed, child: Container( height: kAmountSuffixHeight, diff --git a/lib/widgets/reusable_widgets/input_fields/disabled_address_field.dart b/lib/widgets/reusable_widgets/input_fields/disabled_address_field.dart index 30171a32..a71784d0 100644 --- a/lib/widgets/reusable_widgets/input_fields/disabled_address_field.dart +++ b/lib/widgets/reusable_widgets/input_fields/disabled_address_field.dart @@ -3,14 +3,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class DisabledAddressField extends StatelessWidget { - final TextEditingController _addressController; - final double contentLeftPadding; const DisabledAddressField( this._addressController, { this.contentLeftPadding = 8.0, - Key? key, - }) : super(key: key); + super.key, + }); + final TextEditingController _addressController; + final double contentLeftPadding; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/input_fields/input_field.dart b/lib/widgets/reusable_widgets/input_fields/input_field.dart index f0f8c1b7..0af72dc3 100644 --- a/lib/widgets/reusable_widgets/input_fields/input_field.dart +++ b/lib/widgets/reusable_widgets/input_fields/input_field.dart @@ -4,27 +4,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; class InputField extends StatefulWidget { - final TextEditingController controller; - final FocusNode? thisNode; - final FocusNode? nextNode; - final String? hintText; - final bool enabled; - final List? inputFormatters; - final String? Function(String?)? validator; - final Widget? suffixIcon; - final BoxConstraints? suffixIconConstraints; - final double contentLeftPadding; - final Function(String)? onChanged; - final bool obscureText; - final String? errorText; - final int maxLines; - final Function(String)? onSubmitted; - final TextStyle inputtedTextStyle; - final InputBorder? enabledBorder; - final InputBorder? focusedBorder; - final InputBorder? disabledBorder; - final InputBorder? errorBorder; - final InputBorder? focusedErrorBorder; const InputField({ required this.controller, @@ -43,7 +22,7 @@ class InputField extends StatefulWidget { this.errorText, this.onSubmitted, this.inputtedTextStyle = const TextStyle( - fontSize: 14.0, + fontSize: 14, color: AppColors.znnColor, ), this.disabledBorder, @@ -51,8 +30,29 @@ class InputField extends StatefulWidget { this.errorBorder, this.focusedBorder, this.focusedErrorBorder, - Key? key, - }) : super(key: key); + super.key, + }); + final TextEditingController controller; + final FocusNode? thisNode; + final FocusNode? nextNode; + final String? hintText; + final bool enabled; + final List? inputFormatters; + final String? Function(String?)? validator; + final Widget? suffixIcon; + final BoxConstraints? suffixIconConstraints; + final double contentLeftPadding; + final Function(String)? onChanged; + final bool obscureText; + final String? errorText; + final int maxLines; + final Function(String)? onSubmitted; + final TextStyle inputtedTextStyle; + final InputBorder? enabledBorder; + final InputBorder? focusedBorder; + final InputBorder? disabledBorder; + final InputBorder? errorBorder; + final InputBorder? focusedErrorBorder; @override State createState() { @@ -64,12 +64,12 @@ class _InputFieldState extends State { @override Widget build(BuildContext context) { return TextFormField( - contextMenuBuilder: (context, editableTextState) { + contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) { return AdaptiveTextSelectionToolbar( anchors: editableTextState.contextMenuAnchors, children: editableTextState.contextMenuButtonItems .map((ContextMenuButtonItem buttonItem) { - return Row(children: [ + return Row(children: [ Expanded( child: TextButton( onPressed: buttonItem.onPressed, @@ -78,20 +78,19 @@ class _InputFieldState extends State { ), child: Text( AdaptiveTextSelectionToolbar.getButtonLabel( - context, buttonItem), - style: Theme.of(context).textTheme.bodyMedium), - )) - ]); - }).toList()); + context, buttonItem,), + style: Theme.of(context).textTheme.bodyMedium,), + ),), + ],); + }).toList(),); }, maxLines: widget.maxLines, obscureText: widget.obscureText, onChanged: widget.onChanged, validator: widget.validator, - inputFormatters: widget.inputFormatters ?? [], + inputFormatters: widget.inputFormatters ?? [], enabled: widget.enabled, controller: widget.controller, - autofocus: false, focusNode: widget.thisNode, onFieldSubmitted: widget.onSubmitted, style: widget.inputtedTextStyle, diff --git a/lib/widgets/reusable_widgets/input_fields/labeled_input_container.dart b/lib/widgets/reusable_widgets/input_fields/labeled_input_container.dart index 6ebd72a3..afeb0ba6 100644 --- a/lib/widgets/reusable_widgets/input_fields/labeled_input_container.dart +++ b/lib/widgets/reusable_widgets/input_fields/labeled_input_container.dart @@ -2,52 +2,51 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class LabeledInputContainer extends StatelessWidget { - final String labelText; - final Widget inputWidget; - final String? helpText; const LabeledInputContainer({ required this.labelText, required this.inputWidget, this.helpText, - Key? key, - }) : super(key: key); + super.key, + }); + final String labelText; + final Widget inputWidget; + final String? helpText; @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + children: [ Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ Text( labelText, style: const TextStyle( - fontSize: 14.0, + fontSize: 14, color: AppColors.darkHintTextColor, ), ), - const SizedBox(width: 3.0), + const SizedBox(width: 3), Visibility( visible: helpText != null, child: Tooltip( message: helpText ?? '', child: const Padding( - padding: EdgeInsets.only(top: 3.0), + padding: EdgeInsets.only(top: 3), child: Icon( Icons.help, color: AppColors.darkHintTextColor, - size: 12.0, + size: 12, ), ), ), ), ], ), - const SizedBox(height: 3.0), - inputWidget + const SizedBox(height: 3), + inputWidget, ], ); } diff --git a/lib/widgets/reusable_widgets/input_fields/password_input_field.dart b/lib/widgets/reusable_widgets/input_fields/password_input_field.dart index 45ad4a96..0d44ee9a 100644 --- a/lib/widgets/reusable_widgets/input_fields/password_input_field.dart +++ b/lib/widgets/reusable_widgets/input_fields/password_input_field.dart @@ -4,12 +4,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class PasswordInputField extends StatefulWidget { - final TextEditingController controller; - final String hintText; - final void Function(String)? onSubmitted; - final void Function(String)? onChanged; - final String? Function(String?)? validator; - final String? errorText; const PasswordInputField({ required this.controller, @@ -18,8 +12,14 @@ class PasswordInputField extends StatefulWidget { this.onChanged, this.validator, this.errorText, - Key? key, - }) : super(key: key); + super.key, + }); + final TextEditingController controller; + final String hintText; + final void Function(String)? onSubmitted; + final void Function(String)? onChanged; + final String? Function(String?)? validator; + final String? errorText; @override State createState() => _PasswordInputFieldState(); @@ -44,8 +44,8 @@ class _PasswordInputFieldState extends State { }); }, child: SizedBox( - height: 10.0, - width: 10.0, + height: 10, + width: 10, child: Icon( _obscureText ? Icons.visibility_off_outlined diff --git a/lib/widgets/reusable_widgets/layout_scaffold/card_scaffold.dart b/lib/widgets/reusable_widgets/layout_scaffold/card_scaffold.dart index 406f8480..b21ae2aa 100644 --- a/lib/widgets/reusable_widgets/layout_scaffold/card_scaffold.dart +++ b/lib/widgets/reusable_widgets/layout_scaffold/card_scaffold.dart @@ -13,15 +13,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/widget_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class CardScaffold extends StatefulWidget { - final String? title; - final String description; - final Widget Function()? childBuilder; - final Stream? childStream; - final VoidCallback? onRefreshPressed; - final Widget Function(T)? onCompletedStatusCallback; - final double? titleFontSize; - final Widget? titleIcon; - final Widget? customItem; const CardScaffold({ required this.title, @@ -33,8 +24,17 @@ class CardScaffold extends StatefulWidget { this.titleFontSize, this.titleIcon, this.customItem, - Key? key, - }) : super(key: key); + super.key, + }); + final String? title; + final String description; + final Widget Function()? childBuilder; + final Stream? childStream; + final VoidCallback? onRefreshPressed; + final Widget Function(T)? onCompletedStatusCallback; + final double? titleFontSize; + final Widget? titleIcon; + final Widget? customItem; @override State> createState() => _CardScaffoldState(); @@ -62,14 +62,12 @@ class _CardScaffoldState extends State> { @override Widget build(BuildContext context) { return FlipCard( - direction: FlipDirection.HORIZONTAL, - speed: 500, flipOnTouch: false, key: cardKey, - onFlipDone: (status) {}, + onFlipDone: (bool status) {}, front: ClipRRect( borderRadius: BorderRadius.circular( - 15.0, + 15, ), child: Container( color: Theme.of(context).colorScheme.primary, @@ -83,14 +81,14 @@ class _CardScaffoldState extends State> { color: Theme.of(context).colorScheme.primary, child: _getWidgetFrontBody(), ), - ) + ), ], ), ), ), back: ClipRRect( borderRadius: BorderRadius.circular( - 15.0, + 15, ), child: Material( child: Container( @@ -112,10 +110,10 @@ class _CardScaffoldState extends State> { Widget _getBackBody(HideWidgetStatusBloc model) { return Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: ListView( shrinkWrap: true, - children: [ + children: [ ExpandablePanel( collapsed: Container(), theme: ExpandableThemeData( @@ -124,14 +122,14 @@ class _CardScaffoldState extends State> { iconPlacement: ExpandablePanelIconPlacement.right, ), header: Row( - children: [ + children: [ const Icon( Icons.info, color: AppColors.znnColor, - size: 20.0, + size: 20, ), const SizedBox( - width: 5.0, + width: 5, ), Expanded( child: Text( @@ -143,9 +141,9 @@ class _CardScaffoldState extends State> { ), expanded: Padding( padding: const EdgeInsets.only( - left: 14.0, - top: 5.0, - bottom: 5.0, + left: 14, + top: 5, + bottom: 5, ), child: Text( widget.description, @@ -154,15 +152,14 @@ class _CardScaffoldState extends State> { ), ), Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ + children: [ const Icon( Icons.remove_red_eye_rounded, color: AppColors.znnColor, - size: 20.0, + size: 20, ), const SizedBox( - width: 5.0, + width: 5, ), Expanded( child: Text( @@ -172,9 +169,9 @@ class _CardScaffoldState extends State> { ), const Spacer(), Switch( - splashRadius: 0.0, + splashRadius: 0, value: _hideWidgetInfo!, - onChanged: (value) { + onChanged: (bool value) { setState(() { _hideWidgetInfo = value; }); @@ -196,25 +193,25 @@ class _CardScaffoldState extends State> { }); } }, - ) + ), ], ), Visibility( visible: _showPasswordInputField, child: Row( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Expanded( child: _getPasswordInputField(model), ), const SizedBox( - width: 10.0, + width: 10, ), _actionButton!, ], ), ), - if (widget.customItem != null) widget.customItem! + if (widget.customItem != null) widget.customItem!, ], ), ); @@ -226,22 +223,22 @@ class _CardScaffoldState extends State> { children: [ Expanded( child: Padding( - padding: const EdgeInsets.all(14.0), + padding: const EdgeInsets.all(14), child: Row( - children: [ + children: [ Expanded( child: Text( title, style: Theme.of(context).textTheme.bodyLarge!.copyWith( fontSize: widget.titleFontSize, - height: 1.0, + height: 1, ), ), ), const SizedBox( - width: 5.0, + width: 5, ), - widget.titleIcon != null ? widget.titleIcon! : Container(), + if (widget.titleIcon != null) widget.titleIcon! else Container(), ], ), ), @@ -249,16 +246,16 @@ class _CardScaffoldState extends State> { Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, - children: [ + children: [ Visibility( visible: widget.onRefreshPressed != null, child: Material( shadowColor: Colors.transparent, color: Colors.transparent, child: IconButton( - splashRadius: 15.0, + splashRadius: 15, icon: const Icon(Icons.refresh), - iconSize: 18.0, + iconSize: 18, color: Theme.of(context).colorScheme.secondary, onPressed: widget.onRefreshPressed, ), @@ -268,9 +265,9 @@ class _CardScaffoldState extends State> { shadowColor: Colors.transparent, color: Colors.transparent, child: IconButton( - splashRadius: 15.0, + splashRadius: 15, icon: const Icon(Icons.more_horiz), - iconSize: 18.0, + iconSize: 18, color: Theme.of(context).textTheme.bodyLarge!.color, onPressed: () { cardKey.currentState!.toggleCard(); @@ -285,7 +282,7 @@ class _CardScaffoldState extends State> { Widget _getPasswordInputField(HideWidgetStatusBloc model) { return PasswordInputField( - onSubmitted: (value) { + onSubmitted: (String value) { _actionButton!.onPressed!(); }, controller: _passwordController, @@ -301,18 +298,18 @@ class _CardScaffoldState extends State> { icon: const Icon( AntDesign.arrowright, color: AppColors.znnColor, - size: 25.0, + size: 25, ), ); } Widget _getHideWidgetInfoViewModel() { return ViewModelBuilder.reactive( - onViewModelReady: (model) { + onViewModelReady: (HideWidgetStatusBloc model) { _actionButton = _getActionButton(model); // Stream will tell us if the widget info is hidden or not model.stream.listen( - (response) { + (bool? response) { if (response != null) { _passwordController.clear(); if (!response) { @@ -329,9 +326,9 @@ class _CardScaffoldState extends State> { }, ); }, - builder: (_, model, __) => StreamBuilder( + builder: (_, HideWidgetStatusBloc model, __) => StreamBuilder( stream: model.stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasError) { return _getBackBody(model); } @@ -341,14 +338,14 @@ class _CardScaffoldState extends State> { } return const Center( child: SyriusLoadingWidget( - size: 25.0, + size: 25, ), ); } return _getBackBody(model); }, ), - viewModelBuilder: () => HideWidgetStatusBloc(), + viewModelBuilder: HideWidgetStatusBloc.new, ); } @@ -357,8 +354,8 @@ class _CardScaffoldState extends State> { ? _getHiddenInfoWidget() : widget.childStream != null && widget.onCompletedStatusCallback != null ? StreamBuilder( - stream: widget.childStream as Stream, - builder: (context, snapshot) { + stream: widget.childStream, + builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error!); } else if (snapshot.hasData) { @@ -382,7 +379,7 @@ class _CardScaffoldState extends State> { ); } - void _onActionButtonPressed(HideWidgetStatusBloc model) async { + Future _onActionButtonPressed(HideWidgetStatusBloc model) async { if (_passwordController.text.isNotEmpty && _actionButtonKey.currentState!.btnState == ButtonState.idle) { try { diff --git a/lib/widgets/reusable_widgets/layout_scaffold/overscroll_remover.dart b/lib/widgets/reusable_widgets/layout_scaffold/overscroll_remover.dart index 5b8ee4e7..fb381fd1 100644 --- a/lib/widgets/reusable_widgets/layout_scaffold/overscroll_remover.dart +++ b/lib/widgets/reusable_widgets/layout_scaffold/overscroll_remover.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class RemoveOverscrollEffect extends ScrollBehavior { @override Widget buildOverscrollIndicator( - BuildContext context, Widget child, ScrollableDetails details) { + BuildContext context, Widget child, ScrollableDetails details,) { return child; } } diff --git a/lib/widgets/reusable_widgets/layout_scaffold/standard_fluid_layout.dart b/lib/widgets/reusable_widgets/layout_scaffold/standard_fluid_layout.dart index d2992199..61ff3c27 100644 --- a/lib/widgets/reusable_widgets/layout_scaffold/standard_fluid_layout.dart +++ b/lib/widgets/reusable_widgets/layout_scaffold/standard_fluid_layout.dart @@ -6,9 +6,6 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/layout_scaf const int kStaggeredNumOfColumns = 12; class StandardFluidLayout extends StatelessWidget { - final List children; - final int? defaultCellWidth; - final double? defaultCellHeight; const StandardFluidLayout({ required this.children, @@ -16,25 +13,28 @@ class StandardFluidLayout extends StatelessWidget { this.defaultCellHeight = kStaggeredNumOfColumns / 4, super.key, }); + final List children; + final int? defaultCellWidth; + final double? defaultCellHeight; @override Widget build(BuildContext context) { return Layout( format: FluidLayoutFormat(), child: Builder( - builder: (context) { + builder: (BuildContext context) { const int crossAxisCount = kStaggeredNumOfColumns; final double spacing = context.breakpoint < LayoutBreakpoint.sm ? 4.0 : 12.0; - final double totalDurationMs = children.length > 5 ? 800 : 400; + final int totalDurationMs = children.length > 5 ? 800 : 400; final int durationPerTile = totalDurationMs ~/ children.length; - final List tiles = List.generate( + final List tiles = List.generate( children.length, - (index) { + (int index) { final int widgetAnimatorOffset = durationPerTile * (index + 1); return _generateStaggeredTitle( @@ -65,7 +65,6 @@ class StandardFluidLayout extends StatelessWidget { crossAxisCellCount: fluidCell.width ?? defaultCellWidth!, mainAxisCellCount: fluidCell.height ?? defaultCellHeight!, child: WidgetAnimator( - curve: Curves.linear, animationOffset: Duration( milliseconds: widgetAnimatorOffset, ), @@ -76,13 +75,13 @@ class StandardFluidLayout extends StatelessWidget { } class FluidCell { - final int? width; - final double? height; - final Widget child; const FluidCell({ required this.child, this.width, this.height, }); + final int? width; + final double? height; + final Widget child; } diff --git a/lib/widgets/reusable_widgets/layout_scaffold/widget_animator.dart b/lib/widgets/reusable_widgets/layout_scaffold/widget_animator.dart index 8574d320..4fa9493a 100644 --- a/lib/widgets/reusable_widgets/layout_scaffold/widget_animator.dart +++ b/lib/widgets/reusable_widgets/layout_scaffold/widget_animator.dart @@ -3,18 +3,18 @@ import 'dart:async'; import 'package:flutter/material.dart'; class WidgetAnimator extends StatefulWidget { - final Widget? child; - final Duration duration; - final Curve curve; - final Duration animationOffset; const WidgetAnimator({ required this.child, this.animationOffset = const Duration(milliseconds: 100), this.duration = const Duration(milliseconds: 300), this.curve = Curves.linear, - Key? key, - }) : super(key: key); + super.key, + }); + final Widget? child; + final Duration duration; + final Curve curve; + final Duration animationOffset; @override State createState() => _WidgetAnimatorState(); @@ -60,7 +60,7 @@ class _WidgetAnimatorState extends State opacity: _animation!.value, child: Transform.translate( offset: Offset( - 0.0, + 0, (1.0 - _animation!.value) * 20.0, ), child: child, diff --git a/lib/widgets/reusable_widgets/loading_info_text.dart b/lib/widgets/reusable_widgets/loading_info_text.dart index f0666093..2a0b9232 100644 --- a/lib/widgets/reusable_widgets/loading_info_text.dart +++ b/lib/widgets/reusable_widgets/loading_info_text.dart @@ -3,36 +3,36 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/loading_widget.dart'; class LoadingInfoText extends StatelessWidget { - final String text; - final String? tooltipText; const LoadingInfoText({ required this.text, this.tooltipText, - Key? key, - }) : super(key: key); + super.key, + }); + final String text; + final String? tooltipText; @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ const SyriusLoadingWidget( - size: 16.0, - strokeWidth: 2.0, + size: 16, + strokeWidth: 2, ), const SizedBox( - width: 10.0, + width: 10, ), Text( text, style: - const TextStyle(fontSize: 14.0, color: AppColors.subtitleColor), + const TextStyle(fontSize: 14, color: AppColors.subtitleColor), ), Visibility( visible: tooltipText != null, child: const SizedBox( - width: 5.0, + width: 5, ), ), Visibility( @@ -40,11 +40,11 @@ class LoadingInfoText extends StatelessWidget { child: Tooltip( message: tooltipText ?? '', child: const Padding( - padding: EdgeInsets.only(top: 1.0), + padding: EdgeInsets.only(top: 1), child: Icon( Icons.help, color: AppColors.subtitleColor, - size: 14.0, + size: 14, ), ), ), diff --git a/lib/widgets/reusable_widgets/loading_widget.dart b/lib/widgets/reusable_widgets/loading_widget.dart index 4a66ece8..a7f94bb9 100644 --- a/lib/widgets/reusable_widgets/loading_widget.dart +++ b/lib/widgets/reusable_widgets/loading_widget.dart @@ -2,16 +2,16 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class SyriusLoadingWidget extends StatelessWidget { - final double size; - final double strokeWidth; - final double padding; const SyriusLoadingWidget({ this.size = 50.0, this.strokeWidth = 4.0, this.padding = 4.0, - Key? key, - }) : super(key: key); + super.key, + }); + final double size; + final double strokeWidth; + final double padding; @override Widget build(BuildContext context) { diff --git a/lib/widgets/reusable_widgets/modals/base_modal.dart b/lib/widgets/reusable_widgets/modals/base_modal.dart index 955d4826..46f3b0f8 100644 --- a/lib/widgets/reusable_widgets/modals/base_modal.dart +++ b/lib/widgets/reusable_widgets/modals/base_modal.dart @@ -2,16 +2,14 @@ import 'package:flutter/material.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class BaseModal extends StatelessWidget { - final String title; - final String subtitle; - final Widget child; const BaseModal({ - Key? key, - required this.title, - required this.child, + required this.title, required this.child, super.key, this.subtitle = '', - }) : super(key: key); + }); + final String title; + final String subtitle; + final Widget child; @override Widget build(BuildContext context) { @@ -25,28 +23,28 @@ class BaseModal extends StatelessWidget { duration: const Duration(milliseconds: 100), curve: Curves.easeInOut, child: Container( - width: 570.0, + width: 570, color: Theme.of(context).colorScheme.primaryContainer, child: Padding( - padding: const EdgeInsets.all(25.0), + padding: const EdgeInsets.all(25), child: Column( mainAxisSize: MainAxisSize.min, - children: [ + children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ Column( - children: [ + children: [ Text( title, style: const TextStyle( - fontSize: 18.0, + fontSize: 18, ), ), Visibility( visible: subtitle.isNotEmpty, child: const SizedBox( - height: 3.0, + height: 3, ), ), Visibility( @@ -62,13 +60,13 @@ class BaseModal extends StatelessWidget { child: const Icon( Icons.clear, color: AppColors.lightSecondary, - size: 22.0, + size: 22, ), ), ), ], ), - child + child, ], ), ), diff --git a/lib/widgets/reusable_widgets/notification_widget.dart b/lib/widgets/reusable_widgets/notification_widget.dart index 5b92840e..2b9af2ab 100644 --- a/lib/widgets/reusable_widgets/notification_widget.dart +++ b/lib/widgets/reusable_widgets/notification_widget.dart @@ -6,18 +6,18 @@ import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class NotificationWidget extends StatefulWidget { - final VoidCallback? onSeeMorePressed; - final VoidCallback? onDismissPressed; - final VoidCallback? onNewNotificationCallback; - final bool popBeforeSeeMoreIsPressed; const NotificationWidget({ this.onSeeMorePressed, this.onDismissPressed, this.onNewNotificationCallback, this.popBeforeSeeMoreIsPressed = true, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback? onSeeMorePressed; + final VoidCallback? onDismissPressed; + final VoidCallback? onNewNotificationCallback; + final bool popBeforeSeeMoreIsPressed; @override State createState() => _NotificationWidgetState(); @@ -37,23 +37,22 @@ class _NotificationWidgetState extends State { return _shouldShowNotification() ? Padding( padding: const EdgeInsets.only( - bottom: 15.0, + bottom: 15, ), child: WidgetAnimator( - curve: Curves.linear, child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), color: Theme.of(context).colorScheme.primary, ), child: Padding( padding: const EdgeInsets.symmetric( - vertical: 15.0, - horizontal: 50.0, + vertical: 15, + horizontal: 50, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ _getNotificationDetails(kLastNotification!), _getNotificationOptions(kLastNotification!), ], @@ -72,7 +71,7 @@ class _NotificationWidgetState extends State { void _initNotificationsBloc() { _notificationsBloc = sl.get(); _notificationsBloc.stream.listen( - (value) { + (WalletNotification? value) { if (mounted) { setState(() { kLastNotification = value; @@ -85,10 +84,10 @@ class _NotificationWidgetState extends State { Row _getNotificationDetails(WalletNotification notification) { return Row( - children: [ + children: [ notification.getIcon(), const SizedBox( - width: 15.0, + width: 15, ), Text( notification.title!, @@ -100,14 +99,14 @@ class _NotificationWidgetState extends State { Row _getNotificationOptions(WalletNotification notification) { return Row( - children: [ + children: [ Visibility( visible: kCurrentPage != Tabs.lock && widget.onSeeMorePressed != null, child: RawMaterialButton( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, constraints: const BoxConstraints.tightFor(), padding: const EdgeInsets.all( - 4.0, + 4, ), onPressed: _navigateToNotification, child: Text( @@ -119,13 +118,13 @@ class _NotificationWidgetState extends State { ), ), const SizedBox( - width: 15.0, + width: 15, ), RawMaterialButton( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, constraints: const BoxConstraints.tightFor(), padding: const EdgeInsets.all( - 4.0, + 4, ), onPressed: _dismissNotification, child: Text( diff --git a/lib/widgets/reusable_widgets/number_animation.dart b/lib/widgets/reusable_widgets/number_animation.dart index 274a4fad..79965d18 100644 --- a/lib/widgets/reusable_widgets/number_animation.dart +++ b/lib/widgets/reusable_widgets/number_animation.dart @@ -1,6 +1,31 @@ import 'package:flutter/material.dart'; class NumberAnimation extends StatefulWidget { + + /// constructor + NumberAnimation({ + super.key, + this.start = 0.0, + this.end, + this.isInt = false, + this.style, + this.textAlign, + this.strutStyle, + this.duration = const Duration(milliseconds: 1000), + this.decimalPoint = 2, + this.before = '', + this.after = '', + this.isLoading = false, + this.loadingPlaceHolder = '', + }) { + if (isLoading == false) { + assert(end != null); + if (isInt) { + assert(start.toInt() == start); + assert(end!.toInt() == end); + } + } + } /// start number final num start; @@ -37,31 +62,6 @@ class NumberAnimation extends StatefulWidget { /// loading placeholder final String loadingPlaceHolder; - /// constructor - NumberAnimation({ - Key? key, - this.start = 0.0, - this.end, - this.isInt = false, - this.style, - this.textAlign, - this.strutStyle, - this.duration = const Duration(milliseconds: 1000), - this.decimalPoint = 2, - this.before = '', - this.after = '', - this.isLoading = false, - this.loadingPlaceHolder = '', - }) : super(key: key) { - if (isLoading == false) { - assert(end != null); - if (isInt) { - assert(start.toInt() == start); - assert(end!.toInt() == end); - } - } - } - /// create state @override State createState() => _NumberAnimationState(); @@ -82,8 +82,8 @@ class _NumberAnimationState extends State controller = AnimationController(duration: widget.duration, vsync: this); _curve = CurvedAnimation(parent: controller!, curve: Curves.easeOut); if (widget.isLoading == false) { - Animation animation = Tween( - begin: widget.start.toDouble(), end: widget.end!.toDouble()) + final Animation animation = Tween( + begin: widget.start.toDouble(), end: widget.end!.toDouble(),) .animate(_curve as Animation); _animation = animation; controller!.forward(); @@ -107,11 +107,11 @@ class _NumberAnimationState extends State if (oldWidget.end == widget.end && _hasShowNumber == true) { return; } - Animation animation = Tween( + final Animation animation = Tween( begin: _animation != null ? _animation!.value : widget.start.toDouble(), - end: widget.end!.toDouble()) + end: widget.end!.toDouble(),) .animate(_curve as Animation); _animation = animation; controller! @@ -124,9 +124,9 @@ class _NumberAnimationState extends State /// build @override Widget build(BuildContext context) { - TextStyle? style = widget.style; - TextAlign? textAlign = widget.textAlign; - StrutStyle? strutStyle = widget.strutStyle; + final TextStyle? style = widget.style; + final TextAlign? textAlign = widget.textAlign; + final StrutStyle? strutStyle = widget.strutStyle; if (widget.isLoading == true) { return Text( widget.loadingPlaceHolder, @@ -137,7 +137,7 @@ class _NumberAnimationState extends State } return AnimatedBuilder( animation: _animation!, - builder: (context, child) { + builder: (BuildContext context, Widget? child) { if (widget.isLoading == true) { return Text( widget.loadingPlaceHolder, @@ -148,7 +148,7 @@ class _NumberAnimationState extends State } if (widget.isInt) { return Text( - '${widget.before}${_animation!.value.toInt().toString()}${widget.after}', + '${widget.before}${_animation!.value.toInt()}${widget.after}', style: style, textAlign: textAlign, strutStyle: strutStyle, diff --git a/lib/widgets/reusable_widgets/plasma_icon.dart b/lib/widgets/reusable_widgets/plasma_icon.dart index 6b51d3b4..86a69dbd 100644 --- a/lib/widgets/reusable_widgets/plasma_icon.dart +++ b/lib/widgets/reusable_widgets/plasma_icon.dart @@ -4,24 +4,24 @@ import 'package:zenon_syrius_wallet_flutter/utils/widget_utils.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class PlasmaIcon extends StatelessWidget { - final PlasmaInfo? plasmaInfo; const PlasmaIcon( this.plasmaInfo, { - Key? key, - }) : super(key: key); + super.key, + }); + final PlasmaInfo? plasmaInfo; @override Widget build(BuildContext context) { return Tooltip( message: WidgetUtils.getPlasmaToolTipMessage(plasmaInfo!), child: Container( - height: 20.0, - width: 20.0, + height: 20, + width: 20, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( - width: 3.0, + width: 3, color: ColorUtils.getPlasmaColor(plasmaInfo!), ), ), diff --git a/lib/widgets/reusable_widgets/progress_bars.dart b/lib/widgets/reusable_widgets/progress_bars.dart index 5493794b..a366f5ff 100644 --- a/lib/widgets/reusable_widgets/progress_bars.dart +++ b/lib/widgets/reusable_widgets/progress_bars.dart @@ -5,21 +5,21 @@ import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:zenon_syrius_wallet_flutter/utils/input_validators.dart'; class PasswordProgressBar extends StatefulWidget { - final String password; - final GlobalKey passwordKey; const PasswordProgressBar({ required this.password, required this.passwordKey, - Key? key, - }) : super(key: key); + super.key, + }); + final String password; + final GlobalKey passwordKey; @override State createState() => _PasswordProgressBarState(); } class _PasswordProgressBarState extends State { - final List _colors = [ + final List _colors = [ AppColors.accessWalletContainersGray, AppColors.accessWalletContainersGray, AppColors.accessWalletContainersGray, @@ -33,7 +33,7 @@ class _PasswordProgressBarState extends State { width: kPasswordInputFieldWidth, child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 5.0, + horizontal: 5, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, @@ -45,18 +45,18 @@ class _PasswordProgressBarState extends State { List _getProgressBars() => List.generate( _colors.length, - (index) => _getPasswordProgressBar(_colors[index]), + (int index) => _getPasswordProgressBar(_colors[index]), ); List _getSpacers() => List.generate( _colors.length - 1, - (index) => _getSpacer(), + (int index) => _getSpacer(), ); Expanded _getPasswordProgressBar(Color color) { return Expanded( child: Container( - height: 5.0, + height: 5, color: color, ), ); @@ -64,7 +64,7 @@ class _PasswordProgressBarState extends State { SizedBox _getSpacer() { return const SizedBox( - width: 10.0, + width: 10, ); } @@ -93,38 +93,37 @@ class _PasswordProgressBarState extends State { } class ProgressBar extends StatelessWidget { - final int currentLevel; - final int numLevels; const ProgressBar({ required this.currentLevel, this.numLevels = 5, - Key? key, - }) : super(key: key); + super.key, + }); + final int currentLevel; + final int numLevels; @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, children: _getProgressBars().zip(_getSpacers()), ); } List _getProgressBars() => List.generate( numLevels, - (index) => _getProgressBar(index + 1), + (int index) => _getProgressBar(index + 1), ); List _getSpacers() => List.generate( numLevels - 1, - (index) => _getSpacer(), + (int index) => _getSpacer(), ); Container _getProgressBar(int level) { return Container( - width: 125.0, - height: 5.0, + width: 125, + height: 5, color: currentLevel >= level ? AppColors.znnColor : AppColors.accessWalletContainersGray, @@ -133,22 +132,22 @@ class ProgressBar extends StatelessWidget { SizedBox _getSpacer() { return const SizedBox( - width: 25.0, + width: 25, ); } } class AcceleratorProgressBarSpan extends StatelessWidget { - final double value; - final Color color; - final String tooltipMessage; const AcceleratorProgressBarSpan({ required this.value, required this.color, required this.tooltipMessage, - Key? key, - }) : super(key: key); + super.key, + }); + final double value; + final Color color; + final String tooltipMessage; @override Widget build(BuildContext context) { @@ -166,17 +165,16 @@ class AcceleratorProgressBarSpan extends StatelessWidget { } class AcceleratorProgressBar extends StatelessWidget { - final Widget child; - final BuildContext context; const AcceleratorProgressBar( - {required this.child, required this.context, Key? key}) - : super(key: key); + {required this.child, required this.context, super.key,}); + final Widget child; + final BuildContext context; @override Widget build(BuildContext context) { return ClipRRect( - borderRadius: BorderRadius.circular(20.0), + borderRadius: BorderRadius.circular(20), child: Container( width: kAcceleratorProgressBarSize.width, height: kAcceleratorProgressBarSize.height, diff --git a/lib/widgets/reusable_widgets/receive_qr_image.dart b/lib/widgets/reusable_widgets/receive_qr_image.dart index 8d2fac35..fb0ec2ef 100644 --- a/lib/widgets/reusable_widgets/receive_qr_image.dart +++ b/lib/widgets/reusable_widgets/receive_qr_image.dart @@ -1,6 +1,5 @@ import 'dart:io'; import 'dart:typed_data'; -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; @@ -15,55 +14,54 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/context_men import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class ReceiveQrImage extends StatelessWidget { + + const ReceiveQrImage({ + required this.data, + required this.size, + required this.tokenStandard, + required this.context, + super.key, + }); final String data; final int size; final TokenStandard tokenStandard; final BuildContext context; - static const decorationImage = PrettyQrDecorationImage( + static const PrettyQrDecorationImage decorationImage = PrettyQrDecorationImage( scale: 0.3, padding: EdgeInsets.only(top: 10, bottom: 10), image: AssetImage('assets/images/qr_code_child_image_znn.png'), - position: PrettyQrDecorationImagePosition.embedded, ); - const ReceiveQrImage({ - required this.data, - required this.size, - required this.tokenStandard, - required this.context, - Key? key, - }) : super(key: key); - @override Widget build(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular( - 15.0, + 15, ), child: Container( height: size + 20, width: size + 20, padding: const EdgeInsets.all( - 10.0, + 10, ), - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: ContextMenuRegion( - contextMenuBuilder: (context, offset) { + contextMenuBuilder: (BuildContext context, Offset offset) { return AdaptiveTextSelectionToolbar( anchors: TextSelectionToolbarAnchors( primaryAnchor: offset, ), - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: Directionality( textDirection: TextDirection.rtl, child: TextButton.icon( icon: Icon( MaterialCommunityIcons.share, - color: Theme.of(context).colorScheme.onBackground, + color: Theme.of(context).colorScheme.onSurface, size: 14, ), onPressed: () { @@ -77,8 +75,8 @@ class ReceiveQrImage extends StatelessWidget { AdaptiveTextSelectionToolbar.getButtonLabel( context, ContextMenuButtonItem( - label: 'Share QR', onPressed: () {})), - style: Theme.of(context).textTheme.bodyMedium), + label: 'Share QR', onPressed: () {},),), + style: Theme.of(context).textTheme.bodyMedium,), ), ), ), @@ -86,15 +84,14 @@ class ReceiveQrImage extends StatelessWidget { ), Row( crossAxisAlignment: CrossAxisAlignment.end, - children: [ + children: [ Expanded( - flex: 1, child: Directionality( textDirection: TextDirection.rtl, child: TextButton.icon( icon: Icon( Icons.save_alt, - color: Theme.of(context).colorScheme.onBackground, + color: Theme.of(context).colorScheme.onSurface, size: 14, ), onPressed: () { @@ -108,8 +105,8 @@ class ReceiveQrImage extends StatelessWidget { AdaptiveTextSelectionToolbar.getButtonLabel( context, ContextMenuButtonItem( - label: 'Save QR', onPressed: () {})), - style: Theme.of(context).textTheme.bodyMedium), + label: 'Save QR', onPressed: () {},),), + style: Theme.of(context).textTheme.bodyMedium,), ), ), ), @@ -125,18 +122,18 @@ class ReceiveQrImage extends StatelessWidget { roundFactor: 0, color: ColorUtils.getTokenColor(tokenStandard), ), - image: decorationImage), + image: decorationImage,), errorCorrectLevel: QrErrorCorrectLevel.M, - errorBuilder: (context, error, stack) => Center( + errorBuilder: (BuildContext context, Object error, StackTrace? stack) => Center( child: Padding( - padding: const EdgeInsets.all(5.0), + padding: const EdgeInsets.all(5), child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: [ + children: [ Lottie.asset( 'assets/lottie/ic_anim_no_data.json', - width: 32.0, - height: 32.0, + width: 32, + height: 32, ), Tooltip( message: error.toString(), @@ -144,56 +141,55 @@ class ReceiveQrImage extends StatelessWidget { 'Failed to create QR code', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium, - )), + ),), ], ), ), - ))), + ),),), ), ); } Future _getQRImageData() async { - final qr = QrImage(QrCode.fromData( + final QrImage qr = QrImage(QrCode.fromData( data: data, errorCorrectLevel: QrErrorCorrectLevel.M, - )); + ),); - final b = await qr.toImageAsBytes( + final ByteData? b = await qr.toImageAsBytes( size: size, - format: ImageByteFormat.png, decoration: PrettyQrDecoration( shape: PrettyQrSmoothSymbol( roundFactor: 0, color: ColorUtils.getTokenColor(tokenStandard), ), - image: decorationImage)); + image: decorationImage,),); if (b != null) return b.buffer.asUint8List(); return null; } - void _saveQR() async { - final imageData = await _getQRImageData(); + Future _saveQR() async { + final Uint8List? imageData = await _getQRImageData(); if (imageData != null) { - String fileName = DateTime.now().millisecondsSinceEpoch.toString(); - final imagePath = await File( - '${znnDefaultPaths.cache.path}${path.separator}$fileName.png') + final String fileName = DateTime.now().millisecondsSinceEpoch.toString(); + final File imagePath = await File( + '${znnDefaultPaths.cache.path}${path.separator}$fileName.png',) .create(); await imagePath.writeAsBytes(imageData); await OpenFilex.open(imagePath.path); } } - void _shareQR() async { - final imageData = await _getQRImageData(); + Future _shareQR() async { + final Uint8List? imageData = await _getQRImageData(); if (imageData != null) { - String fileName = DateTime.now().millisecondsSinceEpoch.toString(); - final imagePath = await File( - '${znnDefaultPaths.cache.path}${path.separator}$fileName.png') + final String fileName = DateTime.now().millisecondsSinceEpoch.toString(); + final File imagePath = await File( + '${znnDefaultPaths.cache.path}${path.separator}$fileName.png',) .create(); await imagePath.writeAsBytes(imageData); - await Share.shareXFiles([XFile(imagePath.path)]); + await Share.shareXFiles([XFile(imagePath.path)]); } } } diff --git a/lib/widgets/reusable_widgets/reusable_widgets.dart b/lib/widgets/reusable_widgets/reusable_widgets.dart index 85559c6b..30b39aa0 100644 --- a/lib/widgets/reusable_widgets/reusable_widgets.dart +++ b/lib/widgets/reusable_widgets/reusable_widgets.dart @@ -1,23 +1,23 @@ -export 'buttons/buttons.dart'; -export 'chart/chart.dart'; -export 'dropdown/dropdown.dart'; -export 'icons/icons.dart'; -export 'input_fields/input_fields.dart'; -export 'layout_scaffold/layout_scaffold.dart'; export 'accelerator_project_details.dart'; export 'access_wallet_fluid_cell.dart'; export 'amount_info_column.dart'; export 'available_balance.dart'; +export 'buttons/buttons.dart'; export 'cancel_timer.dart'; +export 'chart/chart.dart'; export 'custom_expandable_panel.dart'; export 'custom_material_stepper.dart'; export 'custom_slider.dart'; export 'custom_table.dart'; export 'dialogs.dart'; export 'dotted_border_info_widget.dart'; +export 'dropdown/dropdown.dart'; export 'error_widget.dart'; export 'formatted_amount_with_tooltip.dart'; +export 'icons/icons.dart'; export 'infinite_scroll_table.dart'; +export 'input_fields/input_fields.dart'; +export 'layout_scaffold/layout_scaffold.dart'; export 'loading_widget.dart'; export 'modals/base_modal.dart'; export 'notification_widget.dart'; @@ -31,6 +31,6 @@ export 'select_file_widget.dart'; export 'settings_address.dart'; export 'settings_node.dart'; export 'stepper_utils.dart'; +export 'syrius_checkbox.dart'; export 'tag_widget.dart'; export 'transfer_icon_legend.dart'; -export 'syrius_checkbox.dart'; diff --git a/lib/widgets/reusable_widgets/seed/seed_choice.dart b/lib/widgets/reusable_widgets/seed/seed_choice.dart index 8774c417..e291a34f 100644 --- a/lib/widgets/reusable_widgets/seed/seed_choice.dart +++ b/lib/widgets/reusable_widgets/seed/seed_choice.dart @@ -3,16 +3,16 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class SeedChoice extends StatefulWidget { - final VoidCallback onSeed24Selected; - final VoidCallback onSeed12Selected; - final bool isSeed12Selected; const SeedChoice({ required this.onSeed24Selected, required this.onSeed12Selected, required this.isSeed12Selected, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onSeed24Selected; + final VoidCallback onSeed12Selected; + final bool isSeed12Selected; @override State createState() => _SeedChoiceState(); @@ -26,12 +26,12 @@ class _SeedChoiceState extends State { Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric( - vertical: 8.0, - horizontal: 20.0, + vertical: 8, + horizontal: 20, ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: BorderRadius.circular(30.0), + borderRadius: BorderRadius.circular(30), ), child: Row( mainAxisSize: MainAxisSize.min, @@ -44,7 +44,7 @@ class _SeedChoiceState extends State { }); }, child: FocusableActionDetector( - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _seed24Color = AppColors.znnColor; @@ -57,17 +57,17 @@ class _SeedChoiceState extends State { }, child: Container( padding: const EdgeInsets.symmetric( - vertical: 5.0, - horizontal: 15.0, + vertical: 5, + horizontal: 15, ), margin: const EdgeInsets.symmetric( - horizontal: 5.0, + horizontal: 5, ), decoration: BoxDecoration( color: widget.isSeed12Selected ? Colors.transparent : AppColors.znnColor, - borderRadius: BorderRadius.circular(30.0), + borderRadius: BorderRadius.circular(30), ), child: SvgPicture.asset( 'assets/svg/ic_seed_24.svg', @@ -75,7 +75,7 @@ class _SeedChoiceState extends State { widget.isSeed12Selected ? _seed24Color : AppColors.selectedSeedChoiceColor, - BlendMode.srcIn), + BlendMode.srcIn,), ), ), ), @@ -88,7 +88,7 @@ class _SeedChoiceState extends State { }); }, child: FocusableActionDetector( - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _seed12Color = AppColors.znnColor; @@ -101,17 +101,17 @@ class _SeedChoiceState extends State { }, child: Container( padding: const EdgeInsets.symmetric( - vertical: 5.0, - horizontal: 15.0, + vertical: 5, + horizontal: 15, ), margin: const EdgeInsets.symmetric( - horizontal: 5.0, + horizontal: 5, ), decoration: BoxDecoration( color: widget.isSeed12Selected ? AppColors.znnColor : Colors.transparent, - borderRadius: BorderRadius.circular(30.0), + borderRadius: BorderRadius.circular(30), ), child: SvgPicture.asset( 'assets/svg/ic_seed_12.svg', @@ -119,7 +119,7 @@ class _SeedChoiceState extends State { widget.isSeed12Selected ? AppColors.selectedSeedChoiceColor : _seed12Color, - BlendMode.srcIn), + BlendMode.srcIn,), ), ), ), diff --git a/lib/widgets/reusable_widgets/seed/seed_grid.dart b/lib/widgets/reusable_widgets/seed/seed_grid.dart index 9df7924d..45753d2f 100644 --- a/lib/widgets/reusable_widgets/seed/seed_grid.dart +++ b/lib/widgets/reusable_widgets/seed/seed_grid.dart @@ -6,18 +6,18 @@ import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart' show Mnemonic; class SeedGrid extends StatefulWidget { - final List seedWords; - final bool isContinueButtonDisabled; - final bool enableSeedInputFields; - final VoidCallback? onTextFieldChangedCallback; const SeedGrid( this.seedWords, { this.isContinueButtonDisabled = false, this.enableSeedInputFields = true, this.onTextFieldChangedCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final List seedWords; + final bool isContinueButtonDisabled; + final bool enableSeedInputFields; + final VoidCallback? onTextFieldChangedCallback; @override State createState() { @@ -26,7 +26,7 @@ class SeedGrid extends StatefulWidget { } class SeedGridState extends State { - final List _seedGridElements = []; + final List _seedGridElements = []; int? _textCursor; int? _onHoverText; @@ -61,16 +61,16 @@ class SeedGridState extends State { } Widget _getSeedInputWidgetsGrid() { - int divider = widget.seedWords.length ~/ kSeedGridNumOfRows; + final int divider = widget.seedWords.length ~/ kSeedGridNumOfRows; - List columnChildren = []; + List columnChildren = []; for (int i = 0; i <= widget.seedWords.length / divider - 1; i++) { columnChildren.add( _getSeedRow( List.generate( divider, - (index) => index + (divider * i), + (int index) => index + (divider * i), ), ), ); @@ -79,8 +79,8 @@ class SeedGridState extends State { columnChildren = columnChildren.zip( List.generate( kSeedGridNumOfRows - 1, - (index) => const SizedBox( - height: 10.0, + (int index) => const SizedBox( + height: 10, ), ), ); @@ -93,14 +93,14 @@ class SeedGridState extends State { } Widget _getSeedRow(List rangeIndexes) { - List children = rangeIndexes.fold>( - [], - (previousValue, index) { + final List children = rangeIndexes.fold>( + [], + (List previousValue, int index) { previousValue.add(_seedWordWidget(index)); if (rangeIndexes.last != index) { previousValue.add(const SizedBox( - width: 10.0, - )); + width: 10, + ),); } return previousValue; }, @@ -112,7 +112,7 @@ class SeedGridState extends State { } Widget _seedWordWidget(int seedWordIndex) { - String seedWord = _seedGridElements[seedWordIndex].word; + final String seedWord = _seedGridElements[seedWordIndex].word; final TextEditingController controller = TextEditingController(); controller.text = seedWord; @@ -124,7 +124,7 @@ class SeedGridState extends State { } return SizedBox( width: kSeedWordCellWidth, - height: 30.0, + height: 30, child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, @@ -136,7 +136,7 @@ class SeedGridState extends State { }, child: FocusableActionDetector( mouseCursor: SystemMouseCursors.click, - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _onHoverText = seedWordIndex; @@ -148,11 +148,11 @@ class SeedGridState extends State { } }, child: Container( - width: 30.0, - height: 30.0, + width: 30, + height: 30, decoration: BoxDecoration( border: Border.all( - width: 2.0, + width: 2, color: _getSeedNumberBorderColor(seedWordIndex, seedWord), ), color: _getSeedNumberColor(seedWordIndex, seedWord), @@ -170,13 +170,13 @@ class SeedGridState extends State { ), ), const SizedBox( - width: 10.0, + width: 10, ), Expanded( child: FocusableActionDetector( actions: _actionMap, shortcuts: _shortcutMap, - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _onHoverText = seedWordIndex; @@ -191,7 +191,7 @@ class SeedGridState extends State { color: Colors.transparent, child: TextField( focusNode: _focusNodes[seedWordIndex], - onChanged: (text) { + onChanged: (String text) { controller.text = text; _seedGridElements[seedWordIndex].word = text; _seedGridElements[seedWordIndex].isValid = @@ -202,7 +202,7 @@ class SeedGridState extends State { _checkIfSeedIsValid(); widget.onTextFieldChangedCallback?.call(); }, - inputFormatters: [LengthLimitingTextInputFormatter(8)], + inputFormatters: [LengthLimitingTextInputFormatter(8)], enabled: widget.enableSeedInputFields, controller: controller, obscureText: _onHoverText == seedWordIndex @@ -214,7 +214,7 @@ class SeedGridState extends State { _onHoverText == seedWordIndex ? Colors.white : getIndicatorColor(seedWord), - fontSize: 12.0, + fontSize: 12, ), decoration: InputDecoration( contentPadding: EdgeInsets.all(8.0), @@ -284,14 +284,14 @@ class SeedGridState extends State { return const UnderlineInputBorder( borderSide: BorderSide( color: AppColors.seedUnderlineBorderColor, - width: 3.0, + width: 3, ), ); } else if (Mnemonic.isValidWord(seedValue)) { return const UnderlineInputBorder( borderSide: BorderSide( color: AppColors.znnColor, - width: 3.0, + width: 3, ), ); } else if (Mnemonic.isValidWord(seedValue) == false && seedValue != '' || @@ -299,14 +299,14 @@ class SeedGridState extends State { return const UnderlineInputBorder( borderSide: BorderSide( color: AppColors.errorColor, - width: 3.0, + width: 3, ), ); } else { return const UnderlineInputBorder( borderSide: BorderSide( color: AppColors.seedUnderlineBorderColor, - width: 3.0, + width: 3, ), ); } @@ -323,7 +323,7 @@ class SeedGridState extends State { } bool _foundInvalidSeedGridElement() { - return _seedGridElements.any((element) => !element.isValid); + return _seedGridElements.any((SeedGridElement element) => !element.isValid); } void changedSeed(List newSeed) { @@ -335,19 +335,19 @@ class SeedGridState extends State { } List get getSeedWords => - _seedGridElements.map((e) => e.word).toList(); + _seedGridElements.map((SeedGridElement e) => e.word).toList(); String get getSeed => getSeedWords.join(' '); void _initFocusNodes(int length) => _focusNodes = List.generate( length, - (index) => FocusNode(), + (int index) => FocusNode(), ); void _changeFocusToNextNode() { - int indexOfFocusedNode = _focusNodes.indexOf( + final int indexOfFocusedNode = _focusNodes.indexOf( _focusNodes.firstWhere( - (node) => node.hasFocus, + (FocusNode node) => node.hasFocus, ), ); if (indexOfFocusedNode + 1 < _focusNodes.length) { @@ -358,7 +358,7 @@ class SeedGridState extends State { } void _initSeedGridElements(List seed) { - for (var word in seed) { + for (final String word in seed) { _seedGridElements.add( SeedGridElement( word: word, @@ -371,7 +371,7 @@ class SeedGridState extends State { @override void dispose() { - for (var focusNode in _focusNodes) { + for (final FocusNode focusNode in _focusNodes) { focusNode.dispose(); } super.dispose(); @@ -379,13 +379,13 @@ class SeedGridState extends State { } class SeedGridElement { - String word; - bool isValid; - bool isShown; SeedGridElement({ required this.word, required this.isValid, required this.isShown, }); + String word; + bool isValid; + bool isShown; } diff --git a/lib/widgets/reusable_widgets/select_file_widget.dart b/lib/widgets/reusable_widgets/select_file_widget.dart index db36d87d..d9e66255 100644 --- a/lib/widgets/reusable_widgets/select_file_widget.dart +++ b/lib/widgets/reusable_widgets/select_file_widget.dart @@ -8,16 +8,16 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; const String _kInitialMessage = 'Click to browse or drag and drop a file'; class SelectFileWidget extends StatefulWidget { - final void Function(String) onPathFoundCallback; - final String? fileExtension; - final TextStyle? textStyle; const SelectFileWidget({ required this.onPathFoundCallback, this.fileExtension, this.textStyle, - Key? key, - }) : super(key: key); + super.key, + }); + final void Function(String) onPathFoundCallback; + final String? fileExtension; + final TextStyle? textStyle; @override SelectFileWidgetState createState() => SelectFileWidgetState(); @@ -32,8 +32,8 @@ class SelectFileWidgetState extends State { @override Widget build(BuildContext context) { return DropTarget( - onDragDone: (detail) { - String walletFilePath = detail.files.first.path; + onDragDone: (DropDoneDetails detail) { + final String walletFilePath = detail.files.first.path; if (walletFilePath.contains(widget.fileExtension ?? '')) { setState(() { widget.onPathFoundCallback(walletFilePath); @@ -41,12 +41,12 @@ class SelectFileWidgetState extends State { }); } }, - onDragEntered: (detail) { + onDragEntered: (DropEventDetails detail) { setState(() { _dragging = true; }); }, - onDragExited: (detail) { + onDragExited: (DropEventDetails detail) { setState(() { _dragging = false; }); @@ -55,7 +55,7 @@ class SelectFileWidgetState extends State { onTap: () async { String? initialDirectory; initialDirectory = (await getApplicationDocumentsDirectory()).path; - final selectedFile = await openFile( + final XFile? selectedFile = await openFile( acceptedTypeGroups: [ XTypeGroup( label: 'file', @@ -76,7 +76,7 @@ class SelectFileWidgetState extends State { } }, child: FocusableActionDetector( - onShowHoverHighlight: (x) { + onShowHoverHighlight: (bool x) { if (x) { setState(() { _browseButtonHover = true; @@ -92,17 +92,17 @@ class SelectFileWidgetState extends State { color: _browseButtonHover ? AppColors.znnColor : Theme.of(context).textTheme.headlineSmall!.color!, - strokeWidth: 2.0, - dashPattern: const [8.0, 5.0], - radius: const Radius.circular(10.0), + strokeWidth: 2, + dashPattern: const [8, 5], + radius: const Radius.circular(10), child: Container( - height: 100.0, + height: 100, decoration: BoxDecoration( color: _dragging ? Colors.blue.withOpacity(0.4) : Theme.of(context).colorScheme.primary, borderRadius: const BorderRadius.all( - Radius.circular(10.0), + Radius.circular(10), ), ), child: Row( @@ -117,7 +117,7 @@ class SelectFileWidgetState extends State { softWrap: true, textAlign: TextAlign.center, ), - ) + ), ], ), ), diff --git a/lib/widgets/reusable_widgets/settings_address.dart b/lib/widgets/reusable_widgets/settings_address.dart index 97acf695..86961174 100644 --- a/lib/widgets/reusable_widgets/settings_address.dart +++ b/lib/widgets/reusable_widgets/settings_address.dart @@ -7,14 +7,14 @@ import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SettingsAddress extends StatefulWidget { - final String? address; - final void Function(String?) onAddressLabelPressed; const SettingsAddress({ required this.address, required this.onAddressLabelPressed, - Key? key, - }) : super(key: key); + super.key, + }); + final String? address; + final void Function(String?) onAddressLabelPressed; @override State createState() => _SettingsAddressState(); @@ -41,7 +41,7 @@ class _SettingsAddressState extends State { Widget build(BuildContext context) { return Container( margin: const EdgeInsets.symmetric( - vertical: 5.0, + vertical: 5, ), child: _editable ? _getAddressLabelInputField() : _getAddressLabel(context), @@ -50,19 +50,19 @@ class _SettingsAddressState extends State { Row _getAddressLabel(BuildContext context) { return Row( - children: [ + children: [ Expanded( child: InkWell( borderRadius: BorderRadius.circular( - 10.0, + 10, ), onTap: () => widget.onAddressLabelPressed(widget.address), child: Padding( padding: - const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0), + const EdgeInsets.symmetric(horizontal: 5, vertical: 5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( _labelController.text, style: Theme.of(context).textTheme.bodyLarge!.copyWith( @@ -80,10 +80,10 @@ class _SettingsAddressState extends State { ), ), const SizedBox( - width: 5.0, + width: 5, ), MaterialIconButton( - size: 15.0, + size: 15, iconData: Icons.edit, onPressed: () { setState(() { @@ -93,14 +93,14 @@ class _SettingsAddressState extends State { materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 5.0, + width: 5, ), CopyToClipboardIcon( widget.address, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), const SizedBox( - width: 5.0, + width: 5, ), ], ); @@ -109,21 +109,21 @@ class _SettingsAddressState extends State { Widget _getAddressLabelInputField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: SizedBox( - height: 40.0, + height: 40, child: InputField( controller: _labelController, - onSubmitted: (value) { + onSubmitted: (String value) { if (_labelController.text != kAddressLabelMap[widget.address]!) { _onChangeButtonPressed(); } }, - onChanged: (value) { + onChanged: (String value) { setState(() {}); }, inputtedTextStyle: @@ -132,38 +132,38 @@ class _SettingsAddressState extends State { ), enabledBorder: OutlineInputBorder( borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), ), - contentLeftPadding: 5.0, + contentLeftPadding: 5, disabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.white.withOpacity(0.1), ), - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), ), focusedBorder: OutlineInputBorder( borderSide: const BorderSide(color: AppColors.znnColor), - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), ), errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), + borderRadius: BorderRadius.circular(10), borderSide: const BorderSide( color: AppColors.errorColor, - width: 2.0, + width: 2, ), ), ), ), ), const SizedBox( - width: 15.0, + width: 15, ), SettingsButton( onPressed: @@ -174,7 +174,7 @@ class _SettingsAddressState extends State { key: _changeButtonKey, ), MaterialIconButton( - size: 15.0, + size: 15, onPressed: () { setState(() { _labelController.text = kAddressLabelMap[widget.address]!; @@ -197,7 +197,7 @@ class _SettingsAddressState extends State { ); } - void _onChangeButtonPressed() async { + Future _onChangeButtonPressed() async { try { _changeButtonKey.currentState!.showLoadingIndicator(true); if (_labelController.text.isNotEmpty && @@ -213,8 +213,8 @@ class _SettingsAddressState extends State { }); } else if (_labelController.text.isEmpty) { await NotificationUtils.sendNotificationError( - 'Label can\'t be empty', - 'Label can\'t be empty', + "Label can't be empty", + "Label can't be empty", ); } else if (_labelController.text.length > kAddressLabelMaxLength) { await NotificationUtils.sendNotificationError( diff --git a/lib/widgets/reusable_widgets/settings_node.dart b/lib/widgets/reusable_widgets/settings_node.dart index 0984c228..96193710 100644 --- a/lib/widgets/reusable_widgets/settings_node.dart +++ b/lib/widgets/reusable_widgets/settings_node.dart @@ -11,18 +11,18 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class SettingsNode extends StatefulWidget { - final String node; - final void Function(String?) onNodePressed; - final VoidCallback onChangedOrDeletedNode; - final String currentNode; const SettingsNode({ required this.node, required this.onNodePressed, required this.onChangedOrDeletedNode, required this.currentNode, - Key? key, - }) : super(key: key); + super.key, + }); + final String node; + final void Function(String?) onNodePressed; + final VoidCallback onChangedOrDeletedNode; + final String currentNode; @override State createState() => _SettingsNodeState(); @@ -42,7 +42,7 @@ class _SettingsNodeState extends State { void initState() { _nodeController.text = widget.node; - NodeUtils.getNodeChainIdentifier().then((chainIdentifier) { + NodeUtils.getNodeChainIdentifier().then((int chainIdentifier) { connectedNodeChainIdentifier = chainIdentifier; setState(() {}); }); @@ -54,7 +54,7 @@ class _SettingsNodeState extends State { Widget build(BuildContext context) { return Container( margin: const EdgeInsets.symmetric( - vertical: 5.0, + vertical: 5, ), child: _editable ? _getNodeInputField() : _getNode(context), ); @@ -62,20 +62,19 @@ class _SettingsNodeState extends State { Row _getNode(BuildContext context) { return Row( - children: [ + children: [ Expanded( - flex: 1, child: InkWell( borderRadius: BorderRadius.circular( - 10.0, + 10, ), onTap: () => widget.onNodePressed(widget.node), child: Padding( padding: - const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0), + const EdgeInsets.symmetric(horizontal: 5, vertical: 5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( _nodeController.text, style: Theme.of(context).textTheme.bodyLarge!.copyWith( @@ -95,16 +94,16 @@ class _SettingsNodeState extends State { visible: widget.currentNode.contains(widget.node), child: StandardTooltipIcon( (connectedNodeChainIdentifier == getChainIdentifier()) - ? 'Client chain identifier: ${getChainIdentifier().toString()}\n' + ? 'Client chain identifier: ${getChainIdentifier()}\n' 'Node chain identifier: $connectedNodeChainIdentifier' : 'Chain identifier mismatch\n' - 'Client chain identifier: ${getChainIdentifier().toString()}\n' + 'Client chain identifier: ${getChainIdentifier()}\n' 'Node chain identifier: $connectedNodeChainIdentifier', MaterialCommunityIcons.identifier, iconColor: (getChainIdentifier() == connectedNodeChainIdentifier) ? AppColors.znnColor - : AppColors.errorColor)), + : AppColors.errorColor,),), Visibility( visible: widget.node.contains('wss://'), child: const StandardTooltipIcon('Encrypted connection', Icons.lock), @@ -146,9 +145,9 @@ class _SettingsNodeState extends State { !kDefaultCommunityNodes.contains(widget.node), child: IconButton( hoverColor: Colors.transparent, - padding: const EdgeInsets.all(4.0), + padding: const EdgeInsets.all(4), constraints: const BoxConstraints(), - iconSize: 15.0, + iconSize: 15, icon: const Icon( Icons.edit, color: AppColors.znnColor, @@ -159,15 +158,15 @@ class _SettingsNodeState extends State { }); }, tooltip: 'Edit node', - )), + ),), Visibility( visible: !kDefaultNodes.contains(widget.node) && !kDefaultCommunityNodes.contains(widget.node), child: IconButton( hoverColor: Colors.transparent, - padding: const EdgeInsets.all(4.0), + padding: const EdgeInsets.all(4), constraints: const BoxConstraints(), - iconSize: 15.0, + iconSize: 15, icon: const Icon( Icons.delete_forever, color: AppColors.znnColor, @@ -178,13 +177,13 @@ class _SettingsNodeState extends State { title: 'Node Management', description: 'Are you sure you want to delete ' '${widget.node} from the list of nodes? This action ' - 'can\'t be undone.', + "can't be undone.", onYesButtonPressed: () { _deleteNodeFromDb(widget.node); }, ), tooltip: 'Delete node', - )), + ),), ], ); } @@ -192,9 +191,9 @@ class _SettingsNodeState extends State { Widget _getNodeInputField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Row( - children: [ + children: [ Expanded( child: SizedBox( child: Form( @@ -203,7 +202,7 @@ class _SettingsNodeState extends State { child: InputField( controller: _nodeController, hintText: 'Node address with port', - onSubmitted: (value) { + onSubmitted: (String value) { if (_nodeController.text != widget.node && _ifUserInputValid()) { _onChangeButtonPressed(); @@ -216,13 +215,13 @@ class _SettingsNodeState extends State { }); } }, - validator: (value) => - InputValidators.node(value) ?? _nodeError), + validator: (String? value) => + InputValidators.node(value) ?? _nodeError,), ), ), ), const SizedBox( - width: 15.0, + width: 15, ), SettingsButton( onPressed: @@ -233,7 +232,7 @@ class _SettingsNodeState extends State { key: _changeButtonKey, ), MaterialIconButton( - size: 15.0, + size: 15, onPressed: () { setState(() { _nodeController.text = widget.node; @@ -252,18 +251,18 @@ class _SettingsNodeState extends State { bool _ifUserInputValid() => InputValidators.node(_nodeController.text) == null; - void _onChangeButtonPressed() async { + Future _onChangeButtonPressed() async { try { _changeButtonKey.currentState!.showLoadingIndicator(true); if (_nodeController.text.isNotEmpty && _nodeController.text.length <= kAddressLabelMaxLength && - ![...kDefaultNodes, ...kDefaultCommunityNodes, ...kDbNodes] + ![...kDefaultNodes, ...kDefaultCommunityNodes, ...kDbNodes] .contains(_nodeController.text)) { if (!Hive.isBoxOpen(kNodesBox)) { await Hive.openBox(kNodesBox); } - Box nodesBox = Hive.box(kNodesBox); - var nodeKey = nodesBox.keys.firstWhere( + final Box nodesBox = Hive.box(kNodesBox); + final nodeKey = nodesBox.keys.firstWhere( (key) => nodesBox.get(key) == widget.node, ); await nodesBox.put(nodeKey, _nodeController.text); @@ -276,7 +275,7 @@ class _SettingsNodeState extends State { widget.onChangedOrDeletedNode(); } else if (_nodeController.text.isEmpty) { setState(() { - _nodeError = 'Node address can\'t be empty'; + _nodeError = "Node address can't be empty"; }); } else if (_nodeController.text.length > kAddressLabelMaxLength) { setState(() { @@ -303,8 +302,8 @@ class _SettingsNodeState extends State { if (!Hive.isBoxOpen(kNodesBox)) { await Hive.openBox(kNodesBox); } - Box nodesBox = Hive.box(kNodesBox); - var nodeKey = nodesBox.keys.firstWhere( + final Box nodesBox = Hive.box(kNodesBox); + final nodeKey = nodesBox.keys.firstWhere( (key) => nodesBox.get(key) == node, ); await nodesBox.delete(nodeKey); diff --git a/lib/widgets/reusable_widgets/stepper_utils.dart b/lib/widgets/reusable_widgets/stepper_utils.dart index 928174b4..41173f50 100644 --- a/lib/widgets/reusable_widgets/stepper_utils.dart +++ b/lib/widgets/reusable_widgets/stepper_utils.dart @@ -23,27 +23,27 @@ class StepperUtils { ), subtitle: stepState == custom_material_stepper.StepState.complete ? Row( - children: [ + children: [ Text( stepSubtitle, style: Theme.of(context).textTheme.bodyLarge!.copyWith( - fontSize: 12.0, + fontSize: 12, color: stepSubtitleColor, ), ), if (stepSubtitleIconData != null) Icon( stepSubtitleIconData, - size: 15.0, + size: 15, color: stepSubtitleColor, ), ], ) : null, content: Container( - margin: const EdgeInsets.only(left: 37.0), + margin: const EdgeInsets.only(left: 37), child: Row( - children: [ + children: [ Expanded( child: stepContent, ), @@ -59,7 +59,7 @@ class StepperUtils { } static custom_material_stepper.StepState getStepState( - int currentStepIndex, int? completedStepIndex) { + int currentStepIndex, int? completedStepIndex,) { return currentStepIndex <= (completedStepIndex ?? -1) ? custom_material_stepper.StepState.complete : custom_material_stepper.StepState.indexed; @@ -67,11 +67,11 @@ class StepperUtils { static Widget getBalanceWidget(Token token, AccountInfo accountInfo) { return Row( - children: [ + children: [ Expanded( child: Padding( - padding: const EdgeInsets.only(left: 20.0, top: 10.0, bottom: 10.0), + padding: const EdgeInsets.only(left: 20, top: 10, bottom: 10), child: AvailableBalance( token, accountInfo, diff --git a/lib/widgets/reusable_widgets/syrius_checkbox.dart b/lib/widgets/reusable_widgets/syrius_checkbox.dart index 1b119d80..3440ed70 100644 --- a/lib/widgets/reusable_widgets/syrius_checkbox.dart +++ b/lib/widgets/reusable_widgets/syrius_checkbox.dart @@ -3,14 +3,8 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_colors.dart'; class SyriusCheckbox extends Checkbox { SyriusCheckbox({ - Key? key, - required Function(bool?) onChanged, - required bool? value, - required BuildContext context, + required Function(bool?) super.onChanged, required super.value, required BuildContext context, super.key, }) : super( - key: key, - onChanged: onChanged, - value: value, checkColor: Theme.of(context).scaffoldBackgroundColor, activeColor: AppColors.znnColor, ); diff --git a/lib/widgets/reusable_widgets/tag_widget.dart b/lib/widgets/reusable_widgets/tag_widget.dart index 4aca3b00..5532abb4 100644 --- a/lib/widgets/reusable_widgets/tag_widget.dart +++ b/lib/widgets/reusable_widgets/tag_widget.dart @@ -3,11 +3,6 @@ import 'package:zenon_syrius_wallet_flutter/utils/app_theme.dart'; import 'package:zenon_syrius_wallet_flutter/utils/color_utils.dart'; class TagWidget extends StatelessWidget { - final IconData? iconData; - final VoidCallback? onPressed; - final String text; - final String? hexColorCode; - final Color? textColor; const TagWidget({ required this.text, @@ -15,38 +10,43 @@ class TagWidget extends StatelessWidget { this.onPressed, this.iconData, this.textColor, - Key? key, - }) : super(key: key); + super.key, + }); + final IconData? iconData; + final VoidCallback? onPressed; + final String text; + final String? hexColorCode; + final Color? textColor; @override Widget build(BuildContext context) { return Row( - children: [ + children: [ InkWell( onTap: onPressed, - borderRadius: BorderRadius.circular(50.0), + borderRadius: BorderRadius.circular(50), child: Container( - padding: const EdgeInsets.symmetric(horizontal: 15.0), - height: 25.0, + padding: const EdgeInsets.symmetric(horizontal: 15), + height: 25, alignment: Alignment.center, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(50.0), + borderRadius: BorderRadius.circular(50), color: hexColorCode != null ? ColorUtils.getColorFromHexCode(hexColorCode!) : Theme.of(context).colorScheme.secondary, ), child: Row( - children: [ + children: [ if (iconData != null) Row( - children: [ + children: [ Icon( iconData, color: Colors.white, - size: 15.0, + size: 15, ), const SizedBox( - width: 5.0, + width: 5, ), ], ), @@ -61,7 +61,7 @@ class TagWidget extends StatelessWidget { ), ), const SizedBox( - width: 10.0, + width: 10, ), ], ); diff --git a/lib/widgets/reusable_widgets/transfer_icon_legend.dart b/lib/widgets/reusable_widgets/transfer_icon_legend.dart index 03680c5f..7040826e 100644 --- a/lib/widgets/reusable_widgets/transfer_icon_legend.dart +++ b/lib/widgets/reusable_widgets/transfer_icon_legend.dart @@ -1,35 +1,32 @@ import 'package:flutter/material.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; class TransferIconLegend extends StatelessWidget { - final String legendText; const TransferIconLegend({ required this.legendText, - Key? key, - }) : super(key: key); + super.key, + }); + final String legendText; @override Widget build(BuildContext context) { return Container( - width: 80.0, padding: const EdgeInsets.symmetric( - vertical: 5.0, + vertical: 5, + horizontal: 10, ), decoration: BoxDecoration( color: Colors.black12, borderRadius: BorderRadius.circular( - 10.0, + 10, ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - legendText, - style: Theme.of(context).textTheme.bodyMedium, - ), - ], + child: Text( + legendText, + style: context.textTheme.bodyMedium, + maxLines: 1, + overflow: TextOverflow.ellipsis, ), ); } diff --git a/lib/widgets/tab_children_widgets/accelerator_tab_child.dart b/lib/widgets/tab_children_widgets/accelerator_tab_child.dart index c7615d16..96f9f571 100644 --- a/lib/widgets/tab_children_widgets/accelerator_tab_child.dart +++ b/lib/widgets/tab_children_widgets/accelerator_tab_child.dart @@ -8,24 +8,24 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class AcceleratorTabChild extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const AcceleratorTabChild({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override Widget build(BuildContext context) { return FutureBuilder>( future: zenon!.embedded.pillar.getByOwner(Address.parse(kSelectedAddress!)), - builder: (_, snapshot) { + builder: (_, AsyncSnapshot> snapshot) { if (snapshot.hasError) { return SyriusErrorWidget(snapshot.error.toString()); } else if (snapshot.hasData) { return _getLayout( - context, snapshot.data!.isNotEmpty ? snapshot.data!.first : null); + context, snapshot.data!.isNotEmpty ? snapshot.data!.first : null,); } return const SyriusLoadingWidget(); }, @@ -34,7 +34,7 @@ class AcceleratorTabChild extends StatelessWidget { StandardFluidLayout _getLayout(BuildContext context, PillarInfo? pillarInfo) { return StandardFluidLayout( - children: [ + children: [ FluidCell( width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 3, diff --git a/lib/widgets/tab_children_widgets/dashboard_tab_child.dart b/lib/widgets/tab_children_widgets/dashboard_tab_child.dart index e8016d46..a55fda75 100644 --- a/lib/widgets/tab_children_widgets/dashboard_tab_child.dart +++ b/lib/widgets/tab_children_widgets/dashboard_tab_child.dart @@ -2,17 +2,18 @@ import 'package:flutter/material.dart'; import 'package:layout/layout.dart'; import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/main.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class DashboardTabChild extends StatefulWidget { + + const DashboardTabChild({super.key, this.changePage}); final void Function( Tabs, { bool redirectWithSendContainerLarge, bool redirectWithReceiveContainerLarge, })? changePage; - const DashboardTabChild({Key? key, this.changePage}) : super(key: key); - @override State createState() => _DashboardTabChildState(); } @@ -38,44 +39,44 @@ class _DashboardTabChildState extends State { xs: kStaggeredNumOfColumns ~/ 2, ); - final List children = [ + final List children = [ const FluidCell( - child: DualCoinStats(), + child: DualCoinStatsCard(), ), const FluidCell( child: PlasmaStats(), ), FluidCell( - child: Transfer( + child: TransferCard( changePage: widget.changePage, ), ), const FluidCell( - child: TotalHourlyTransactions(), + child: TotalHourlyTransactionsCard(), height: kStaggeredNumOfColumns / 4, ), const FluidCell( - child: Pillars(), + child: PillarsCard(), height: kStaggeredNumOfColumns / 8, ), const FluidCell( - child: Staking(), + child: StakingCard(), height: kStaggeredNumOfColumns / 8, ), const FluidCell( - child: DelegationStats(), + child: DelegationCard(), height: kStaggeredNumOfColumns / 8, ), const FluidCell( - child: Sentinels(), + child: SentinelsCard(), height: kStaggeredNumOfColumns / 8, ), FluidCell( - child: const BalanceWidget(), + child: const BalanceCard(), width: defaultCellWidth * 2, ), FluidCell( - child: const RealtimeStatistics(), + child: const RealtimeStatisticsCard(), width: defaultCellWidth * 2, ), FluidCell( @@ -88,7 +89,6 @@ class _DashboardTabChildState extends State { return StandardFluidLayout( defaultCellWidth: defaultCellWidth, - defaultCellHeight: kStaggeredNumOfColumns / 4, children: children, ); } diff --git a/lib/widgets/tab_children_widgets/help_tab_child.dart b/lib/widgets/tab_children_widgets/help_tab_child.dart index 3536ac8a..b54909c9 100644 --- a/lib/widgets/tab_children_widgets/help_tab_child.dart +++ b/lib/widgets/tab_children_widgets/help_tab_child.dart @@ -3,12 +3,12 @@ import 'package:layout/layout.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class HelpTabChild extends StatelessWidget { - const HelpTabChild({Key? key}) : super(key: key); + const HelpTabChild({super.key}); @override Widget build(BuildContext context) { return StandardFluidLayout( - children: [ + children: [ FluidCell( width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 3, diff --git a/lib/widgets/tab_children_widgets/lock_tab_child.dart b/lib/widgets/tab_children_widgets/lock_tab_child.dart index 8f23c260..8ac249cd 100644 --- a/lib/widgets/tab_children_widgets/lock_tab_child.dart +++ b/lib/widgets/tab_children_widgets/lock_tab_child.dart @@ -9,20 +9,19 @@ import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; import 'package:zenon_syrius_wallet_flutter/utils/extensions.dart'; import 'package:zenon_syrius_wallet_flutter/utils/global.dart'; import 'package:zenon_syrius_wallet_flutter/utils/init_utils.dart'; -import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/navigation_utils.dart'; import 'package:zenon_syrius_wallet_flutter/utils/notification_utils.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/wallet_utils.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; import 'package:znn_ledger_dart/znn_ledger_dart.dart'; import 'package:znn_sdk_dart/znn_sdk_dart.dart'; class LockTabChild extends StatefulWidget { - final Future Function(String) afterUnlockCallback; - final Function() afterInitCallback; const LockTabChild(this.afterUnlockCallback, this.afterInitCallback, - {Key? key}) - : super(key: key); + {super.key,}); + final Future Function(String) afterUnlockCallback; + final Function() afterInitCallback; @override State createState() => _LockTabChildState(); @@ -48,30 +47,29 @@ class _LockTabChildState extends State { return Container( color: Theme.of(context).colorScheme.primary, child: Column( - crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon( Fontisto.locked, color: AppColors.znnColor, - size: 50.0, + size: 50, ), const SizedBox( - height: 40.0, + height: 40, ), Text( 'Welcome Back', style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox( - height: 20.0, + height: 20, ), Text( 'Enter the password to access the wallet', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( - height: 40.0, + height: 40, ), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -79,18 +77,18 @@ class _LockTabChildState extends State { PasswordInputField( controller: _passwordController, hintText: 'Current password', - onSubmitted: (value) { + onSubmitted: (String value) { _actionButton!.onPressed!(); }, ), const SizedBox( - width: 10.0, + width: 10, ), _actionButton!, ], ), const SizedBox( - height: 30.0, + height: 30, ), Visibility( visible: _messageToUser.isEmpty, @@ -110,7 +108,7 @@ class _LockTabChildState extends State { Visibility( visible: _messageToUser.isNotEmpty, child: Padding( - padding: const EdgeInsets.only(top: 30.0), + padding: const EdgeInsets.only(top: 30), child: Text( _messageToUser, style: Theme.of(context).textTheme.bodyLarge, @@ -129,7 +127,7 @@ class _LockTabChildState extends State { icon: const Icon( AntDesign.arrowright, color: AppColors.znnColor, - size: 25.0, + size: 25, ), ); } @@ -169,7 +167,7 @@ class _LockTabChildState extends State { _messageToUser = 'Initializing wallet, please wait'; }); await InitUtils.initWalletAfterDecryption( - Crypto.digest(utf8.encode(_passwordController.text))); + Crypto.digest(utf8.encode(_passwordController.text)),); widget.afterInitCallback(); } else { await widget.afterUnlockCallback(_passwordController.text); @@ -196,9 +194,7 @@ class _LockTabChildState extends State { } void _resetScreenState() { - setState(() { - _cleanScreen(); - }); + setState(_cleanScreen); } void _cleanScreen() { diff --git a/lib/widgets/tab_children_widgets/notifications_tab_child.dart b/lib/widgets/tab_children_widgets/notifications_tab_child.dart index 73e510c7..0c9c7c11 100644 --- a/lib/widgets/tab_children_widgets/notifications_tab_child.dart +++ b/lib/widgets/tab_children_widgets/notifications_tab_child.dart @@ -9,7 +9,7 @@ import 'package:zenon_syrius_wallet_flutter/widgets/reusable_widgets/icons/clear import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class NotificationsTabChild extends StatefulWidget { - const NotificationsTabChild({Key? key}) : super(key: key); + const NotificationsTabChild({super.key}); @override State createState() => _NotificationsTabChildState(); @@ -23,7 +23,6 @@ class _NotificationsTabChildState extends State { _loadNotifications(); return WidgetAnimator( - curve: Curves.linear, child: _getNotificationsContainer(), ); } @@ -35,7 +34,7 @@ class _NotificationsTabChildState extends State { 'wallet notifications', childBuilder: () => CustomTable( items: _notifications, - headerColumns: const [ + headerColumns: const [ CustomHeaderColumn(columnName: 'Description', flex: 5), CustomHeaderColumn(columnName: 'Date', flex: 2), CustomHeaderColumn(columnName: 'Time', flex: 2), @@ -43,12 +42,12 @@ class _NotificationsTabChildState extends State { columnName: '', ), ], - generateRowCells: _rowCellsGenerator), + generateRowCells: _rowCellsGenerator,), ); } ExpandablePanel _getNotificationExpandablePanel( - WalletNotification notification) { + WalletNotification notification,) { return ExpandablePanel( collapsed: Container(), theme: ExpandableThemeData( @@ -57,10 +56,10 @@ class _NotificationsTabChildState extends State { iconPlacement: ExpandablePanelIconPlacement.right, ), header: Row( - children: [ + children: [ notification.getIcon(), const SizedBox( - width: 10.0, + width: 10, ), Expanded( child: Text( @@ -71,9 +70,9 @@ class _NotificationsTabChildState extends State { ], ), expanded: Padding( - padding: const EdgeInsets.only(left: 14.0, top: 5.0, bottom: 5.0), + padding: const EdgeInsets.only(left: 14, top: 5, bottom: 5), child: Row( - children: [ + children: [ Expanded( child: Text( notification.details!, @@ -96,8 +95,8 @@ class _NotificationsTabChildState extends State { List _getNotificationsFromDb() { try { - Box notificationsBox = Hive.box(kNotificationsBox); - List keys = notificationsBox.keys.toList(); + final Box notificationsBox = Hive.box(kNotificationsBox); + final List keys = notificationsBox.keys.toList(); if (keys.length >= kNotificationsResultLimit) { return List.from( notificationsBox.valuesBetween( @@ -112,14 +111,14 @@ class _NotificationsTabChildState extends State { ) .toList(); } catch (e) { - return []; + return []; } } Future _deleteNotification(int? notificationTimestamp) async { - Box notificationsBox = Hive.box(kNotificationsBox); + final Box notificationsBox = Hive.box(kNotificationsBox); - var notificationKey = notificationsBox.keys.firstWhere( + final notificationKey = notificationsBox.keys.firstWhere( (key) => notificationsBox.get(key).timestamp == notificationTimestamp, ); @@ -130,7 +129,7 @@ class _NotificationsTabChildState extends State { void _loadNotifications() { _notifications = _getNotificationsFromDb(); - _notifications!.sort((a, b) => b.timestamp!.compareTo(a.timestamp!)); + _notifications!.sort((WalletNotification a, WalletNotification b) => b.timestamp!.compareTo(a.timestamp!)); } List _rowCellsGenerator( @@ -138,7 +137,7 @@ class _NotificationsTabChildState extends State { isSelected, { SentinelsListBloc? model, }) { - return [ + return [ CustomTableCell( _getNotificationExpandablePanel(notification), flex: 5, @@ -151,7 +150,7 @@ class _NotificationsTabChildState extends State { CustomTableCell.withText( context, FormatUtils.formatDate(notification.timestamp, - dateFormat: kNotificationsTimeFormat), + dateFormat: kNotificationsTimeFormat,), flex: 2, ), CustomTableCell(_getClearIcon(notification)), diff --git a/lib/widgets/tab_children_widgets/p2p_swap_tab_child.dart b/lib/widgets/tab_children_widgets/p2p_swap_tab_child.dart index ac20e942..286d1feb 100644 --- a/lib/widgets/tab_children_widgets/p2p_swap_tab_child.dart +++ b/lib/widgets/tab_children_widgets/p2p_swap_tab_child.dart @@ -2,17 +2,17 @@ import 'package:flutter/material.dart'; import 'package:layout/layout.dart'; import 'package:provider/provider.dart'; import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; -import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/p2p_swap_options_card.dart'; +import 'package:zenon_syrius_wallet_flutter/widgets/modular_widgets/p2p_swap_widgets/p2p_swaps_card.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class P2pSwapTabChild extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const P2pSwapTabChild({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => P2pSwapTabChildState(); @@ -34,7 +34,7 @@ class P2pSwapTabChildState extends State { StandardFluidLayout _getLayout(BuildContext context) { return StandardFluidLayout( - children: [ + children: [ FluidCell( height: kStaggeredNumOfColumns / 2, width: context.layout.value( diff --git a/lib/widgets/tab_children_widgets/pillars_tab_child.dart b/lib/widgets/tab_children_widgets/pillars_tab_child.dart index 4e1b589d..d85c71f9 100644 --- a/lib/widgets/tab_children_widgets/pillars_tab_child.dart +++ b/lib/widgets/tab_children_widgets/pillars_tab_child.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class PillarsTabChild extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const PillarsTabChild({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _PillarsTabChildState(); @@ -21,7 +21,7 @@ class _PillarsTabChildState extends State { @override Widget build(BuildContext context) { - final List children = [ + final List children = [ FluidCell( child: PillarRewards( pillarRewardsHistoryBloc: _pillarRewardsHistoryBloc, diff --git a/lib/widgets/tab_children_widgets/plasma_tab_child.dart b/lib/widgets/tab_children_widgets/plasma_tab_child.dart index 34a6fb52..d8d0084b 100644 --- a/lib/widgets/tab_children_widgets/plasma_tab_child.dart +++ b/lib/widgets/tab_children_widgets/plasma_tab_child.dart @@ -8,7 +8,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/notifiers/plasma_generated_not import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class PlasmaTabChild extends StatefulWidget { - const PlasmaTabChild({Key? key}) : super(key: key); + const PlasmaTabChild({super.key}); @override State createState() { @@ -30,9 +30,9 @@ class _PlasmaTabChildState extends State { Widget build(BuildContext context) { return StreamBuilder>( stream: sl.get().stream, - builder: (_, snapshot) { + builder: (_, AsyncSnapshot> snapshot) { if (snapshot.hasError) { - return _getFluidLayout([], errorText: snapshot.error.toString()); + return _getFluidLayout([], errorText: snapshot.error.toString()); } if (snapshot.connectionState == ConnectionState.active) { if (snapshot.hasData) { @@ -50,7 +50,7 @@ class _PlasmaTabChildState extends State { String? errorText, }) { return StandardFluidLayout( - children: [ + children: [ FluidCell( child: Consumer( builder: (_, __, ___) => const PlasmaStats( diff --git a/lib/widgets/tab_children_widgets/sentinels_tab_child.dart b/lib/widgets/tab_children_widgets/sentinels_tab_child.dart index 018f2196..b31f316c 100644 --- a/lib/widgets/tab_children_widgets/sentinels_tab_child.dart +++ b/lib/widgets/tab_children_widgets/sentinels_tab_child.dart @@ -4,12 +4,12 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SentinelsTabChild extends StatefulWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const SentinelsTabChild({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override State createState() => _SentinelsTabChildState(); @@ -21,7 +21,7 @@ class _SentinelsTabChildState extends State { @override Widget build(BuildContext context) { - final List children = [ + final List children = [ FluidCell( child: SentinelRewards( sentinelRewardsHistoryBloc: _sentinelRewardsHistoryBloc, diff --git a/lib/widgets/tab_children_widgets/settings_tab_child.dart b/lib/widgets/tab_children_widgets/settings_tab_child.dart index 2a67efd2..c4376692 100644 --- a/lib/widgets/tab_children_widgets/settings_tab_child.dart +++ b/lib/widgets/tab_children_widgets/settings_tab_child.dart @@ -4,16 +4,16 @@ import 'package:zenon_syrius_wallet_flutter/blocs/blocs.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class SettingsTabChild extends StatefulWidget { - final VoidCallback _onChangeAutoLockTime; - final VoidCallback onStepperNotificationSeeMorePressed; - final VoidCallback onNodeChangedCallback; const SettingsTabChild( this._onChangeAutoLockTime, { required this.onStepperNotificationSeeMorePressed, required this.onNodeChangedCallback, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback _onChangeAutoLockTime; + final VoidCallback onStepperNotificationSeeMorePressed; + final VoidCallback onNodeChangedCallback; @override State createState() => _SettingsTabChildState(); @@ -32,7 +32,7 @@ class _SettingsTabChildState extends State { sm: kStaggeredNumOfColumns, xs: kStaggeredNumOfColumns, ), - children: [ + children: [ FluidCell( width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 2, @@ -79,7 +79,7 @@ class _SettingsTabChildState extends State { onStepperNotificationSeeMorePressed: widget.onStepperNotificationSeeMorePressed, ), - height: kStaggeredNumOfColumns / 2 + height: kStaggeredNumOfColumns / 2, ), FluidCell( width: context.layout.value( @@ -90,7 +90,7 @@ class _SettingsTabChildState extends State { xs: kStaggeredNumOfColumns, ), child: const DisplayWidget(), - height: kStaggeredNumOfColumns / 2 + height: kStaggeredNumOfColumns / 2, ), FluidCell( child: const WalletOptions(), diff --git a/lib/widgets/tab_children_widgets/staking_tab_child.dart b/lib/widgets/tab_children_widgets/staking_tab_child.dart index f6faf556..ce915d60 100644 --- a/lib/widgets/tab_children_widgets/staking_tab_child.dart +++ b/lib/widgets/tab_children_widgets/staking_tab_child.dart @@ -6,7 +6,7 @@ import 'package:zenon_syrius_wallet_flutter/utils/notifiers/default_address_noti import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class StakingTabChild extends StatefulWidget { - const StakingTabChild({Key? key}) : super(key: key); + const StakingTabChild({super.key}); @override State createState() { @@ -25,7 +25,7 @@ class _StakingTabChildState extends State { } Widget _getFluidLayout() { - final List children = [ + final List children = [ FluidCell( child: StakingRewards( stakingRewardsHistoryBloc: _stakingRewardsHistoryBloc, @@ -52,7 +52,7 @@ class _StakingTabChildState extends State { ), FluidCell( child: Consumer( - builder: (_, __, child) => StakingOptions(_stakingListBloc), + builder: (_, __, Widget? child) => StakingOptions(_stakingListBloc), ), width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 3, diff --git a/lib/widgets/tab_children_widgets/tab_children_widgets.dart b/lib/widgets/tab_children_widgets/tab_children_widgets.dart index ef80719d..b69ee3e5 100644 --- a/lib/widgets/tab_children_widgets/tab_children_widgets.dart +++ b/lib/widgets/tab_children_widgets/tab_children_widgets.dart @@ -3,9 +3,9 @@ export 'dashboard_tab_child.dart'; export 'help_tab_child.dart'; export 'lock_tab_child.dart'; export 'notifications_tab_child.dart'; +export 'p2p_swap_tab_child.dart'; export 'pillars_tab_child.dart'; export 'plasma_tab_child.dart'; -export 'p2p_swap_tab_child.dart'; export 'sentinels_tab_child.dart'; export 'settings_tab_child.dart'; export 'staking_tab_child.dart'; diff --git a/lib/widgets/tab_children_widgets/tokens_tab_child.dart b/lib/widgets/tab_children_widgets/tokens_tab_child.dart index c586af38..a32f9308 100644 --- a/lib/widgets/tab_children_widgets/tokens_tab_child.dart +++ b/lib/widgets/tab_children_widgets/tokens_tab_child.dart @@ -3,17 +3,17 @@ import 'package:layout/layout.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class TokensTabChild extends StatelessWidget { - final VoidCallback onStepperNotificationSeeMorePressed; const TokensTabChild({ required this.onStepperNotificationSeeMorePressed, - Key? key, - }) : super(key: key); + super.key, + }); + final VoidCallback onStepperNotificationSeeMorePressed; @override Widget build(BuildContext context) { return StandardFluidLayout( - children: [ + children: [ FluidCell( width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 3, diff --git a/lib/widgets/tab_children_widgets/transfer_tab_child.dart b/lib/widgets/tab_children_widgets/transfer_tab_child.dart index 5e7ad643..00e9cce3 100644 --- a/lib/widgets/tab_children_widgets/transfer_tab_child.dart +++ b/lib/widgets/tab_children_widgets/transfer_tab_child.dart @@ -5,14 +5,14 @@ import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; enum DimensionCard { small, medium, large } class TransferTabChild extends StatefulWidget { - DimensionCard sendCard; - DimensionCard receiveCard; TransferTabChild({ - Key? key, + super.key, this.sendCard = DimensionCard.medium, this.receiveCard = DimensionCard.medium, - }) : super(key: key); + }); + DimensionCard sendCard; + DimensionCard receiveCard; @override State createState() => _TransferTabChildState(); @@ -22,7 +22,7 @@ class _TransferTabChildState extends State { @override Widget build(BuildContext context) { return StandardFluidLayout( - children: [ + children: [ _getSendCard(), _getReceiveCard(), const FluidCell( diff --git a/lib/widgets/tab_children_widgets/wallet_connect_tab_child.dart b/lib/widgets/tab_children_widgets/wallet_connect_tab_child.dart index f82a8584..f03372e8 100644 --- a/lib/widgets/tab_children_widgets/wallet_connect_tab_child.dart +++ b/lib/widgets/tab_children_widgets/wallet_connect_tab_child.dart @@ -3,12 +3,12 @@ import 'package:layout/layout.dart'; import 'package:zenon_syrius_wallet_flutter/widgets/widgets.dart'; class WalletConnectTabChild extends StatelessWidget { - const WalletConnectTabChild({Key? key}) : super(key: key); + const WalletConnectTabChild({super.key}); @override Widget build(BuildContext context) { return StandardFluidLayout( - children: [ + children: [ FluidCell( width: context.layout.value( xl: kStaggeredNumOfColumns ~/ 3, diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index 7a7c38dc..f23b3668 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -1,5 +1,4 @@ export 'charts/pillar_rewards_chart.dart'; -export 'charts/realtime_txs_chart.dart'; export 'charts/sentinel_rewards_chart.dart'; export 'charts/staking_rewards_chart.dart'; export 'main_app_container.dart'; diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 2c99e53e..2c1ccb1d 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -140,50 +140,77 @@ endif() # Bundle required ZNN libraries for Syrius set(SYRIUS_PROJECT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/..") -# Leveraging flutter to identify dependency locations -file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_SDK_DART_PATH REGEX "(file:).*(znn_sdk_dart).*\\/\"" ) - -if (ZNN_SDK_DART_PATH STREQUAL "") - file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_SDK_DART_PATH REGEX "(rootUri).*(znn_sdk_dart).*\"" ) - string(REPLACE "\"rootUri\": \"" "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") - string(REPLACE "/\"," "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") - string(REPLACE "\"," "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") - string(STRIP "${ZNN_SDK_DART_PATH}" ZNN_SDK_DART_PATH) -else() - string(REPLACE "\"rootUri\": \"file://" "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") - string(REPLACE "/\"," "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") - string(STRIP "${ZNN_SDK_DART_PATH}" ZNN_SDK_DART_PATH) -endif() - -file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_LEDGER_DART_PATH REGEX "(file:).*(znn_ledger_dart).*\\/\"" ) - -if (ZNN_LEDGER_DART_PATH STREQUAL "") - file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_LEDGER_DART_PATH REGEX "(rootUri).*(znn_ledger_dart).*\"" ) - string(REPLACE "\"rootUri\": \"" "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") - string(REPLACE "/\"," "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") - string(REPLACE "\"," "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") - string(STRIP "${ZNN_LEDGER_DART_PATH}" ZNN_LEDGER_DART_PATH) -else() - string(REPLACE "\"rootUri\": \"file://" "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") - string(REPLACE "/\"," "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") - string(STRIP "${ZNN_LEDGER_DART_PATH}" ZNN_LEDGER_DART_PATH) -endif() - +# Read lines from the file `package_config_subset` that match the regex pattern +# looking for paths containing "znn_sdk_dart" and ending with a "/". +file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config_subset" + ZNN_SDK_DART_PATHS REGEX "(file:).*(znn_sdk_dart).*/$" ) + +# Initialize an empty variable to store the final znn_sdk_dart path +set(ZNN_SDK_DART_PATH "") + +# Loop through each path found by the file command +foreach(PATH ${ZNN_SDK_DART_PATHS}) + # Exclude paths containing "/lib/" using a conditional check + if(NOT "${PATH}" MATCHES ".*/lib/.*") + # If the condition is met, set the current path as ZNN_SDK_DART_PATH + set(ZNN_SDK_DART_PATH ${PATH}) + endif() +endforeach() + +# Remove the "file://" prefix from the selected path, if present +string(REPLACE "file://" "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") + +# Strip any leading or trailing whitespace from the cleaned path +string(STRIP "${ZNN_SDK_DART_PATH}" ZNN_SDK_DART_PATH) + +# Repeat the same process for "znn_ledger_dart" paths: + +# Read lines from the file `package_config_subset` that match the regex pattern +# looking for paths containing "znn_ledger_dart" and ending with a "/". +file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config_subset" + ZNN_LEDGER_DART_PATHS REGEX "(file:).*(znn_ledger_dart).*/$" ) + +# Initialize an empty variable to store the final znn_ledger_dart path +set(ZNN_LEDGER_DART_PATH "") + +# Loop through each path found by the file command +foreach(PATH ${ZNN_LEDGER_DART_PATHS}) + # Exclude paths containing "/lib/" using a conditional check + if(NOT "${PATH}" MATCHES ".*/lib/.*") + # If the condition is met, set the current path as ZNN_LEDGER_DART_PATH + set(ZNN_LEDGER_DART_PATH ${PATH}) + endif() +endforeach() + +# Remove the "file://" prefix from the selected path, if present +string(REPLACE "file://" "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") + +# Strip any leading or trailing whitespace from the cleaned path +string(STRIP "${ZNN_LEDGER_DART_PATH}" ZNN_LEDGER_DART_PATH) + +# Append the paths to various library files into the `SYRIUS_LIBRARIES` list. +# These paths include: +# 1. A static path to `libznn.so` located in the `embedded_node/blobs` directory. +# 2. Dynamically constructed paths based on `ZNN_SDK_DART_PATH` and `ZNN_LEDGER_DART_PATH`. +# These paths point to shared libraries for argon2, proof-of-work, and ledger functionality. list(APPEND SYRIUS_LIBRARIES - "${SYRIUS_PROJECT_DIRECTORY}/lib/embedded_node/blobs/libznn.so" - "${ZNN_SDK_DART_PATH}/lib/src/argon2/blobs/libargon2_ffi_plugin.so" - "${ZNN_SDK_DART_PATH}/lib/src/pow/blobs/libpow_links.so" - "${ZNN_LEDGER_DART_PATH}/lib/src/ledger/blobs/libledger_ffi.so" -) + "${SYRIUS_PROJECT_DIRECTORY}/lib/embedded_node/blobs/libznn.so" # Path to libznn.so + "${ZNN_SDK_DART_PATH}/lib/src/argon2/blobs/libargon2_ffi_plugin.so" # Argon2 plugin + "${ZNN_SDK_DART_PATH}/lib/src/pow/blobs/libpow_links.so" # Proof-of-work library + "${ZNN_LEDGER_DART_PATH}/lib/src/ledger/blobs/libledger_ffi.so" # Ledger FFI library + ) +# Loop over each library in the `SYRIUS_LIBRARIES` list. foreach(znn_library ${SYRIUS_LIBRARIES}) + # Install the library to the destination specified by `CMAKE_INSTALL_PREFIX`. + # `FILES` specifies the file to copy. + # `DESTINATION` specifies where the file should be installed. + # `COMPONENT` groups the installation under the "Runtime" component for packaging or deployment tools. install(FILES "${znn_library}" - DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + + # Print a status message indicating that the current library is being copied. message(STATUS "Copy ZNN library: \"${znn_library}\"") endforeach(znn_library) diff --git a/macos/Podfile b/macos/Podfile index dade8dfa..049abe29 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.11' +platform :osx, '10.14' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 9bda8154..a23f750f 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -217,7 +217,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -382,7 +382,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "OUTPUT_DIRECTORY=\"./\"\n\nPACKAGE_CONFIG=\"../.dart_tool/package_config.json\"\nZNN_SDK_DART_PATH=`cat $PACKAGE_CONFIG | grep git/znn_sdk_dart | sed 's/\"rootUri\": \"file:\\/\\///' | sed 's/\\/\",//' | xargs` \n\nSYRIUS_LIBRARIES=(\n \"$ZNN_SDK_DART_PATH/lib/src/argon2/blobs/libargon2_ffi.dylib\"\n \"$ZNN_SDK_DART_PATH/lib/src/pow/blobs/libpow_links.dylib\"\n)\n\necho \"$OUTPUT_DIRECTORY\"\n\nfor znn_library in ${SYRIUS_LIBRARIES[@]}; do\n echo \"Copy ZNN library: $znn_library\"\n cp $znn_library \"$OUTPUT_DIRECTORY\"\ndone\n"; + shellScript = "OUTPUT_DIRECTORY=\"./\"\n\nPACKAGE_CONFIG=\"../.dart_tool/package_config_subset\"\n\n# Locate the line containing the desired path for znn_sdk_dart (not ending with /lib/)\nZNN_SDK_DART_PATH=$(grep \"file:///.*znn_sdk_dart\" $PACKAGE_CONFIG | grep -v \"/lib/\" | sed 's|file:///||' | sed 's|//|/|g')\n\n# Ensure the path starts with a slash for macOS or Unix-based systems\nZNN_SDK_DART_PATH=\"/$ZNN_SDK_DART_PATH\"\n\nSYRIUS_LIBRARIES=(\n \"$ZNN_SDK_DART_PATH/lib/src/argon2/blobs/libargon2_ffi.dylib\"\n \"$ZNN_SDK_DART_PATH/lib/src/pow/blobs/libpow_links.dylib\"\n)\n\necho \"$OUTPUT_DIRECTORY\"\n\nfor znn_library in ${SYRIUS_LIBRARIES[@]}; do\n # Clean up any accidental double slashes in the paths\n znn_library=$(echo $znn_library | sed 's|//|/|g')\n echo \"Copy ZNN library: $znn_library\"\n cp $znn_library \"$OUTPUT_DIRECTORY\"\ndone\n"; }; 96DA2500296EB70F00545E88 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -399,7 +399,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "OUTPUT_DIRECTORY=\"./\"\n\nPACKAGE_CONFIG=\"../.dart_tool/package_config.json\"\nZNN_LEDGER_DART_PATH=`cat $PACKAGE_CONFIG | grep git/znn_ledger_dart | sed 's/\"rootUri\": \"file:\\/\\///' | sed 's/\\/\",//' | xargs` \n\nSYRIUS_LIBRARIES=(\n \"$ZNN_LEDGER_DART_PATH/lib/src/ledger/blobs/libledger_ffi.dylib\"\n)\n\necho \"$OUTPUT_DIRECTORY\"\n\nfor znn_library in ${SYRIUS_LIBRARIES[@]}; do\n echo \"Copy ZNN library: $znn_library\"\n cp $znn_library \"$OUTPUT_DIRECTORY\"\ndone\n"; + shellScript = "OUTPUT_DIRECTORY=\"./\"\n\nPACKAGE_CONFIG=\"../.dart_tool/package_config_subset\"\n\n# Locate the line containing the desired path for znn_ledger_dart (not ending with /lib/)\nZNN_LEDGER_DART_PATH=$(grep \"file:///.*znn_ledger_dart\" $PACKAGE_CONFIG | grep -v \"/lib/\" | sed 's|file:///||' | sed 's|//|/|g')\n\n# Ensure the path starts with a slash for macOS or Unix-based systems\nZNN_LEDGER_DART_PATH=\"/$ZNN_LEDGER_DART_PATH\"\n\nSYRIUS_LIBRARIES=(\n \"$ZNN_LEDGER_DART_PATH/lib/src/ledger/blobs/libledger_ffi.dylib\"\n)\n\necho \"$OUTPUT_DIRECTORY\"\n\nfor znn_library in ${SYRIUS_LIBRARIES[@]}; do\n # Clean up any accidental double slashes in the paths\n znn_library=$(echo $znn_library | sed 's|//|/|g')\n echo \"Copy ZNN library: $znn_library\"\n cp $znn_library \"$OUTPUT_DIRECTORY\"\ndone\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 2b6fa26c..1c1b0f78 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ NSApplication.TerminateReply { print("applicationShouldTerminate") diff --git a/pubspec.lock b/pubspec.lock index ebc6c0d8..d4720f10 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -26,10 +26,10 @@ packages: dependency: "direct main" description: name: ai_barcode_scanner - sha256: b6bac0dbaa0458cda27fa03d0b051b3cdf76ae11149ab49c4e0a5132bc84cddc + sha256: beecc9b97d136e82318804a14bd2866fc6fdb26ac05979d23d46a3b3cf6659e9 url: "https://pub.dev" source: hosted - version: "5.2.2" + version: "6.0.1" analyzer: dependency: transitive description: @@ -90,10 +90,10 @@ packages: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.6.0" async: dependency: transitive description: @@ -150,6 +150,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + bloc: + dependency: "direct main" + description: + name: bloc + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" + url: "https://pub.dev" + source: hosted + version: "8.1.4" + bloc_test: + dependency: "direct dev" + description: + name: bloc_test + sha256: "165a6ec950d9252ebe36dc5335f2e6eb13055f33d56db0eeb7642768849b43d2" + url: "https://pub.dev" + source: hosted + version: "9.1.7" boolean_selector: dependency: transitive description: @@ -282,10 +298,10 @@ packages: dependency: transitive description: name: code_builder - sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" url: "https://pub.dev" source: hosted - version: "4.10.0" + version: "4.10.1" collection: dependency: "direct main" description: @@ -298,10 +314,18 @@ packages: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "88b0fddbe4c92910fefc09cc0248f5e7f0cd23e450ded4c28f16ab8ee8f83268" + url: "https://pub.dev" + source: hosted + version: "1.10.0" cross_file: dependency: transitive description: @@ -314,10 +338,10 @@ packages: dependency: transitive description: name: crypto - sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" cryptography: dependency: transitive description: @@ -362,10 +386,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + sha256: c4af09051b4f0508f6c1dc0a5c085bf014d5c9a4a0678ce1799c2b4d716387a0 url: "https://pub.dev" source: hosted - version: "10.1.2" + version: "11.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -374,6 +398,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + diff_match_patch: + dependency: transitive + description: + name: diff_match_patch + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" + source: hosted + version: "0.4.1" dotted_border: dependency: "direct main" description: @@ -407,7 +439,7 @@ packages: source: hosted version: "1.0.2" equatable: - dependency: transitive + dependency: "direct main" description: name: equatable sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 @@ -430,6 +462,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" ffi: dependency: "direct main" description: @@ -442,10 +482,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_selector: dependency: "direct main" description: @@ -458,18 +498,18 @@ packages: dependency: transitive description: name: file_selector_android - sha256: b8c9717a0177ca6fa035554b82cd6c83b838ddc66b7704eb6df0f77f027ecc90 + sha256: ec439df07c4999faad319ce8ad9e971795c2f1d7132ad5a793b9370a863c6128 url: "https://pub.dev" source: hosted - version: "0.5.1+7" + version: "0.5.1+10" file_selector_ios: dependency: transitive description: name: file_selector_ios - sha256: "38ebf91ecbcfa89a9639a0854ccaed8ab370c75678938eebca7d34184296f0bb" + sha256: "94b98ad950b8d40d96fee8fa88640c2e4bd8afcdd4817993bd04e20310f45420" url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.3+1" file_selector_linux: dependency: transitive description: @@ -482,10 +522,10 @@ packages: dependency: transitive description: name: file_selector_macos - sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" url: "https://pub.dev" source: hosted - version: "0.9.4+1" + version: "0.9.4+2" file_selector_platform_interface: dependency: transitive description: @@ -514,10 +554,10 @@ packages: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" fl_chart: dependency: "direct main" description: @@ -539,6 +579,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a + url: "https://pub.dev" + source: hosted + version: "8.1.6" flutter_flip_card: dependency: "direct main" description: @@ -547,22 +595,19 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.6" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" - source: hosted - version: "5.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" + sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.23" flutter_staggered_grid_view: dependency: "direct main" description: @@ -579,6 +624,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.10+1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" flutter_vector_icons: dependency: "direct main" description: @@ -696,14 +746,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + hydrated_bloc: + dependency: "direct main" + description: + name: hydrated_bloc + sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c + url: "https://pub.dev" + source: hosted + version: "9.1.5" image: dependency: "direct main" description: name: image - sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.3.0" image_picker: dependency: transitive description: @@ -716,26 +774,26 @@ packages: dependency: transitive description: name: image_picker_android - sha256: c0a6763d50b354793d0192afd0a12560b823147d3ded7c6b77daf658fa05cc85 + sha256: "8faba09ba361d4b246dc0a17cb4289b3324c2b9f6db7b3d457ee69106a86bd32" url: "https://pub.dev" source: hosted - version: "0.8.12+13" + version: "0.8.12+17" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" + sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b" url: "https://pub.dev" source: hosted - version: "0.8.12" + version: "0.8.12+1" image_picker_linux: dependency: transitive description: @@ -801,7 +859,7 @@ packages: source: hosted version: "0.6.7" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" @@ -812,10 +870,18 @@ packages: dependency: "direct main" description: name: json_rpc_2 - sha256: "5e469bffa23899edacb7b22787780068d650b106a21c76db3c49218ab7ca447e" + sha256: "246b321532f0e8e2ba474b4d757eaa558ae4fdd0688fdbc1e1ca9705f9b8ca0e" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b + url: "https://pub.dev" + source: hosted + version: "6.8.0" launch_at_startup: dependency: "direct main" description: @@ -832,14 +898,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" - lints: + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: dependency: transitive description: - name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" local_notifier: dependency: "direct main" description: @@ -860,18 +942,18 @@ packages: dependency: "direct main" description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" lottie: dependency: "direct main" description: name: lottie - sha256: "6a24ade5d3d918c306bb1c21a6b9a04aab0489d51a2582522eea820b4093b62b" + sha256: "7afc60865a2429d994144f7d66ced2ae4305fe35d82890b8766e3359872d872c" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" macros: dependency: transitive description: @@ -924,18 +1006,26 @@ packages: dependency: transitive description: name: mime - sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "2.0.0" mobile_scanner: dependency: transitive description: name: mobile_scanner - sha256: d234581c090526676fd8fab4ada92f35c6746e3fb4f05a399665d75a399fb760 + sha256: "728828a798d1a2ee506beb652ca23d974c542c96ed03dcbd5eaf97bef96cdaad" + url: "https://pub.dev" + source: hosted + version: "6.0.2" + mocktail: + dependency: "direct dev" + description: + name: mocktail + sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" url: "https://pub.dev" source: hosted - version: "5.2.3" + version: "1.0.4" mutex: dependency: "direct main" description: @@ -952,6 +1042,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" number_selector: dependency: "direct main" description: @@ -988,10 +1086,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 + sha256: df3eb3e0aed5c1107bb0fdb80a8e82e778114958b1c5ac5644fb1ac9cae8a998 url: "https://pub.dev" source: hosted - version: "8.0.2" + version: "8.1.0" package_info_plus_platform_interface: dependency: transitive description: @@ -1028,10 +1126,10 @@ packages: dependency: transitive description: name: path_parsing - sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + sha256: "45f7d6bba1128761de5540f39d5ca000ea8a1f22f06b76b61094a60a2997bd0e" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" path_provider: dependency: "direct main" description: @@ -1044,10 +1142,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.12" path_provider_foundation: dependency: transitive description: @@ -1092,10 +1190,10 @@ packages: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -1228,10 +1326,42 @@ packages: dependency: transitive description: name: screen_retriever - sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" + sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" url: "https://pub.dev" source: hosted - version: "0.1.9" + version: "0.2.0" + screen_retriever_linux: + dependency: transitive + description: + name: screen_retriever_linux + sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_macos: + dependency: transitive + description: + name: screen_retriever_macos + sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_platform_interface: + dependency: transitive + description: + name: screen_retriever_platform_interface + sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + screen_retriever_windows: + dependency: transitive + description: + name: screen_retriever_windows + sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" + url: "https://pub.dev" + source: hosted + version: "0.2.0" sec: dependency: transitive description: @@ -1252,18 +1382,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "468c43f285207c84bcabf5737f33b914ceb8eb38398b91e5e3ad1698d1b72a52" + sha256: "3af2cda1752e5c24f2fc04b6083b40f013ffe84fb90472f30c6499a9213d5442" url: "https://pub.dev" source: hosted - version: "10.0.2" + version: "10.1.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "6ababf341050edff57da8b6990f11f4e99eaba837865e2e6defe16d039619db5" + sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48 url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.0.1" shared_preferences: dependency: transitive description: @@ -1276,18 +1406,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.3" shared_preferences_linux: dependency: transitive description: @@ -1328,6 +1458,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -1381,6 +1527,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" source_span: dependency: transitive description: @@ -1393,10 +1555,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.1" stacked: dependency: "direct main" description: @@ -1433,10 +1595,18 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -1445,14 +1615,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e" + url: "https://pub.dev" + source: hosted + version: "1.25.7" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.2" + test_core: + dependency: transitive + description: + name: test_core + sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696" + url: "https://pub.dev" + source: hosted + version: "0.6.4" timing: dependency: transitive description: @@ -1473,10 +1659,10 @@ packages: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" universal_io: dependency: transitive description: @@ -1489,18 +1675,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab + sha256: "0dea215895a4d254401730ca0ba8204b29109a34a99fb06ae559a2b60988d2de" url: "https://pub.dev" source: hosted - version: "6.3.10" + version: "6.3.13" url_launcher_ios: dependency: transitive description: @@ -1545,10 +1731,10 @@ packages: dependency: transitive description: name: url_launcher_windows - sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" uuid: dependency: transitive description: @@ -1605,6 +1791,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + very_good_analysis: + dependency: "direct dev" + description: + name: very_good_analysis + sha256: "1fb637c0022034b1f19ea2acb42a3603cbd8314a470646a59a2fb01f5f3a8629" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" wakelock_plus: dependency: "direct main" description: @@ -1677,14 +1879,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" - win32: + webkit_inspection_protocol: dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + win32: + dependency: "direct main" description: name: win32 - sha256: "4d45dc9069dba4619dc0ebd93c7cec5e66d8482cb625a370ac806dcc8165f2ec" + sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69" url: "https://pub.dev" source: hosted - version: "5.5.5" + version: "5.9.0" win32_registry: dependency: transitive description: @@ -1697,10 +1907,10 @@ packages: dependency: "direct main" description: name: window_manager - sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792 + sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.4.3" x25519: dependency: transitive description: @@ -1713,10 +1923,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: @@ -1737,20 +1947,20 @@ packages: dependency: "direct main" description: path: "." - ref: "v0.0.5" - resolved-ref: "9c6b251f4be5ab05447f17f63acd56f7a9ff040b" + ref: "v0.0.6" + resolved-ref: "17f2503dd91d2a3705f598e6beb25ed7a8eb8e4f" url: "https://github.com/zenon-network/znn_ledger_dart.git" source: git - version: "0.0.5" + version: "0.0.6" znn_sdk_dart: dependency: "direct main" description: path: "." - ref: "v0.0.7" - resolved-ref: "8511f17a0dfa721e8f0ec2e0b0aae409f509e102" + ref: "v0.0.8" + resolved-ref: "32e4b0cbd7dc57e4e98e3dbdb9728a8b787494b8" url: "https://github.com/zenon-network/znn_sdk_dart.git" source: git - version: "0.0.7" + version: "0.0.8" zxing2: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 01ca4323..5b107d76 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,8 @@ environment: dependencies: flutter: sdk: flutter - + flutter_localizations: + sdk: flutter fl_chart: ^0.69.0 overlay_support: ^2.1.0 lottie: ^3.1.2 @@ -29,9 +30,9 @@ dependencies: hive: ^2.0.5 url_launcher: ^6.1.12 provider: ^6.0.2 - intl: ^0.19.0 + intl: any package_info_plus: ^8.0.2 - device_info_plus: ^10.1.2 + device_info_plus: ^11.1.0 infinite_scroll_pagination: ^4.0.0 share_plus: ^10.0.2 page_transition: ^2.0.4 @@ -44,11 +45,11 @@ dependencies: znn_sdk_dart: git: url: https://github.com/zenon-network/znn_sdk_dart.git - ref: v0.0.7 + ref: v0.0.8 znn_ledger_dart: git: url: https://github.com/zenon-network/znn_ledger_dart.git - ref: v0.0.5 + ref: v0.0.6 json_rpc_2: ^3.0.2 path: ^1.8.2 ffi: ^2.1.0 @@ -69,18 +70,31 @@ dependencies: clipboard_watcher: ^0.2.0 wallet_connect_uri_validator: ^0.1.0 big_decimal: ^0.5.0 - ai_barcode_scanner: ^5.2.1 + ai_barcode_scanner: ^6.0.1 version: ^3.0.0 mutex: ^3.1.0 retry: ^3.1.2 + flutter_bloc: ^8.1.6 + bloc: ^8.1.4 + equatable: ^2.0.5 + hydrated_bloc: ^9.1.5 + json_annotation: ^4.9.0 + win32: ^5.9.0 dev_dependencies: build_runner: ^2.4.6 hive_generator: ^2.0.0 - flutter_lints: ^5.0.0 dependency_validator: ^4.1.1 + mocktail: ^1.0.4 + bloc_test: ^9.0.0 + flutter_test: + sdk: flutter + very_good_analysis: ^6.0.0 + json_serializable: ^6.8.0 + flutter: + generate: true uses-material-design: true assets: diff --git a/run_configurations/dev.run.xml b/run_configurations/dev.run.xml new file mode 100644 index 00000000..83c0f623 --- /dev/null +++ b/run_configurations/dev.run.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/test/balance/cubit/balance_cubit_test.dart b/test/balance/cubit/balance_cubit_test.dart new file mode 100644 index 00000000..6a488223 --- /dev/null +++ b/test/balance/cubit/balance_cubit_test.dart @@ -0,0 +1,183 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockLedger extends Mock implements LedgerApi {} + +class FakeAddress extends Fake implements Address {} + + +void main() { + initHydratedStorage(); + + setUpAll(() { + registerFallbackValue(FakeAddress()); + }); + + group('BalanceCubit', () { + late MockZenon mockZenon; + late MockLedger mockLedger; + late MockWsClient mockWsClient; + late BalanceCubit balanceCubit; + late AccountInfo accountInfo; + late BalanceInfoListItem balanceInfoListItem; + late NoBalanceException balanceException; + + setUp(() async { + mockZenon = MockZenon(); + mockLedger = MockLedger(); + mockWsClient = MockWsClient(); + + balanceInfoListItem = BalanceInfoListItem( + token: kZnnCoin, + balance: BigInt.from(5), + ); + + accountInfo = AccountInfo( + address: emptyAddress.toString(), + blockCount: 1, + balanceInfoList: [balanceInfoListItem], + ); + + balanceCubit = BalanceCubit( + address: emptyAddress, + zenon: mockZenon, + ); + balanceException = NoBalanceException(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.ledger).thenReturn(mockLedger); + + when(() => mockLedger.getAccountInfoByAddress(any()), + ).thenAnswer((_) async => accountInfo); + + }); + + test('initial status is correct', () { + final BalanceCubit balanceCubit = BalanceCubit( + address: emptyAddress, + zenon: mockZenon, + ); + expect(balanceCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final BalanceState initialState = BalanceState(); + + final Map? serialized = balanceCubit.toJson( + initialState, + ); + final BalanceState? deserialized = balanceCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final BalanceState loadingState = BalanceState( + status: TimerStatus.loading, + ); + + final Map? serialized = balanceCubit.toJson( + loadingState, + ); + final BalanceState? deserialized = balanceCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final BalanceState balanceState = BalanceState( + data: accountInfo, + status: TimerStatus.success, + ); + + final Map? serialized = balanceCubit.toJson( + balanceState, + ); + final BalanceState? deserialized = balanceCubit.fromJson( + serialized!, + ); + + expect(deserialized, balanceState); + }); + + + test('can (de)serialize failure state', () { + final BalanceState failureState = BalanceState( + status: TimerStatus.failure, + error: balanceException, + ); + + final Map? serialized = balanceCubit.toJson( + failureState, + ); + final BalanceState? deserialized = balanceCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + + group('fetchDataPeriodically', () { + blocTest( + 'calls getAccountInfoByAddress once', + build: () => balanceCubit, + setUp: () { + when(() => mockLedger.getAccountInfoByAddress(any()), + ).thenAnswer((_) async => accountInfo); + }, + act: (BalanceCubit cubit) => cubit.fetch(), + verify: (_) { + verify(() => + mockLedger.getAccountInfoByAddress(any()), + ).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when fetch throws', + build: () => balanceCubit, + setUp: () { + when(() => mockLedger.getAccountInfoByAddress(any()), + ).thenThrow(balanceException); + }, + act: (BalanceCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + BalanceState(status: TimerStatus.loading), + BalanceState( + status: TimerStatus.failure, + error: balanceException, + ), + ], + ); + + blocTest( + 'emits [loading, success] when fetch returns', + build: () => balanceCubit, + act: (BalanceCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + BalanceState(status: TimerStatus.loading), + BalanceState(status: TimerStatus.success, + data: accountInfo, + ), + ], + ); + }); + }); +} diff --git a/test/delegation/cubit/delegation_cubit_test.dart b/test/delegation/cubit/delegation_cubit_test.dart new file mode 100644 index 00000000..956837c8 --- /dev/null +++ b/test/delegation/cubit/delegation_cubit_test.dart @@ -0,0 +1,171 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockEmbedded extends Mock implements EmbeddedApi {} + +class MockPillar extends Mock implements PillarApi {} + +class MockDelegationInfo extends Mock implements DelegationInfo {} + +class FakeAddress extends Fake implements Address {} + +void main() { + initHydratedStorage(); + + setUpAll(() { + registerFallbackValue(FakeAddress()); + }); + + group('DelegationCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late DelegationCubit delegationCubit; + late MockEmbedded mockEmbedded; + late MockPillar mockPillar; + final DelegationInfo delegationInfo = DelegationInfo.fromJson( + {'name': 'Test-Name', 'status': 1, 'weight': '1000'}, + ); + late NoDelegationStatsException delegationException; + + setUp(() async { + mockZenon = MockZenon(); + mockWsClient = MockWsClient(); + mockEmbedded = MockEmbedded(); + mockPillar = MockPillar(); + delegationException = NoDelegationStatsException(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.embedded).thenReturn(mockEmbedded); + when(() => mockEmbedded.pillar).thenReturn(mockPillar); + when(() => mockPillar.getDelegatedPillar(any())) + .thenAnswer((_) async => delegationInfo); + + delegationCubit = DelegationCubit( + address: emptyAddress, + zenon: mockZenon, + ); + }); + + test('initial status is correct', () { + expect(delegationCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final DelegationState initialState = DelegationState(); + + final Map? serialized = delegationCubit.toJson( + initialState, + ); + final DelegationState? deserialized = delegationCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final DelegationState loadingState = DelegationState( + status: TimerStatus.loading, + ); + + final Map? serialized = delegationCubit.toJson( + loadingState, + ); + final DelegationState? deserialized = delegationCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final DelegationState successState = DelegationState( + status: TimerStatus.success, + data: delegationInfo, + ); + + final Map? serialized = delegationCubit.toJson( + successState, + ); + final DelegationState? deserialized = delegationCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final DelegationState failureState = DelegationState( + status: TimerStatus.failure, + error: delegationException, + ); + + final Map? serialized = delegationCubit.toJson( + failureState, + ); + final DelegationState? deserialized = delegationCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + + group('fetchDataPeriodically', () { + blocTest( + 'calls getDelegatedPillar once', + build: () => delegationCubit, + act: (DelegationCubit cubit) => cubit.fetchDataPeriodically(), + verify: (_) { + verify( + () => mockZenon.embedded.pillar.getDelegatedPillar( + emptyAddress, + ), + ).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when getDelegatedPillar throws', + setUp: () { + when( + () => mockPillar.getDelegatedPillar( + any(), + ), + ).thenThrow(delegationException); + }, + build: () => delegationCubit, + act: (DelegationCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + DelegationState(status: TimerStatus.loading), + DelegationState( + status: TimerStatus.failure, + error: delegationException, + ), + ], + ); + + blocTest( + 'emits [loading, success] when getDelegatedPillar ' + 'returns a DelegationInfo instance', + build: () => delegationCubit, + act: (DelegationCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + DelegationState(status: TimerStatus.loading), + DelegationState(status: TimerStatus.success, data: delegationInfo), + ], + ); + }); + }); +} diff --git a/test/dual_coin_stats/cubit/dual_coin_stats_cubit_test.dart b/test/dual_coin_stats/cubit/dual_coin_stats_cubit_test.dart new file mode 100644 index 00000000..988bf575 --- /dev/null +++ b/test/dual_coin_stats/cubit/dual_coin_stats_cubit_test.dart @@ -0,0 +1,171 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/cubits/timer_cubit.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockEmbedded extends Mock implements EmbeddedApi {} + +class MockTokenApi extends Mock implements TokenApi {} + + +class FakeTokenStandard extends Fake implements TokenStandard {} + +void main() { + initHydratedStorage(); + + setUpAll(() { + registerFallbackValue(FakeTokenStandard()); + }); + + group('DualCoinStatsCubit', () { + late MockZenon mockZenon; + late MockEmbedded mockEmbedded; + late MockWsClient mockWsClient; + late MockTokenApi mockTokenApi; + late DualCoinStatsCubit dualCoinStatsCubit; + late CubitFailureException exception; + + setUp(() async { + mockZenon = MockZenon(); + mockEmbedded = MockEmbedded(); + mockTokenApi = MockTokenApi(); + mockWsClient = MockWsClient(); + exception = CubitFailureException(); + dualCoinStatsCubit = DualCoinStatsCubit( + zenon: mockZenon, + ); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.embedded).thenReturn(mockEmbedded); + when(() => mockEmbedded.token).thenReturn(mockTokenApi); + + + when(() => mockTokenApi.getByZts(znnZts)) + .thenAnswer((_) async => kZnnCoin); + when(() => mockTokenApi.getByZts(qsrZts)) + .thenAnswer((_) async => kQsrCoin); + }); + + test('initial status is correct', () { + final DualCoinStatsCubit dualCoinStatsCubit = DualCoinStatsCubit( + zenon: mockZenon, + ); + expect(dualCoinStatsCubit.state.status, TimerStatus.initial); + }); + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final DualCoinStatsState initialState = DualCoinStatsState(); + + final Map? serialized = dualCoinStatsCubit.toJson( + initialState, + ); + final DualCoinStatsState? deserialized = dualCoinStatsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final DualCoinStatsState loadingState = DualCoinStatsState( + status: TimerStatus.loading, + ); + + final Map? serialized = dualCoinStatsCubit.toJson( + loadingState, + ); + final DualCoinStatsState? deserialized = dualCoinStatsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final DualCoinStatsState dualCoinStatsState = DualCoinStatsState( + data: [kZnnCoin, kQsrCoin], + status: TimerStatus.success, + ); + + final Map? serialized =dualCoinStatsCubit.toJson( + dualCoinStatsState, + ); + final DualCoinStatsState? deserialized = dualCoinStatsCubit.fromJson( + serialized!, + ); + expect(deserialized, dualCoinStatsState); + }); + + test('can (de)serialize failure state', () { + final DualCoinStatsState failureState = DualCoinStatsState( + status: TimerStatus.failure, + error: exception, + ); + + final Map? serialized = dualCoinStatsCubit.toJson( + failureState, + ); + final DualCoinStatsState? deserialized = dualCoinStatsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + + blocTest( + 'calls getByZts for each address in token once', + build: () => dualCoinStatsCubit, + setUp: () { + + }, + act: (DualCoinStatsCubit cubit) => cubit.fetch(), + verify: (_) { + verify(() => mockTokenApi.getByZts(znnZts)).called(1); + verify(() => mockTokenApi.getByZts(qsrZts)).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when getByZts throws', + setUp: () { + when( + () => mockTokenApi.getByZts(any()), + ).thenThrow(exception); + }, + build: () => dualCoinStatsCubit, + act: (DualCoinStatsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + DualCoinStatsState(status: TimerStatus.loading), + DualCoinStatsState( + status: TimerStatus.failure, + error: exception, + ), + ], + ); + + blocTest( + 'emits [loading, success] when getByZts returns', + build: () => dualCoinStatsCubit, + act: (DualCoinStatsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + DualCoinStatsState(status: TimerStatus.loading), + DualCoinStatsState( + status: TimerStatus.success, + data: [kZnnCoin, kQsrCoin], + ), + ], + ); + }); +} diff --git a/test/helpers/hydrated_bloc.dart b/test/helpers/hydrated_bloc.dart new file mode 100644 index 00000000..d132d6c2 --- /dev/null +++ b/test/helpers/hydrated_bloc.dart @@ -0,0 +1,16 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:mocktail/mocktail.dart'; + +class MockStorage extends Mock implements Storage {} + +late Storage hydratedStorage; + +void initHydratedStorage() { + TestWidgetsFlutterBinding.ensureInitialized(); + hydratedStorage = MockStorage(); + when( + () => hydratedStorage.write(any(), any()), + ).thenAnswer((_) async {}); + HydratedBloc.storage = hydratedStorage; +} diff --git a/test/node_sync_status/cubit/node_sync_status_cubit_test.dart b/test/node_sync_status/cubit/node_sync_status_cubit_test.dart new file mode 100644 index 00000000..471d8894 --- /dev/null +++ b/test/node_sync_status/cubit/node_sync_status_cubit_test.dart @@ -0,0 +1,161 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/blocs/auto_receive_tx_worker.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/cubit_failure_exception.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockStatsApi extends Mock implements StatsApi {} + +class MockAutoReceiveTxWorker extends Mock implements AutoReceiveTxWorker {} + +void main() { + initHydratedStorage(); + + group('NodeSyncStatusCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late MockStatsApi mockStatsApi; + late NodeSyncStatusCubit nodeSyncStatusCubit; + late CubitFailureException exception; + late SyncInfo syncInfo; + late Pair syncPair; + + setUp(() async { + mockZenon = MockZenon(); + mockWsClient = MockWsClient(); + mockStatsApi = MockStatsApi(); + exception = CubitFailureException(); + nodeSyncStatusCubit = NodeSyncStatusCubit( + zenon: mockZenon, + ); + + syncInfo = SyncInfo.fromJson({ + 'state': 2, + 'currentHeight': 100, + 'targetHeight': 120, + }); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockWsClient.status()).thenReturn(WebsocketStatus.running); + + + when(() => mockZenon.stats).thenReturn(mockStatsApi); + when(() => mockStatsApi.syncInfo()).thenAnswer((_) async => syncInfo); + + syncPair = Pair(SyncState.syncDone, syncInfo); + }); + + test('initial status is correct', () { + expect(nodeSyncStatusCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final NodeSyncStatusState initialState = NodeSyncStatusState(); + + final Map? serialized = nodeSyncStatusCubit.toJson( + initialState, + ); + final NodeSyncStatusState? deserialized = nodeSyncStatusCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final NodeSyncStatusState loadingState = NodeSyncStatusState( + status: TimerStatus.loading, + ); + + final Map? serialized = nodeSyncStatusCubit.toJson( + loadingState, + ); + final NodeSyncStatusState? deserialized = nodeSyncStatusCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final NodeSyncStatusState successState = NodeSyncStatusState( + status: TimerStatus.success, + data: syncPair, + ); + + final Map? serialized = nodeSyncStatusCubit.toJson( + successState, + ); + final NodeSyncStatusState? deserialized = nodeSyncStatusCubit.fromJson( + serialized!, + ); + + expect(deserialized, isA()); + expect(deserialized!.status, equals(TimerStatus.success)); + expect(deserialized.data, isA>()); + expect(deserialized.data!.first, equals(SyncState.syncDone)); + expect(deserialized.data!.second, isA()); + }); + + test('can (de)serialize failure state', () { + final NodeSyncStatusState failureState = NodeSyncStatusState( + status: TimerStatus.failure, + error: exception, + ); + + final Map? serialized = nodeSyncStatusCubit.toJson( + failureState, + ); + final NodeSyncStatusState? deserialized = nodeSyncStatusCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetch', () { + blocTest( + 'emits [loading, success] when websocket is running and ' + 'fetch returns syncInfo', + build: () => nodeSyncStatusCubit, + act: (NodeSyncStatusCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ // Expected state changes + NodeSyncStatusState(status: TimerStatus.loading), + NodeSyncStatusState( + status: TimerStatus.success, + data: syncPair, + ), + ], + ); + + + blocTest( + 'emits [loading, failure] when fetch throws an error', + setUp: () { + when(() => mockStatsApi.syncInfo()).thenThrow(exception); + }, + build: () => nodeSyncStatusCubit, + act: (NodeSyncStatusCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + NodeSyncStatusState(status: TimerStatus.loading), + NodeSyncStatusState( + status: TimerStatus.failure, + error: exception, + ), + ], + ); + }); + }); +} diff --git a/test/pillars/cubit/pillars_cubit_test.dart b/test/pillars/cubit/pillars_cubit_test.dart new file mode 100644 index 00000000..0b32c468 --- /dev/null +++ b/test/pillars/cubit/pillars_cubit_test.dart @@ -0,0 +1,152 @@ +// ignore_for_file: prefer_const_constructors +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/cubit_failure_exception.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockEmbedded extends Mock implements EmbeddedApi {} + +class MockPillar extends Mock implements PillarApi {} + +class MockPillarInfoList extends Mock implements PillarInfoList {} + +class MockPillarInfo extends Mock implements PillarInfo {} + +void main() { + initHydratedStorage(); + + group('PillarsCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late MockEmbedded mockEmbedded; + late MockPillar mockPillar; + late PillarsCubit pillarsCubit; + late CubitFailureException exception; + + setUp(() async { + mockZenon = MockZenon(); + mockWsClient = MockWsClient(); + mockEmbedded = MockEmbedded(); + mockPillar = MockPillar(); + pillarsCubit = PillarsCubit( + zenon: mockZenon, + ); + exception = CubitFailureException(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.embedded).thenReturn(mockEmbedded); + when(() => mockEmbedded.pillar).thenReturn(mockPillar); + }); + + test('initial status is correct', () { + final PillarsCubit pillarsCubit = PillarsCubit( + zenon: mockZenon, + ); + expect(pillarsCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final PillarsState initialState = PillarsState(); + + final Map? serialized = pillarsCubit.toJson( + initialState, + ); + final PillarsState? deserialized = pillarsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final PillarsState loadingState = PillarsState( + status: TimerStatus.loading, + ); + + final Map? serialized = pillarsCubit.toJson( + loadingState, + ); + final PillarsState? deserialized = pillarsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final PillarsState successState = PillarsState( + status: TimerStatus.success, + data: 100, + ); + + final Map? serialized = pillarsCubit.toJson( + successState, + ); + final PillarsState? deserialized = pillarsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final PillarsState failureState = PillarsState( + status: TimerStatus.failure, + error: exception, + ); + + final Map? serialized = pillarsCubit.toJson( + failureState, + ); + final PillarsState? deserialized = pillarsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetch', () { + blocTest( + 'emits [loading, success] when fetch is successful', + build: () => pillarsCubit, + setUp: () { + final MockPillarInfoList mockPillarInfoList = MockPillarInfoList(); + final MockPillarInfo mockPillarInfo = MockPillarInfo(); + when(() => mockPillar.getAll()) + .thenAnswer((_) async => mockPillarInfoList); + when(() => mockPillarInfoList.list) + .thenReturn(List.filled(100, mockPillarInfo)); + }, + act: (PillarsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + PillarsState(status: TimerStatus.loading), + PillarsState(status: TimerStatus.success, data: 100), + ], + verify: (_) { + verify(() => mockPillar.getAll()).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when getAll() throws', + setUp: () { + when(() => mockPillar.getAll()).thenThrow(exception); + }, + build: () => pillarsCubit, + act: (PillarsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + PillarsState(status: TimerStatus.loading), + PillarsState(status: TimerStatus.failure, error: exception), + ], + ); + }); + }); +} diff --git a/test/realtime_statistics/cubit/realtime_statistics_cubit_test.dart b/test/realtime_statistics/cubit/realtime_statistics_cubit_test.dart new file mode 100644 index 00000000..b7f130fe --- /dev/null +++ b/test/realtime_statistics/cubit/realtime_statistics_cubit_test.dart @@ -0,0 +1,226 @@ +// ignore_for_file: prefer_const_constructors +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/utils.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockLedger extends Mock implements LedgerApi {} + +class FakeAddress extends Fake implements Address {} + +class MockAccountBlock extends Mock implements AccountBlock {} + +class MockMomentum extends Mock implements Momentum {} + +class MockAccountBlockList extends Mock implements AccountBlockList {} + + +void main() { + initHydratedStorage(); + + setUpAll(() { + registerFallbackValue(FakeAddress()); + }); + + group('RealtimeStatisticsCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late MockLedger mockLedger; + late RealtimeStatisticsCubit statsCubit; + late SyriusException statsException; + late MockMomentum mockMomentum; + late AccountBlock accountBlock; + + setUp(() async { + final Map confirmationDetailJson = { + 'numConfirmations': 42, + 'momentumHeight': 12345, + 'momentumHash': emptyHash.toString(), + 'momentumTimestamp': 1625132800, + }; + + final Map accountBlockJson = { + 'descendantBlocks': [], + 'basePlasma': 1000, + 'usedPlasma': 500, + 'changesHash': emptyHash.toString(), + 'confirmationDetail': confirmationDetailJson, + 'version': 1, + 'chainIdentifier': 1, + 'blockType': 2, + 'hash': emptyHash.toString(), + 'previousHash': emptyHash.toString(), + 'height': 100, + 'momentumAcknowledged': { + 'hash': emptyHash.toString(), + 'height': 99, + }, + 'address': emptyAddress.toString(), + 'toAddress': emptyAddress.toString(), + 'amount': '1000000000', + 'tokenStandard': znnTokenStandard, + 'fromBlockHash': emptyHash.toString(), + 'data': null, + 'fusedPlasma': 0, + 'difficulty': 0, + 'nonce': '1', + 'publicKey': null, + 'signature': null, + 'token': kZnnCoin.toJson(), + 'pairedAccountBlock': null, + }; + + accountBlock = AccountBlock.fromJson(accountBlockJson); + + final AccountBlockList accountBlockList = AccountBlockList( + count: 1, + list: [accountBlock], + more: false, + ); + + + mockZenon = MockZenon(); + mockLedger = MockLedger(); + mockWsClient = MockWsClient(); + statsCubit = RealtimeStatisticsCubit( + address: emptyAddress, + zenon: mockZenon, + ); + statsException = NoBlocksAvailableException(); + mockMomentum = MockMomentum(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.ledger).thenReturn(mockLedger); + when(() => mockLedger.getFrontierMomentum()) + .thenAnswer((_) async => mockMomentum); + when(() => mockMomentum.height) + .thenReturn(kMomentumsPerWeek + 100); + when(() => mockLedger.getAccountBlocksByPage(any(), + pageIndex: any(named: 'pageIndex'), + pageSize: any(named: 'pageSize'), + ), + ).thenAnswer((_) async => accountBlockList); + }); + + test('initial status is correct', () { + expect(statsCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final RealtimeStatisticsState initialState = RealtimeStatisticsState(); + + final Map? serialized = statsCubit.toJson( + initialState, + ); + final RealtimeStatisticsState? deserialized = statsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final RealtimeStatisticsState loadingState = RealtimeStatisticsState( + status: TimerStatus.loading, + ); + + final Map? serialized = statsCubit.toJson( + loadingState, + ); + final RealtimeStatisticsState? deserialized = statsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final RealtimeStatisticsState successState = RealtimeStatisticsState( + status: TimerStatus.success, + data: [accountBlock], + ); + + final Map? serialized = statsCubit.toJson( + successState, + ); + final RealtimeStatisticsState? deserialized = statsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final RealtimeStatisticsState failureState = RealtimeStatisticsState( + status: TimerStatus.failure, + error: statsException, + ); + + final Map? serialized = statsCubit.toJson( + failureState, + ); + final RealtimeStatisticsState? deserialized = statsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetch', () { + blocTest( + 'calls getFrontierMomentum and getAccountBlocksByPage once', + build: () => statsCubit, + act: (RealtimeStatisticsCubit cubit) => cubit.fetch(), + verify: (_) { + verify(() => mockLedger.getFrontierMomentum()).called(1); + verify(() => mockLedger.getAccountBlocksByPage( + any(), + pageIndex: any(named: 'pageIndex'), + pageSize: any(named: 'pageSize'), + ), + ).called(1); + }, + ); + + blocTest( + 'emits [loading, success] when fetch returns', + build: () => statsCubit, + act: (RealtimeStatisticsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + RealtimeStatisticsState(status: TimerStatus.loading), + RealtimeStatisticsState( + status: TimerStatus.success, + data: [accountBlock], + ), + ], + ); + + blocTest( + 'emits [loading, failure] when fetch throws an error', + setUp: () { + when(() => mockLedger.getFrontierMomentum()) + .thenThrow(statsException); + }, + build: () => statsCubit, + act: (RealtimeStatisticsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + RealtimeStatisticsState(status: TimerStatus.loading), + RealtimeStatisticsState( + status: TimerStatus.failure, + error: statsException, + ), + ], + ); + }); + }); +} diff --git a/test/sentinels/cubit/sentinels_cubit_test.dart b/test/sentinels/cubit/sentinels_cubit_test.dart new file mode 100644 index 00000000..bf08132d --- /dev/null +++ b/test/sentinels/cubit/sentinels_cubit_test.dart @@ -0,0 +1,178 @@ +// ignore_for_file: prefer_const_constructors +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockSentinel extends Mock implements SentinelApi {} + +class MockEmbedded extends Mock implements EmbeddedApi {} + +class MockSentinelInfoList extends Mock implements SentinelInfoList {} + +void main() { + initHydratedStorage(); + + group('SentinelsCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late MockEmbedded mockEmbedded; + late MockSentinel mockSentinel; + late SentinelsCubit sentinelsCubit; + late CubitFailureException exception; + late SentinelInfo sentinelInfo; + late SentinelInfoList sentinelInfoList; + + setUp(() async { + mockZenon = MockZenon(); + mockWsClient = MockWsClient(); + mockEmbedded = MockEmbedded(); + mockSentinel = MockSentinel(); + sentinelInfo = SentinelInfo.fromJson( + { + 'owner': emptyAddress.toString(), + 'registrationTimestamp': 1625132800, + 'isRevocable': true, + 'revokeCooldown': 1000, + 'active': true, + }, + ); + sentinelInfoList = SentinelInfoList( + count: 1, + list: [sentinelInfo], + ); + sentinelsCubit = SentinelsCubit( + zenon: mockZenon, + ); + exception = CubitFailureException(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when( + () => mockZenon.embedded, + ).thenReturn(mockEmbedded); + when( + () => mockEmbedded.sentinel, + ).thenReturn(mockSentinel); + when( + () => mockSentinel.getAllActive(), + ).thenAnswer((_) async => sentinelInfoList); + }); + + test('initial status is correct', () { + final SentinelsCubit sentinelsCubit = SentinelsCubit( + zenon: mockZenon, + ); + expect(sentinelsCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final SentinelsState initialState = SentinelsState(); + + final Map? serialized = sentinelsCubit.toJson( + initialState, + ); + final SentinelsState? deserialized = sentinelsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final SentinelsState loadingState = SentinelsState( + status: TimerStatus.loading, + ); + + final Map? serialized = sentinelsCubit.toJson( + loadingState, + ); + final SentinelsState? deserialized = sentinelsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final SentinelsState successState = SentinelsState( + status: TimerStatus.success, + data: sentinelInfoList, + ); + + final Map? serialized = sentinelsCubit.toJson( + successState, + ); + final SentinelsState? deserialized = sentinelsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final SentinelsState failureState = SentinelsState( + status: TimerStatus.failure, + error: exception, + ); + + final Map? serialized = sentinelsCubit.toJson( + failureState, + ); + final SentinelsState? deserialized = sentinelsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetchDataPeriodically', () { + blocTest( + 'calls getAllActive() once', + build: () => sentinelsCubit, + act: (SentinelsCubit cubit) => cubit.fetchDataPeriodically(), + verify: (_) { + verify(() => mockZenon.embedded.sentinel.getAllActive()).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when getAllActive() throws', + setUp: () { + when( + () => mockSentinel.getAllActive(), + ).thenThrow(exception); + }, + build: () => sentinelsCubit, + act: (SentinelsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + SentinelsState(status: TimerStatus.loading), + SentinelsState( + status: TimerStatus.failure, + error: exception, + ), + ], + ); + + blocTest( + 'emits [loading, success] when getAllActive() returns successfully', + build: () => sentinelsCubit, + act: (SentinelsCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + SentinelsState(status: TimerStatus.loading), + SentinelsState( + status: TimerStatus.success, + data: sentinelInfoList, + ), + ], + ); + }); + }); +} diff --git a/test/staking/cubit/staking_cubit_test.dart b/test/staking/cubit/staking_cubit_test.dart new file mode 100644 index 00000000..9bfd0f54 --- /dev/null +++ b/test/staking/cubit/staking_cubit_test.dart @@ -0,0 +1,181 @@ +// ignore_for_file: prefer_const_constructors +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockEmbedded extends Mock implements EmbeddedApi {} + +class MockStake extends Mock implements StakeApi {} + +class FakeAddress extends Fake implements Address {} + +void main() { + initHydratedStorage(); + + setUpAll(() { + registerFallbackValue(FakeAddress()); + }); + + group('StakingCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late StakingCubit stakingCubit; + late MockEmbedded mockEmbedded; + late MockStake mockStake; + late SyriusException stakingException; + late StakeEntry stakeEntry; + late StakeList testStakeList; + + setUp(() async { + mockZenon = MockZenon(); + mockWsClient = MockWsClient(); + mockEmbedded = MockEmbedded(); + mockStake = MockStake(); + stakingCubit = StakingCubit( + address: emptyAddress, + zenon: mockZenon, + ); + stakeEntry = StakeEntry( + amount: BigInt.from(1), + weightedAmount: BigInt.from(1), + startTimestamp: 123, + expirationTimestamp: 321, + address: emptyAddress, + id: emptyHash, + ); + testStakeList = StakeList( + totalAmount: BigInt.from(1), + totalWeightedAmount: BigInt.from(1), + count: 1, + list: [stakeEntry], + ); + stakingException = NoActiveStakingEntriesException(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.embedded).thenReturn(mockEmbedded); + when(() => mockEmbedded.stake).thenReturn(mockStake); + when( + () => mockStake.getEntriesByAddress(any()), + ).thenAnswer((_) async => testStakeList); + }); + + test('initial status is correct', () { + expect(stakingCubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final StakingState initialState = StakingState(); + + final Map? serialized = stakingCubit.toJson( + initialState, + ); + final StakingState? deserialized = stakingCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final StakingState loadingState = StakingState( + status: TimerStatus.loading, + ); + + final Map? serialized = stakingCubit.toJson( + loadingState, + ); + final StakingState? deserialized = stakingCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final StakingState successState = StakingState( + status: TimerStatus.success, + data: testStakeList, + ); + + final Map? serialized = stakingCubit.toJson( + successState, + ); + final StakingState? deserialized = stakingCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final StakingState failureState = StakingState( + status: TimerStatus.failure, + error: stakingException, + ); + + final Map? serialized = stakingCubit.toJson( + failureState, + ); + final StakingState? deserialized = stakingCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetchDataPeriodically', () { + blocTest( + 'calls getEntriesByAddress() once', + build: () => stakingCubit, + act: (StakingCubit cubit) => cubit.fetchDataPeriodically(), + verify: (_) { + verify( + () => mockZenon.embedded.stake.getEntriesByAddress( + any(), + ), + ).called(1); + }, + ); + + blocTest( + 'emits [loading, failure] when getEntriesByAddress() throws', + setUp: () { + when( + () => mockStake.getEntriesByAddress(any()), + ).thenThrow(stakingException); + }, + build: () => stakingCubit, + act: (StakingCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + StakingState(status: TimerStatus.loading), + StakingState( + status: TimerStatus.failure, + error: stakingException, + ), + ], + ); + + blocTest( + 'emits [loading, success] when getAllActive() returns successfully', + build: () => stakingCubit, + act: (StakingCubit cubit) => cubit.fetchDataPeriodically(), + expect: () => [ + StakingState(status: TimerStatus.loading), + StakingState( + status: TimerStatus.success, + data: testStakeList, + ), + ], + ); + }); + }); +} diff --git a/test/total_hourly_transactions/cubit/total_hourly_transactions_cubit_test.dart b/test/total_hourly_transactions/cubit/total_hourly_transactions_cubit_test.dart new file mode 100644 index 00000000..fd913583 --- /dev/null +++ b/test/total_hourly_transactions/cubit/total_hourly_transactions_cubit_test.dart @@ -0,0 +1,188 @@ +// ignore_for_file: prefer_const_constructors +import 'package:bloc_test/bloc_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/features/features.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/rearchitecture.dart'; +import 'package:zenon_syrius_wallet_flutter/rearchitecture/utils/exceptions/exceptions.dart'; +import 'package:zenon_syrius_wallet_flutter/utils/constants.dart'; +import 'package:znn_sdk_dart/znn_sdk_dart.dart'; + +import '../../helpers/hydrated_bloc.dart'; + +class MockZenon extends Mock implements Zenon {} + +class MockWsClient extends Mock implements WsClient {} + +class MockLedger extends Mock implements LedgerApi {} + +class MockDetailedMomentumList extends Mock implements DetailedMomentumList {} + +class MockDetailedMomentum extends Mock implements DetailedMomentum {} + +class MockMomentum extends Mock implements Momentum {} + +class MockAccountBlock extends Mock implements AccountBlock {} + +void main() { + initHydratedStorage(); + + group('TotalHourlyTransactionsCubit', () { + late MockZenon mockZenon; + late MockWsClient mockWsClient; + late MockLedger mockLedger; + late TotalHourlyTransactionsCubit transactionsCubit; + late SyriusException fetchException; + late MockMomentum mockMomentum; + late MockDetailedMomentum mockDetailedMomentum; + late MockDetailedMomentumList mockDetailedMomentumList; + late MockAccountBlock mockAccBlock; + + setUp(() async { + mockZenon = MockZenon(); + mockLedger = MockLedger(); + mockWsClient = MockWsClient(); + transactionsCubit = TotalHourlyTransactionsCubit( + zenon: mockZenon, + ); + fetchException = NotEnoughMomentumsException(); + mockMomentum = MockMomentum(); + mockDetailedMomentum = MockDetailedMomentum(); + mockDetailedMomentumList = MockDetailedMomentumList(); + mockAccBlock = MockAccountBlock(); + + when(() => mockZenon.wsClient).thenReturn(mockWsClient); + when(() => mockWsClient.isClosed()).thenReturn(false); + when(() => mockZenon.ledger).thenReturn(mockLedger); + + when(() => mockLedger.getFrontierMomentum()) + .thenAnswer((_) async => mockMomentum); + when(() => mockMomentum.height) + .thenReturn(kMomentumsPerHour + 1); + when(() => mockLedger.getDetailedMomentumsByHeight(any(), any())) + .thenAnswer((_) async => mockDetailedMomentumList); + when(() => mockDetailedMomentumList.list) + .thenReturn([mockDetailedMomentum]); + when(() => mockDetailedMomentum.blocks) + .thenReturn([mockAccBlock, mockAccBlock]); + }); + + test('initial status is correct', () { + final TotalHourlyTransactionsCubit cubit = TotalHourlyTransactionsCubit( + zenon: mockZenon, + ); + expect(cubit.state.status, TimerStatus.initial); + }); + + group('fromJson/toJson', () { + test('can (de)serialize initial state', () { + final TotalHourlyTransactionsState initialState = + TotalHourlyTransactionsState(); + + final Map? serialized = transactionsCubit.toJson( + initialState, + ); + final TotalHourlyTransactionsState? deserialized = + transactionsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(initialState)); + }); + + test('can (de)serialize loading state', () { + final TotalHourlyTransactionsState loadingState = + TotalHourlyTransactionsState( + status: TimerStatus.loading, + ); + + final Map? serialized = transactionsCubit.toJson( + loadingState, + ); + final TotalHourlyTransactionsState? deserialized = + transactionsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(loadingState)); + }); + + test('can (de)serialize success state', () { + final TotalHourlyTransactionsState successState = + TotalHourlyTransactionsState( + status: TimerStatus.success, + data: 2, + ); + + final Map? serialized = transactionsCubit.toJson( + successState, + ); + final TotalHourlyTransactionsState? deserialized = + transactionsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(successState)); + }); + + test('can (de)serialize failure state', () { + final TotalHourlyTransactionsState failureState = + TotalHourlyTransactionsState( + status: TimerStatus.failure, + error: fetchException, + ); + + final Map? serialized = transactionsCubit.toJson( + failureState, + ); + final TotalHourlyTransactionsState? deserialized = + transactionsCubit.fromJson( + serialized!, + ); + expect(deserialized, equals(failureState)); + }); + }); + + group('fetch', () { + blocTest( + 'calls getFrontierMomentum and getDetailedMomentumsByHeight once', + build: () => transactionsCubit, + act: (TotalHourlyTransactionsCubit cubit) => cubit.fetch(), + verify: (_) { + verify(() => mockLedger.getFrontierMomentum()).called(1); + verify(() => mockLedger.getDetailedMomentumsByHeight(any(), any())) + .called(1); + }, + ); + + blocTest( + 'emits [loading, success] when fetch returns', + build: () => transactionsCubit, + act: (TotalHourlyTransactionsCubit cubit) + => cubit.fetchDataPeriodically(), + expect: () => [ + TotalHourlyTransactionsState(status: TimerStatus.loading), + TotalHourlyTransactionsState( + status: TimerStatus.success, + data: 2, + ), + ], + ); + + blocTest( + 'emits [loading, failure] when fetch throws an error', + setUp: () { + when(() => mockLedger.getFrontierMomentum()) + .thenThrow(fetchException); + }, + build: () => transactionsCubit, + act: (TotalHourlyTransactionsCubit cubit) + => cubit.fetchDataPeriodically(), + expect: () => [ + TotalHourlyTransactionsState(status: TimerStatus.loading), + TotalHourlyTransactionsState( + status: TimerStatus.failure, + error: fetchException, + ), + ], + ); + }); + }); +} diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 3313166a..83815039 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -1,14 +1,17 @@ -cmake_minimum_required(VERSION 3.15) +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) project(syrius LANGUAGES CXX) +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. set(BINARY_NAME "syrius") set(APPLICATION_ID "network.zenon.syrius") -cmake_policy(SET CMP0063 NEW) +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Configure build options. +# Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" @@ -21,7 +24,7 @@ else() "Debug" "Profile" "Release") endif() endif() - +# Define settings for the Profile build mode. set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") @@ -31,6 +34,10 @@ set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") add_definitions(-DUNICODE -D_UNICODE) # Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. function(APPLY_STANDARD_SETTINGS TARGET) target_compile_features(${TARGET} PUBLIC cxx_std_17) target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") @@ -39,14 +46,14 @@ function(APPLY_STANDARD_SETTINGS TARGET) target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") - # Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") add_subdirectory(${FLUTTER_MANAGED_DIR}) -# Application build +# Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -81,6 +88,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") @@ -98,35 +111,80 @@ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" # Bundle required ZNN libraries for Syrius set(SYRIUS_PROJECT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/..") -# Leveraging flutter to identify dependency locations -file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_SDK_DART_PATH REGEX "(file:).*(znn_sdk_dart).*\\/\"" ) +# Read lines from the file `package_config_subset` that match the regex pattern +# looking for paths containing "znn_sdk_dart" and ending with a "/". +file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config_subset" + ZNN_SDK_DART_PATHS REGEX "(file:).*(znn_sdk_dart).*/$" ) + +# Initialize an empty variable to store the final znn_sdk_dart path +set(ZNN_SDK_DART_PATH "") + +# Loop through each path found by the file command +foreach(PATH ${ZNN_SDK_DART_PATHS}) + # Exclude paths containing "/lib/" using a conditional check + if(NOT "${PATH}" MATCHES ".*/lib/.*") + # If the condition is met, set the current path as ZNN_SDK_DART_PATH + set(ZNN_SDK_DART_PATH ${PATH}) + endif() +endforeach() + +# Remove the "file:///" prefix from the selected path, if present +string(REPLACE "file:///" "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") -string(REPLACE "\"rootUri\": \"file:///" "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") -string(REPLACE "/\"," "" ZNN_SDK_DART_PATH "${ZNN_SDK_DART_PATH}") +# Strip any leading or trailing whitespace from the cleaned path string(STRIP "${ZNN_SDK_DART_PATH}" ZNN_SDK_DART_PATH) -file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config.json" - ZNN_LEDGER_DART_PATH REGEX "(file:).*(znn_ledger_dart).*\\/\"" ) +# Repeat the same process for "znn_ledger_dart" paths: + +# Read lines from the file `package_config_subset` that match the regex pattern +# looking for paths containing "znn_ledger_dart" and ending with a "/". +file(STRINGS "${SYRIUS_PROJECT_DIRECTORY}/.dart_tool/package_config_subset" + ZNN_LEDGER_DART_PATHS REGEX "(file:).*(znn_ledger_dart).*/$" ) -string(REPLACE "\"rootUri\": \"file:///" "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") -string(REPLACE "/\"," "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") +# Initialize an empty variable to store the final znn_ledger_dart path +set(ZNN_LEDGER_DART_PATH "") + +# Loop through each path found by the file command +foreach(PATH ${ZNN_LEDGER_DART_PATHS}) + # Exclude paths containing "/lib/" using a conditional check + if(NOT "${PATH}" MATCHES ".*/lib/.*") + # If the condition is met, set the current path as ZNN_LEDGER_DART_PATH + set(ZNN_LEDGER_DART_PATH ${PATH}) + endif() +endforeach() + +# Remove the "file:///" prefix from the selected path, if present +string(REPLACE "file:///" "" ZNN_LEDGER_DART_PATH "${ZNN_LEDGER_DART_PATH}") + +# Strip any leading or trailing whitespace from the cleaned path string(STRIP "${ZNN_LEDGER_DART_PATH}" ZNN_LEDGER_DART_PATH) +# Append the paths to various library files into the `SYRIUS_LIBRARIES` list. +# These paths include: +# 1. A static path to `libznn.dll` located in the `embedded_node/blobs` directory. +# 2. Dynamically constructed paths based on `ZNN_SDK_DART_PATH` and `ZNN_LEDGER_DART_PATH`. +# These paths point to shared libraries for argon2, proof-of-work, and ledger functionality. list(APPEND SYRIUS_LIBRARIES - "${SYRIUS_PROJECT_DIRECTORY}/lib/embedded_node/blobs/libznn.dll" - "${ZNN_SDK_DART_PATH}/lib/src/argon2/blobs/argon2_ffi_plugin.dll" - "${ZNN_SDK_DART_PATH}/lib/src/pow/blobs/libpow_links.dll" - "${ZNN_LEDGER_DART_PATH}/lib/src/ledger/blobs/libledger_ffi.dll" -) + "${SYRIUS_PROJECT_DIRECTORY}/lib/embedded_node/blobs/libznn.dll" # Path to libznn.dll + "${ZNN_SDK_DART_PATH}/lib/src/argon2/blobs/argon2_ffi_plugin.dll" # Argon2 plugin + "${ZNN_SDK_DART_PATH}/lib/src/pow/blobs/libpow_links.dll" # Proof-of-work library + "${ZNN_LEDGER_DART_PATH}/lib/src/ledger/blobs/libledger_ffi.dll" # Ledger FFI library + ) +# Loop over each library in the `SYRIUS_LIBRARIES` list. foreach(znn_library ${SYRIUS_LIBRARIES}) + # Install the library to the destination specified by `CMAKE_INSTALL_PREFIX`. + # `FILES` specifies the file to copy. + # `DESTINATION` specifies where the file should be installed. + # `COMPONENT` groups the installation under the "Runtime" component for packaging or deployment tools. install(FILES "${znn_library}" - DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) + DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + + # Print a status message indicating that the current library is being copied. message(STATUS "Copy ZNN library: \"${znn_library}\"") endforeach(znn_library) find_program(POWERSHELL_PATH NAMES powershell) add_custom_target("git_metadata" ALL - COMMAND ${POWERSHELL_PATH} -ExecutionPolicy Bypass "${CMAKE_HOME_DIRECTORY}/CreateGitMetadata.ps1") \ No newline at end of file + COMMAND ${POWERSHELL_PATH} -ExecutionPolicy Bypass "${CMAKE_HOME_DIRECTORY}/CreateGitMetadata.ps1") \ No newline at end of file diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt index 86edc67b..903f4899 100644 --- a/windows/flutter/CMakeLists.txt +++ b/windows/flutter/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.15) +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt index 0b899a0b..394917c0 100644 --- a/windows/runner/CMakeLists.txt +++ b/windows/runner/CMakeLists.txt @@ -1,6 +1,11 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.14) project(runner LANGUAGES CXX) +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. add_executable(${BINARY_NAME} WIN32 "flutter_window.cpp" "main.cpp" @@ -10,8 +15,26 @@ add_executable(${BINARY_NAME} WIN32 "Runner.rc" "runner.exe.manifest" ) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index b43b9095..955ee303 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index 25f090a9..35699359 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -4,9 +4,49 @@ #include "flutter_window.h" #include "utils.h" +#include "app_links/app_links_plugin_c_api.h" + +bool SendAppLinkToInstance(const std::wstring& title) { + // Find our exact window + HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", title.c_str()); + + if (hwnd) { + // Dispatch new link to current window + SendAppLink(hwnd); + + // (Optional) Restore our window to front in same state + WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) }; + GetWindowPlacement(hwnd, &place); + + switch(place.showCmd) { + case SW_SHOWMAXIMIZED: + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + break; + case SW_SHOWMINIMIZED: + ShowWindow(hwnd, SW_RESTORE); + break; + default: + ShowWindow(hwnd, SW_NORMAL); + break; + } + + SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); + SetForegroundWindow(hwnd); + // END (Optional) Restore + + // Window has been found, don't create another one. + return true; + } + + return false; +} int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, _In_ wchar_t *command_line, _In_ int show_command) { + if (SendAppLinkToInstance(L"s y r i u s")) { + return EXIT_SUCCESS; + } + // Attach to console when present (e.g., 'flutter run') or create a // new console when running with a debugger. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { @@ -27,7 +67,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"s y r i u s", origin, size)) { + if (!window.Create(L"s y r i u s", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest index a42ea768..153653e8 100644 --- a/windows/runner/runner.exe.manifest +++ b/windows/runner/runner.exe.manifest @@ -9,12 +9,6 @@ - - - - - - diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp index d19bdbbc..3a0b4651 100644 --- a/windows/runner/utils.cpp +++ b/windows/runner/utils.cpp @@ -45,18 +45,19 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - int target_length = ::WideCharToMultiByte( + unsigned int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); - if (target_length == 0) { - return std::string(); - } + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index 10a458a3..60608d0f 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -1,15 +1,31 @@ #include "win32_window.h" +#include #include #include "resource.h" -#include "app_links/app_links_plugin_c_api.h" - namespace { +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -33,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -44,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -104,13 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { - if (SendAppLinkToInstance(title)) { - return false; - } - +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -123,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(size.width, scale_factor), Scale(size.height, scale_factor), nullptr, nullptr, GetModuleHandle(nullptr), this); @@ -132,44 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + UpdateTheme(window); + return OnCreate(); } -bool Win32Window::SendAppLinkToInstance(const std::wstring& title) { - // Find our exact window - HWND hwnd = ::FindWindow(kWindowClassName, title.c_str()); - - if (hwnd) { - // Dispatch new link to current window - SendAppLink(hwnd); - - // (Optional) Restore our window to front in same state - WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) }; - GetWindowPlacement(hwnd, &place); - - switch (place.showCmd) { - case SW_SHOWMAXIMIZED: - ShowWindow(hwnd, SW_SHOWMAXIMIZED); - break; - case SW_SHOWMINIMIZED: - ShowWindow(hwnd, SW_RESTORE); - break; - default: - ShowWindow(hwnd, SW_NORMAL); - break; - } - - SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); - SetForegroundWindow(hwnd); - - // Window has been found, don't create another one. - return true; - } - - return false; +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); } - // static LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, @@ -229,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -284,3 +271,18 @@ bool Win32Window::OnCreate() { void Win32Window::OnDestroy() { // No-op; provided for subclasses. } + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index 9cfea10a..e901dde6 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // Creates a win32 window with |title| that is positioned and sized using // |origin| and |size|. New windows are created on the default monitor. Window // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size to will treat the width height passed in to this function - // as logical pixels and scale to appropriate for the default monitor. Returns - // true if the window was created successfully. - bool CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size); + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); // Release OS resources associated with window. void Destroy(); @@ -76,7 +77,7 @@ class Win32Window { // OS callback called by message pump. Handles the WM_NCCREATE message which // is passed when the non-client area is being created and enables automatic // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // Retrieves a class instance pointer for |window| static Win32Window* GetThisFromHandle(HWND const window) noexcept; + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + bool quit_on_close_ = false; // window handle for top level window. @@ -93,11 +97,6 @@ class Win32Window { // window handle for hosted content. HWND child_content_ = nullptr; - - // Dispatches link if any. - // This method enables our app to be with a single instance too. - // This is mandatory if you want to catch further links in same app. - bool SendAppLinkToInstance(const std::wstring& title); }; #endif // RUNNER_WIN32_WINDOW_H_