Change Dashboard view on desktop size screens

This commit is contained in:
OmarHatem 2023-01-18 22:11:59 +02:00
parent 9f1e663719
commit 42a7439315
7 changed files with 393 additions and 121 deletions

View file

@ -0,0 +1,123 @@
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class MainActions {
final String Function(BuildContext context) name;
final String image;
final bool Function(DashboardViewModel viewModel)? isEnabled;
final bool Function(DashboardViewModel viewModel)? canShow;
final Future<void> Function(BuildContext context, DashboardViewModel viewModel) onTap;
MainActions._({
required this.name,
required this.image,
this.isEnabled,
this.canShow,
required this.onTap,
});
static List<MainActions> all = [
buyAction,
receiveAction,
exchangeAction,
sendAction,
sellAction,
];
static MainActions buyAction = MainActions._(
name: (context) => S.of(context).buy,
image: 'assets/images/buy.png',
isEnabled: (viewModel) => viewModel.isEnabledBuyAction,
canShow: (viewModel) => viewModel.hasBuyAction,
onTap: (BuildContext context, DashboardViewModel viewModel) async {
final walletType = viewModel.type;
switch (walletType) {
case WalletType.bitcoin:
Navigator.of(context).pushNamed(Routes.onramperPage);
break;
case WalletType.litecoin:
Navigator.of(context).pushNamed(Routes.onramperPage);
break;
default:
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).buy,
alertContent: S.of(context).buy_alert_content,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
}
},
);
static MainActions receiveAction = MainActions._(
name: (context) => S.of(context).receive,
image: 'assets/images/received.png',
onTap: (BuildContext context, DashboardViewModel viewModel) async {
Navigator.pushNamed(context, Routes.addressPage);
},
);
static MainActions exchangeAction = MainActions._(
name: (context) => S.of(context).exchange,
image: 'assets/images/transfer.png',
isEnabled: (viewModel) => viewModel.isEnabledExchangeAction,
canShow: (viewModel) => viewModel.hasExchangeAction,
onTap: (BuildContext context, DashboardViewModel viewModel) async {
if (viewModel.isEnabledExchangeAction) {
await Navigator.of(context).pushNamed(Routes.exchange);
}
},
);
static MainActions sendAction = MainActions._(
name: (context) => S.of(context).send,
image: 'assets/images/upload.png',
onTap: (BuildContext context, DashboardViewModel viewModel) async {
Navigator.pushNamed(context, Routes.send);
},
);
static MainActions sellAction = MainActions._(
name: (context) => S.of(context).sell,
image: 'assets/images/sell.png',
isEnabled: (viewModel) => viewModel.isEnabledSellAction,
canShow: (viewModel) => viewModel.hasSellAction,
onTap: (BuildContext context, DashboardViewModel viewModel) async {
final walletType = viewModel.type;
switch (walletType) {
case WalletType.bitcoin:
final moonPaySellProvider = MoonPaySellProvider();
final uri = await moonPaySellProvider.requestUrl(
currency: viewModel.wallet.currency,
refundWalletAddress: viewModel.wallet.walletAddresses.address,
);
await launch(uri);
break;
default:
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).sell,
alertContent: S.of(context).sell_alert_content,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
},
);
}
},
);
}

View file

@ -5,6 +5,7 @@ import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
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/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';
@ -26,6 +27,7 @@ import 'package:cake_wallet/src/screens/support/support_page.dart';
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
@ -511,6 +513,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
getIt.get<NodeCreateOrEditViewModel>(param1: type),
));
case Routes.desktop_actions:
return CupertinoPageRoute<void>(
builder: (_) => DesktopDashboardActions(getIt<DashboardViewModel>()));
default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(

View file

@ -82,4 +82,5 @@ class Routes {
static const displaySettingsPage = '/display_settings_page';
static const otherSettingsPage = '/other_settings_page';
static const advancedPrivacySettings = '/advanced_privacy_settings';
static const desktop_actions = '/desktop_actions';
}

View file

@ -1,4 +1,6 @@
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/widgets/market_place_page.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/generated/i18n.dart';
@ -30,8 +32,9 @@ class DashboardPage extends BasePage {
required this.walletViewModel,
required this.addressListViewModel,
});
final BalancePage balancePage;
@override
Color get backgroundLightColor =>
currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white;
@ -58,15 +61,15 @@ class DashboardPage extends BasePage {
@override
Widget middle(BuildContext context) {
return SyncIndicator(dashboardViewModel: walletViewModel,
onTap: () => Navigator.of(context, rootNavigator: true)
.pushNamed(Routes.connectionSync));
return SyncIndicator(
dashboardViewModel: walletViewModel,
onTap: () => Navigator.of(context, rootNavigator: true).pushNamed(Routes.connectionSync));
}
@override
Widget trailing(BuildContext context) {
final menuButton = Image.asset('assets/images/menu.png',
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!);
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!);
return Container(
alignment: Alignment.centerRight,
@ -93,125 +96,97 @@ class DashboardPage extends BasePage {
final sendImage = Image.asset('assets/images/upload.png',
height: 24,
width: 24,
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!);
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!);
final receiveImage = Image.asset('assets/images/received.png',
height: 24,
width: 24,
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!);
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!);
_setEffects(context);
return SafeArea(
minimum: EdgeInsets.only(bottom: 24),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
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!),
)),
Observer(builder: (_) {
return ClipRect(
child:Container(
margin: const EdgeInsets.only(left: 16, right: 16),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
border: Border.all(color: currentTheme.type == ThemeType.bright ? Color.fromRGBO(255, 255, 255, 0.2): Colors.transparent, width: 1, ),
color:Theme.of(context).textTheme!.headline6!.backgroundColor!),
child: Container(
padding: EdgeInsets.only(left: 32, right: 32),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
if (walletViewModel.hasBuyAction)
ActionButton(
image: Image.asset('assets/images/buy.png',
height: 24,
width: 24,
color: !walletViewModel.isEnabledBuyAction
? Theme.of(context)
.accentTextTheme!
.headline3!
.backgroundColor!
: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!),
title: S.of(context).buy,
onClick: () async => await _onClickBuyButton(context),
textColor: !walletViewModel.isEnabledBuyAction
? Theme.of(context)
minimum: EdgeInsets.only(bottom: 24),
child: LayoutBuilder(builder: (context, constraints) {
if (constraints.maxWidth > 900) {
return DesktopDashboardView(balancePage);
}
return Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
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!
.headline3!
.backgroundColor!
: null),
ActionButton(
image: receiveImage,
title: S.of(context).receive,
route: Routes.addressPage),
if (walletViewModel.hasExchangeAction)
ActionButton(
image: Image.asset('assets/images/transfer.png',
height: 24,
width: 24,
color: !walletViewModel.isEnabledExchangeAction
? Theme.of(context)
.accentTextTheme!
.headline3!
.backgroundColor!
: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!),
title: S.of(context).exchange,
onClick: () async => _onClickExchangeButton(context),
textColor: !walletViewModel.isEnabledExchangeAction
? Theme.of(context)
.accentTextTheme!
.headline3!
.backgroundColor!
: null),
ActionButton(
image: sendImage,
title: S.of(context).send,
route: Routes.send),
if (walletViewModel.hasSellAction)
ActionButton(
image: Image.asset('assets/images/sell.png',
height: 24,
width: 24,
color: !walletViewModel.isEnabledSellAction
? Theme.of(context)
.accentTextTheme!
.headline3!
.backgroundColor!
: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!),
title: S.of(context).sell,
onClick: () async => await _onClickSellButton(context),
textColor: !walletViewModel.isEnabledSellAction
? Theme.of(context)
.accentTextTheme!
.headline3!
.backgroundColor!
: null),
],
),),
),),);
}),
],
));
.headline4!
.backgroundColor!),
)),
Observer(builder: (_) {
return ClipRect(
child: Container(
margin: const EdgeInsets.only(left: 16, right: 16),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
border: Border.all(
color: currentTheme.type == ThemeType.bright
? Color.fromRGBO(255, 255, 255, 0.2)
: Colors.transparent,
width: 1,
),
color: Theme.of(context).textTheme.headline6!.backgroundColor!,
),
child: Container(
padding: EdgeInsets.only(left: 32, right: 32),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: MainActions.all
.where((element) => element.canShow?.call(walletViewModel) ?? true)
.map((action) => ActionButton(
image: Image.asset(action.image,
height: 24,
width: 24,
color: action.isEnabled?.call(walletViewModel) ?? true
? Theme.of(context)
.accentTextTheme
.headline2!
.backgroundColor!
: Theme.of(context)
.accentTextTheme
.headline3!
.backgroundColor!),
title: action.name(context),
onClick: () async =>
await action.onTap(context, walletViewModel),
textColor: action.isEnabled?.call(walletViewModel) ?? true
? null
: Theme.of(context)
.accentTextTheme
.headline3!
.backgroundColor!,
))
.toList(),
),
),
),
),
);
}),
],
);
}));
}
void _setEffects(BuildContext context) async {
@ -234,8 +209,7 @@ class DashboardPage extends BasePage {
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).pre_seed_title,
alertContent:
S.of(context).outdated_electrum_wallet_description,
alertContent: S.of(context).outdated_electrum_wallet_description,
buttonText: S.of(context).understand,
buttonAction: () => Navigator.of(context).pop());
});
@ -297,8 +271,7 @@ class DashboardPage extends BasePage {
final moonPaySellProvider = MoonPaySellProvider();
final uri = await moonPaySellProvider.requestUrl(
currency: walletViewModel.wallet.currency,
refundWalletAddress:
walletViewModel.wallet.walletAddresses.address);
refundWalletAddress: walletViewModel.wallet.walletAddresses.address);
await launch(uri);
break;
default:

View file

@ -0,0 +1,66 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
class DesktopActionButton extends StatelessWidget {
final String image;
final String title;
final bool canShow;
final bool isEnabled;
final Function() onTap;
const DesktopActionButton({
Key? key,
required this.title,
required this.image,
required this.onTap,
bool? canShow,
bool? isEnabled,
}) : this.isEnabled = isEnabled ?? true,
this.canShow = canShow ?? true,
super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Container(
padding: EdgeInsets.symmetric(vertical: 25),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Theme.of(context).textTheme.headline6!.backgroundColor!,
),
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
image,
height: 30,
width: 30,
color: isEnabled
? Theme.of(context).accentTextTheme.headline2!.backgroundColor!
: Theme.of(context).accentTextTheme.headline3!.backgroundColor!,
),
const SizedBox(width: 10),
AutoSizeText(
title,
style: TextStyle(
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
color: isEnabled
? Theme.of(context).accentTextTheme.headline2!.backgroundColor!
: null,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
)
],
),
),
),
);
}
}

View file

@ -0,0 +1,71 @@
import 'package:cake_wallet/entities/main_actions.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/material.dart';
class DesktopDashboardActions extends StatelessWidget {
final DashboardViewModel dashboardViewModel;
const DesktopDashboardActions(this.dashboardViewModel, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(height: 16),
DesktopActionButton(
title: MainActions.exchangeAction.name(context),
image: MainActions.exchangeAction.image,
canShow: MainActions.exchangeAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.exchangeAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.exchangeAction.onTap(context, dashboardViewModel),
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.receiveAction.name(context),
image: MainActions.receiveAction.image,
canShow: MainActions.receiveAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.receiveAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.receiveAction.onTap(context, dashboardViewModel),
),
),
Expanded(
child: DesktopActionButton(
title: MainActions.sendAction.name(context),
image: MainActions.sendAction.image,
canShow: MainActions.sendAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.sendAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.sendAction.onTap(context, dashboardViewModel),
),
),
],
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.buyAction.name(context),
image: MainActions.buyAction.image,
canShow: MainActions.buyAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.buyAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.buyAction.onTap(context, dashboardViewModel),
),
),
Expanded(
child: DesktopActionButton(
title: MainActions.sellAction.name(context),
image: MainActions.sellAction.image,
canShow: MainActions.sellAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.sellAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.sellAction.onTap(context, dashboardViewModel),
),
),
],
),
],
);
}
}

View file

@ -0,0 +1,32 @@
import 'package:cake_wallet/routes.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/router.dart' as Router;
class DesktopDashboardView extends StatelessWidget {
final Widget balancePage;
const DesktopDashboardView(this.balancePage, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 3,
child: balancePage,
),
Expanded(
flex: 5,
child: Navigator(
initialRoute: Routes.desktop_actions,
onGenerateRoute: (settings) => Router.createRoute(settings),
onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) {
return [navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!];
},
),
),
],
);
}
}