diff --git a/assets/images/desktop_menu.png b/assets/images/desktop_transactions_outline_icon.png similarity index 100% rename from assets/images/desktop_menu.png rename to assets/images/desktop_transactions_outline_icon.png diff --git a/assets/images/solid_desktop_menu.png b/assets/images/desktop_transactions_solid_icon.png similarity index 100% rename from assets/images/solid_desktop_menu.png rename to assets/images/desktop_transactions_solid_icon.png diff --git a/lib/di.dart b/lib/di.dart index 6180df576..c5bf8d0ea 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -19,6 +19,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart'; @@ -168,6 +169,7 @@ import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cw_core/crypto_currency.dart'; + final getIt = GetIt.instance; var _isSetupFinished = false; @@ -832,6 +834,8 @@ Future setup( getIt.registerFactory(() => DesktopWalletSelectionDropDown(getIt.get())); + getIt.registerFactory(() => DesktopSidebarViewModel()); + getIt.registerFactoryParam( (IoniaAnyPayPaymentInfo paymentInfo, AnyPayPaymentCommittedInfo committedInfo) => IoniaPaymentStatusViewModel( diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 5e560cc01..4665751a7 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/main_actions.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_dashboard_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart'; @@ -10,6 +11,7 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -37,6 +39,7 @@ class DashboardPage extends StatelessWidget { @override Widget build(BuildContext context) { + final desktopSidebarViewModel = getIt(); return Scaffold( body: ResponsiveLayoutUtil.instance.isMobile(context) ? _DashboardPageView( @@ -45,7 +48,9 @@ class DashboardPage extends StatelessWidget { addressListViewModel: addressListViewModel, ) : DesktopSidebarWrapper( + desktopSidebarViewModel: desktopSidebarViewModel, child: DesktopDashboardPage( + desktopSidebarViewModel: desktopSidebarViewModel, balancePage: balancePage, walletViewModel: walletViewModel, addressListViewModel: addressListViewModel, diff --git a/lib/src/screens/dashboard/desktop_dashboard_page.dart b/lib/src/screens/dashboard/desktop_dashboard_page.dart index 4b8a4bb44..ac5700af4 100644 --- a/lib/src/screens/dashboard/desktop_dashboard_page.dart +++ b/lib/src/screens/dashboard/desktop_dashboard_page.dart @@ -4,17 +4,18 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_view.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/main.dart'; @@ -23,6 +24,7 @@ class DesktopDashboardPage extends BasePage { required this.balancePage, required this.walletViewModel, required this.addressListViewModel, + required this.desktopSidebarViewModel, }); @override @@ -58,8 +60,9 @@ class DesktopDashboardPage extends BasePage { @override Widget trailing(BuildContext context) { - final iconPath = Image.asset('assets/images/solid_desktop_menu.png', - color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!); + final selectedIconPath = 'assets/images/desktop_transactions_solid_icon.png'; + final unselectedIconPath = 'assets/images/desktop_transactions_outline_icon.png'; + return InkWell( onTap: () { String? currentPath; @@ -70,18 +73,30 @@ class DesktopDashboardPage extends BasePage { }); if (currentPath == Routes.transactionsPage) { - return Navigator.pop(desktopKey.currentContext!); - } + desktopSidebarViewModel.resetSidebar(); + return; + } + desktopSidebarViewModel.onPageChange(SidebarItem.transactions); desktopKey.currentState!.pushNamed(Routes.transactionsPage); + }, - child: iconPath, + child: Observer( + builder: (_) { + return Image.asset( + desktopSidebarViewModel.currentPage == SidebarItem.transactions + ? selectedIconPath + : unselectedIconPath, + ); + }, + ), ); } final BalancePage balancePage; final DashboardViewModel walletViewModel; final WalletAddressListViewModel addressListViewModel; + final DesktopSidebarViewModel desktopSidebarViewModel; bool _isEffectsInstalled = false; StreamSubscription? _onInactiveSub; diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart deleted file mode 100644 index b56329966..000000000 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'dart:async'; - -class SideMenuController { - late int _currentPage; - - int get currentPage => _currentPage; - - SideMenuController({int initialPage = 0}) { - _currentPage = initialPage; - } - final _streameController = StreamController.broadcast(); - - Stream get stream => _streameController.stream; - - void changePage(int index) { - _currentPage = index; - _streameController.sink.add(index); - } - - void dispose() { - _streameController.close(); - } - - void addListener(void Function(int) listener) { - _streameController.stream.listen(listener); - } - - void removeListener(void Function(int) listener) { - _streameController.stream.listen(listener).cancel(); - } -} - -class SideMenuGlobal { - static late SideMenuController controller; -} diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart index 5c3d0ea6b..f50cf6387 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart @@ -1,74 +1,39 @@ -import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart'; import 'package:flutter/material.dart'; -class SideMenuItem extends StatefulWidget { +class SideMenuItem extends StatelessWidget { const SideMenuItem({ Key? key, - this.onTap, + required this.onTap, required this.iconPath, - required this.priority, + required this.isSelected, }) : super(key: key); - final void Function(int, SideMenuController)? onTap; + final void Function() onTap; final String iconPath; - final int priority; - - @override - _SideMenuItemState createState() => _SideMenuItemState(); -} - -class _SideMenuItemState extends State { - late int currentPage = SideMenuGlobal.controller.currentPage; - - void _handleChange(int page) { - if (mounted) { - setState(() { - currentPage = page; - }); - } - } - - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - setState(() { - currentPage = SideMenuGlobal.controller.currentPage; - }); - if (mounted) { - SideMenuGlobal.controller.addListener(_handleChange); - } - }); - } - - @override - void dispose() { - SideMenuGlobal.controller.removeListener(_handleChange); - super.dispose(); - } - - Color _setColor() { - if (widget.priority == currentPage) { - return Theme.of(context).primaryTextTheme.headline6!.color!; - } else { - return Theme.of(context).highlightColor; - } - } + final bool isSelected; @override Widget build(BuildContext context) { + Color _setColor() { + if (isSelected) { + return Theme.of(context).primaryTextTheme.headline6!.color!; + } else { + return Theme.of(context).highlightColor; + } + } + return InkWell( child: Padding( padding: EdgeInsets.all(20), child: Image.asset( - widget.iconPath, + iconPath, fit: BoxFit.cover, height: 30, width: 30, color: _setColor(), ), ), - onTap: () => widget.onTap?.call(widget.priority, SideMenuGlobal.controller), + onTap: () => onTap.call(), highlightColor: Colors.transparent, focusColor: Colors.transparent, hoverColor: Colors.transparent, diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart index 84acd42a0..d93df1994 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart @@ -1,64 +1,76 @@ import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_view.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart'; -import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart'; +import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/router.dart' as Router; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; -class DesktopSidebarWrapper extends StatefulWidget { +class DesktopSidebarWrapper extends StatelessWidget { final Widget child; + final DesktopSidebarViewModel desktopSidebarViewModel; - const DesktopSidebarWrapper({required this.child}); - - @override - State createState() => _DesktopSidebarWrapperState(); -} - -class _DesktopSidebarWrapperState extends State { - final page = PageController(); - final sideMenu = SideMenuController(); - - @override - void initState() { - SideMenuGlobal.controller = sideMenu; - sideMenu.addListener((p0) { - page.jumpToPage(p0); - }); - super.initState(); - } + const DesktopSidebarWrapper({required this.child, required this.desktopSidebarViewModel}); @override Widget build(BuildContext context) { + final pageController = PageController(); + + reaction((_) => desktopSidebarViewModel.currentPage, (page) { + String? currentPath; + + desktopKey.currentState?.popUntil((route) { + currentPath = route.settings.name; + return true; + }); + if (page == SidebarItem.transactions) { + return; + } + + if (currentPath == Routes.transactionsPage) { + Navigator.of(desktopKey.currentContext!).pop(); + } + + pageController.animateToPage( + page.index, + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + }); + return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SideMenu( - topItems: [ - SideMenuItem( - iconPath: 'assets/images/wallet_outline.png', - priority: 0, - onTap: (page, _) => sideMenu.changePage(page), - ), - ], - bottomItems: [ - SideMenuItem( - iconPath: 'assets/images/support_icon.png', - priority: 1, - onTap: (page, _) => sideMenu.changePage(page), - ), - SideMenuItem( - iconPath: 'assets/images/settings_outline.png', - priority: 2, - onTap: (page, _) => sideMenu.changePage(page), - ), - ], - ), + Observer(builder: (_) { + return SideMenu( + topItems: [ + SideMenuItem( + iconPath: 'assets/images/wallet_outline.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.dashboard, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.dashboard), + ), + ], + bottomItems: [ + SideMenuItem( + iconPath: 'assets/images/support_icon.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.support, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.support)), + SideMenuItem( + iconPath: 'assets/images/settings_outline.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.settings, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.settings), + ), + ], + ); + }), Expanded( child: PageView( - controller: page, + controller: pageController, physics: NeverScrollableScrollPhysics(), children: [ - widget.child, + child, Container( child: Navigator( initialRoute: Routes.support, diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 64f02c73c..89149b3de 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -22,6 +22,7 @@ class TransactionsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + color: Theme.of(context).backgroundColor, padding: EdgeInsets.only( top: 24, bottom: 24 diff --git a/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart b/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart index c8ed24233..c8e32f16f 100644 --- a/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart'; import 'package:cake_wallet/src/widgets/setting_action_button.dart'; import 'package:cake_wallet/src/widgets/setting_actions.dart'; import 'package:cake_wallet/typography.dart'; @@ -17,19 +16,14 @@ class DesktopSettingsPage extends StatefulWidget { } class _DesktopSettingsPageState extends State { - int itemCount = 0; - SideMenuController sideMenu = SideMenuController(); + int itemCount = SettingActions.all.length; int? currentPage; bool isTapped = false; - initState() { - super.initState(); - itemCount = SettingActions.all.length; - sideMenu.addListener((index) { - setState(() { - isTapped = true; - currentPage = index; - }); + void _onItemChange(int index) { + setState(() { + currentPage = index; + isTapped = true; }); } @@ -67,8 +61,8 @@ class _DesktopSettingsPageState extends State { if (currentPage != index) { final settingContext = _settingsNavigatorKey.currentState?.context ?? context; - sideMenu.changePage(index); item.onTap.call(settingContext); + _onItemChange(index); } }, image: item.image, diff --git a/lib/view_model/dashboard/desktop_sidebar_view_model.dart b/lib/view_model/dashboard/desktop_sidebar_view_model.dart new file mode 100644 index 000000000..516990d85 --- /dev/null +++ b/lib/view_model/dashboard/desktop_sidebar_view_model.dart @@ -0,0 +1,33 @@ +import 'package:mobx/mobx.dart'; + +part 'desktop_sidebar_view_model.g.dart'; + +enum SidebarItem { + dashboard(0), + support(1), + settings(2), + transactions(3); + + final int value; + const SidebarItem(this.value); +} + +class DesktopSidebarViewModel = DesktopSidebarViewModelBase with _$DesktopSidebarViewModel; + +abstract class DesktopSidebarViewModelBase with Store { + DesktopSidebarViewModelBase(); + + @observable + SidebarItem currentPage = SidebarItem.dashboard; + + + @action + void onPageChange(SidebarItem item) { + currentPage = item; + } + + @action + void resetSidebar() { + currentPage = SidebarItem.dashboard; + } +}