From 4f1f51e0aa990490dae3ba3f31e54782f4b6cf06 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 25 Jan 2023 15:57:56 +0200 Subject: [PATCH] Add desktop sidebar --- assets/images/settings_outline.png | Bin 0 -> 871 bytes assets/images/support_icon.png | Bin 0 -> 819 bytes assets/images/wallet_outline.png | Bin 0 -> 628 bytes assets/images/wallet_solid.png | Bin 0 -> 581 bytes lib/router.dart | 5 + lib/routes.dart | 2 +- lib/src/screens/dashboard/dashboard_page.dart | 162 +++++++++++++++--- .../desktop_sidebar/side_menu.dart | 35 ++++ .../desktop_sidebar/side_menu_controller.dart | 35 ++++ .../desktop_sidebar/side_menu_item.dart | 76 ++++++++ lib/src/screens/exchange/exchange_page.dart | 15 +- .../dashboard_settings_page.dart | 15 ++ 12 files changed, 314 insertions(+), 31 deletions(-) create mode 100644 assets/images/settings_outline.png create mode 100644 assets/images/support_icon.png create mode 100644 assets/images/wallet_outline.png create mode 100644 assets/images/wallet_solid.png create mode 100644 lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart create mode 100644 lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart create mode 100644 lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart create mode 100644 lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart diff --git a/assets/images/settings_outline.png b/assets/images/settings_outline.png new file mode 100644 index 0000000000000000000000000000000000000000..3230f00c45cdb4a258fe38fc67edfb5fe61c1fd9 GIT binary patch literal 871 zcmV-t1DO1YP)NcZr-hDYJSr$5+#51u;(>6fSs(0k^Ylk04Ce&Rg$&A1T~T^h;#T$se5~cP>-Cl*PyXbo{R(3J>L#BoHGLVh_svqZqY5-%aERrA6ECL z`D+lkFFSqyRy==oFmpZ!h*BSyYcVbl>$yl+dN0`~Bx(|>h_4p=j01?Uq4~fCt2Z|e zVkCs{iU`k=)HSM8EhIWqO4>6L;a{4Bk+#HF3@Dia^2tfUGkZiGxJ?K~um6k`vQ*Tc z;2F_yf=H#P$dRmU9nBNd2B>#q1a3KC^lRcHc^0q_kK5}~;Bh~@=`2>bpiEPVkj^4h zyk?4`dJGCTM2l-S|4UtsNunwVPiuVv8S-JlIGSVE9V8VitZ`t1ABehh0LFV!7*x zqFs{~*IF3wkc;{7%B{xhKQr=DvT<&wieL?nIM&pU>Z{DIWF)54UMV xptZ|L(m=3b4f*%gWMKAyW002ovPDHLkV1jsFlE44} literal 0 HcmV?d00001 diff --git a/assets/images/support_icon.png b/assets/images/support_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0d6ec99fd1ef8fe39f50ce854500e89cc2c4fb26 GIT binary patch literal 819 zcmV-31I+x1P)wSQf5ttS2y@z~u(` zWQ1he?oG0!l1)OiEV^nlliA+>rvJVM_|Jlq6rR61%Uc!}SoJ<@yU8KpC4l*QeTDVc z&x-M10qni~R6xrv13{sC6ca+6>TlB0DFE| zMgy9k%E3-i!xVA@g2Ca|iZ=wHIhk!seH&#w$%)Es0+K_9PL8%$>q9!np99X#CWm$T zXr~y-nd-f4*~;f7&N43GsO)pz7C7lH8>#V)3xj$RQn7(n5-vyqp1ulQOsd5UB`E<{ zxWUd|TI$!LrJ4_9&*4}fx(MfsjHycHNqMILIh!8KYAF?E0dU>djWHE5&}_~+eBcn7 zpINH5eHF;cUKW!7T|btHu%W$`IP0TsJflt?u*LwfZK)tjS1z&tK8%&(#)Pg1gyHFwCW>Mz;iz1s09-*0 z?uhl0Uvq*noqM>o8cZ@S70H~HXR4_tVDi%@ie#N{&6LJ{y#FrzAR2c63o|%&_^s>HWB3m41S-6ael3CWQ_0G~Nl3EuA ztTO6s7sGIr-?yd@MDJQ5oL66XK18$JqfTEJ9J931usS-XZN%44BH+xwbLImH z{hR;W?%a6tw%pkM+f!C{3;Wq!(OM>+z5FQq($+a zEewe0w|vQ4q}idQJAA({@98Anm@CuLMj<=_wY8R<2baJMN(5@`bUX9~tK37+zUB`A O0000TM^696XwPC$_OmD~W+AU*|K5J9;T28Dok zm`&ouaqI*+lzENU2*_8FVHOye6f*nNkccSgX}jFreY?LB zkp#*4vmaRhr&uF6H-UN$*ahMpZK~<9T>hCnN)v4LV&`TMsgIc1RAE}ON z_tZ~J8kCHL5o(551mu8CA<9xaseAS<+&0LYNT!#c18yjj9W2_B4a=@O>G6DHGP7VA zjORe{Rxa6Ak|z5d1mx$NsA7?gH2l8%@%>r$Zf^G;k04#pjGOEq;Cwmb9$`y^ANbJ( zk`0ane>W`x{U7fm+MkNQJe-yMfzZEODx+_yvi!nD0l5-fars_zuA_7qq9=X00000NkvXXu0mjfLBjiN literal 0 HcmV?d00001 diff --git a/lib/router.dart b/lib/router.dart index b5d1cdd9f..5a790a265 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/onramper_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart'; +import 'package:cake_wallet/src/screens/settings/desktop_settings/dashboard_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; @@ -516,6 +517,10 @@ Route createRoute(RouteSettings settings) { case Routes.desktop_actions: return CupertinoPageRoute( builder: (_) => DesktopDashboardActions(getIt())); + + case Routes.desktop_settings_page: + return CupertinoPageRoute( + builder: (_) => DesktopSettingsPage()); default: return MaterialPageRoute( diff --git a/lib/routes.dart b/lib/routes.dart index 293864a23..44d9ab0ee 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -36,7 +36,7 @@ class Routes { static const exchangeTrade = '/exchange_trade'; static const restoreWalletFromSeedDetails = '/restore_from_seed_details'; static const exchange = '/exchange'; - static const settings = '/settings'; + static const desktop_settings_page = '/desktop_settings_page'; static const unlock = '/auth_not_closable'; static const rescan = '/rescan'; static const faq = '/faq'; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index ea23bcd6a..82188344e 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -1,6 +1,9 @@ import 'dart:async'; import 'package:cake_wallet/entities/main_actions.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/src/screens/dashboard/widgets/market_place_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; @@ -21,14 +24,132 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:cake_wallet/main.dart'; +import 'package:cake_wallet/router.dart' as Router; -class DashboardPage extends BasePage { +class DashboardPage extends StatefulWidget { DashboardPage({ required this.balancePage, required this.walletViewModel, required this.addressListViewModel, }); + final BalancePage balancePage; + final DashboardViewModel walletViewModel; + final WalletAddressListViewModel addressListViewModel; + + @override + State createState() => _DashboardPageState(); +} + +class _DashboardPageState extends State { + PageController page = PageController(); + SideMenuController sideMenu = SideMenuController(); + @override + void initState() { + sideMenu.addListener((p0) { + page.jumpToPage(p0); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: LayoutBuilder(builder: (context, constraints) { + if (constraints.maxWidth > 900) { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + flex: 1, + child: SideMenu( + controller: 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); + }, + ), + ], + ), + ), + Expanded( + flex: 9, + child: PageView( + controller: page, + physics: NeverScrollableScrollPhysics(), + children: [ + _DashboardPage( + balancePage: widget.balancePage, + walletViewModel: widget.walletViewModel, + addressListViewModel: widget.addressListViewModel, + ), + Container( + child: Navigator( + initialRoute: Routes.support, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: + (NavigatorState navigator, String initialRouteName) { + return [ + navigator + .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, + ), + ), + Navigator( + initialRoute: Routes.desktop_settings_page, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: + (NavigatorState navigator, String initialRouteName) { + return [ + navigator + .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, + ), + + ]), + ) + ], + ), + ); + } + return _DashboardPage( + balancePage: widget.balancePage, + walletViewModel: widget.walletViewModel, + addressListViewModel: widget.addressListViewModel); + }), + ); + } +} + +class _DashboardPage extends BasePage { + _DashboardPage({ + required this.balancePage, + required this.walletViewModel, + required this.addressListViewModel, + }); + final BalancePage balancePage; @override @@ -38,6 +159,9 @@ class DashboardPage extends BasePage { @override Color get backgroundDarkColor => Colors.transparent; + @override + AppBarStyle get appBarStyle => AppBarStyle.transparent; + @override Widget Function(BuildContext, Widget) get rootWrapper => (BuildContext context, Widget scaffold) => Container( @@ -101,26 +225,24 @@ class DashboardPage extends BasePage { mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: PageView.builder( - controller: controller, - itemCount: pages.length, - itemBuilder: (context, index) => pages[index])), + child: PageView.builder( + controller: controller, + itemCount: pages.length, + itemBuilder: (context, index) => pages[index])), Padding( - padding: EdgeInsets.only(bottom: 24, top: 10), - child: SmoothPageIndicator( - controller: controller, - count: pages.length, - effect: ColorTransitionEffect( - spacing: 6.0, - radius: 6.0, - dotWidth: 6.0, - dotHeight: 6.0, - dotColor: Theme.of(context).indicatorColor, - activeDotColor: Theme.of(context) - .accentTextTheme! - .headline4! - .backgroundColor!), - )), + padding: EdgeInsets.only(bottom: 24, top: 10), + child: SmoothPageIndicator( + controller: controller, + count: pages.length, + effect: ColorTransitionEffect( + spacing: 6.0, + radius: 6.0, + dotWidth: 6.0, + dotHeight: 6.0, + dotColor: Theme.of(context).indicatorColor, + activeDotColor: + Theme.of(context).accentTextTheme!.headline4!.backgroundColor!), + )), Observer(builder: (_) { return ClipRect( child: Container( diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart new file mode 100644 index 000000000..b59af2593 --- /dev/null +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart @@ -0,0 +1,35 @@ +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:flutter/material.dart'; + +class SideMenu extends StatelessWidget { + const SideMenu({ + super.key, + required this.topItems, + required this.controller, + required this.bottomItems, + }); + final List topItems; + final List bottomItems; + + final SideMenuController controller; + + @override + Widget build(BuildContext context) { + SideMenuGlobal.controller = controller; + return Container( + color: Colors.black.withOpacity(0.1), + width: double.infinity, + height: MediaQuery.of(context).size.height, + child: Column( + children: [ + SizedBox(height: 20), + ...topItems, + Spacer(), + ...bottomItems, + SizedBox(height: 30), + ], + ), + ); + } +} 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 new file mode 100644 index 000000000..b56329966 --- /dev/null +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart @@ -0,0 +1,35 @@ +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 new file mode 100644 index 000000000..5429566aa --- /dev/null +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart @@ -0,0 +1,76 @@ +import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart'; +import 'package:flutter/material.dart'; + +class SideMenuItem extends StatefulWidget { + const SideMenuItem({ + Key? key, + this.onTap, + required this.iconPath, + required this.priority, + }) : super(key: key); + + final void Function(int, SideMenuController)? 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) { + 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; + } + } + + @override + Widget build(BuildContext context) { + return InkWell( + child: Padding( + padding: EdgeInsets.all(20), + child: Image.asset( + widget.iconPath, + fit: BoxFit.cover, + height: 30, + width: 30, + color: _setColor(), + ), + ), + onTap: () => widget.onTap?.call(widget.priority, SideMenuGlobal.controller), + highlightColor: Colors.transparent, + focusColor: Colors.transparent, + hoverColor: Colors.transparent, + splashColor: Colors.transparent, + ); + } +} diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 744848156..fc49582ca 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -168,17 +168,12 @@ class ExchangePage extends BasePage { bottomRight: Radius.circular(24)), gradient: LinearGradient( colors: [ - Theme.of(context) - .primaryTextTheme! - .subtitle2! - .color!, - Theme.of(context) - .primaryTextTheme! - .subtitle2! - .decorationColor!, - ], + Theme.of(context).scaffoldBackgroundColor, + + Theme.of(context).accentColor, + ], begin: Alignment.topLeft, - end: Alignment.bottomRight), + end: Alignment.topRight), ), padding: EdgeInsets.fromLTRB(24, 100, 24, 32), child: Observer( diff --git a/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart b/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart new file mode 100644 index 000000000..336ff0cd0 --- /dev/null +++ b/lib/src/screens/settings/desktop_settings/dashboard_settings_page.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class DesktopSettingsPage extends StatelessWidget { + const DesktopSettingsPage({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + child: Center( + child: Text('Desktop settings page'), + ), + ); + } +} \ No newline at end of file