Merge pull request #790 from cake-tech/add-create-restore-dropdown

Add create and restore wallet options to dropdown menu
This commit is contained in:
Omar Hatem 2023-02-22 19:05:20 +02:00 committed by GitHub
commit 9616974d33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 195 additions and 86 deletions

View file

@ -0,0 +1,9 @@
import 'package:flutter/material.dart';
class DesktopDropdownItem {
final Function() onSelected;
final Widget child;
final bool isSelected;
DesktopDropdownItem({required this.onSelected, required this.child, this.isSelected = false});
}

View file

@ -1,5 +1,4 @@
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_view.dart';
import 'package:flutter/widgets.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/entities/load_current_wallet.dart';

View file

@ -1,14 +1,18 @@
import 'package:another_flushbar/flushbar.dart';
import 'package:cake_wallet/entities/desktop_dropdown_item.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
class DesktopWalletSelectionDropDown extends StatefulWidget {
final WalletListViewModel walletListViewModel;
@ -25,85 +29,96 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
final double tileHeight = 60;
Image _getNewWalletImage(BuildContext context) => Image.asset(
'assets/images/new_wallet.png',
height: 12,
width: 12,
color: Theme.of(context).primaryTextTheme.headline6!.color!,
);
Image _getRestoreWalletImage(BuildContext context) => Image.asset(
'assets/images/restore_wallet.png',
height: 12,
width: 12,
color: Theme.of(context).primaryTextTheme.headline6!.color!,
);
Flushbar<void>? _progressBar;
@override
Widget build(BuildContext context) {
final themeData = Theme.of(context);
return DropdownButton<WalletListItem>(
items: widget.walletListViewModel.wallets
.map((wallet) => DropdownMenuItem(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: walletListItemTile(wallet),
),
return Observer(builder: (context) {
final dropDownItems = [
...widget.walletListViewModel.wallets
.map((wallet) => DesktopDropdownItem(
isSelected: wallet.isCurrent,
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: DropDownItemWidget(
title: wallet.name,
image: wallet.isEnabled ? _imageFor(type: wallet.type) : nonWalletTypeIcon),
),
onSelected: () => _onSelectedWallet(wallet),
))
.toList(),
DesktopDropdownItem(
onSelected: () => _navigateToCreateWallet(),
child: DropDownItemWidget(
title: S.of(context).create_new,
image: _getNewWalletImage(context),
),
),
DesktopDropdownItem(
onSelected: () => _navigateToRestoreWallet(),
child: DropDownItemWidget(
title: S.of(context).restore_wallet,
image: _getRestoreWalletImage(context),
),
),
];
return DropdownButton<DesktopDropdownItem>(
items: dropDownItems
.map(
(wallet) => DropdownMenuItem<DesktopDropdownItem>(
child: wallet.child,
value: wallet,
))
.toList(),
onChanged: (selectedWallet) async {
if (selectedWallet!.isCurrent || !selectedWallet.isEnabled) {
return;
}
final confirmed = await showPopUp<bool>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).change_wallet_alert_title,
alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () => Navigator.of(context).pop(false),
actionRightButton: () => Navigator.of(context).pop(true));
}) ??
false;
if (confirmed) {
await _loadWallet(selectedWallet);
}
},
dropdownColor: themeData.textTheme.bodyText1?.decorationColor,
style: TextStyle(color: themeData.primaryTextTheme.headline6?.color),
selectedItemBuilder: (context) => widget.walletListViewModel.wallets
.map((wallet) => ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: walletListItemTile(wallet),
))
.toList(),
value: widget.walletListViewModel.wallets.firstWhere((element) => element.isCurrent),
underline: const SizedBox(),
focusColor: Colors.transparent,
);
),
)
.toList(),
onChanged: (item) {
item?.onSelected();
},
dropdownColor: themeData.textTheme.bodyText1?.decorationColor,
style: TextStyle(color: themeData.primaryTextTheme.headline6?.color),
selectedItemBuilder: (context) => dropDownItems.map((item) => item.child).toList(),
value: dropDownItems.firstWhere((element) => element.isSelected),
underline: const SizedBox(),
focusColor: Colors.transparent,
);
});
}
Widget walletListItemTile(WalletListItem wallet) {
return Container(
height: tileHeight,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
wallet.isEnabled ? _imageFor(type: wallet.type) : nonWalletTypeIcon,
SizedBox(width: 10),
Flexible(
child: Text(
wallet.name,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.headline6!.color!,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
)
],
),
);
void _onSelectedWallet(WalletListItem selectedWallet) async {
if (selectedWallet.isCurrent || !selectedWallet.isEnabled) {
return;
}
final confirmed = await showPopUp<bool>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).change_wallet_alert_title,
alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () => Navigator.of(context).pop(false),
actionRightButton: () => Navigator.of(context).pop(true));
}) ??
false;
if (confirmed) {
await _loadWallet(selectedWallet);
}
}
Image _imageFor({required WalletType type}) {
@ -152,6 +167,24 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
}
}
void _navigateToCreateWallet() {
if (isSingleCoin) {
Navigator.of(context)
.pushNamed(Routes.newWallet, arguments: widget.walletListViewModel.currentWalletType);
} else {
Navigator.of(context).pushNamed(Routes.newWalletType);
}
}
void _navigateToRestoreWallet() {
if (isSingleCoin) {
Navigator.of(context)
.pushNamed(Routes.restoreWallet, arguments: widget.walletListViewModel.currentWalletType);
} else {
Navigator.of(context).pushNamed(Routes.restoreWalletType);
}
}
void changeProcessText(String text) {
_progressBar = createBar<void>(text, duration: null)..show(context);
}

View file

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
class DropDownItemWidget extends StatelessWidget {
const DropDownItemWidget({super.key, required this.title, required this.image});
final double tileHeight = 60;
final Image image;
final String title;
@override
Widget build(BuildContext context) {
return Container(
height: tileHeight,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
image,
SizedBox(width: 10),
Flexible(
child: Text(
title,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.headline6!.color!,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
)
],
),
);
}
}

View file

@ -16,7 +16,8 @@ class DesktopSettingsPage extends StatefulWidget {
}
class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
final int itemCount = SettingActions.all.length;
final int itemCount = SettingActions.desktopSettings.length;
int? currentPage;
void _onItemChange(int index) {
@ -48,8 +49,8 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
child: ListView.separated(
padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) {
final item = SettingActions.all[index];
final isLastTile = index == itemCount;
final item = SettingActions.desktopSettings[index];
final isLastTile = index == itemCount - 1;
return SettingActionButton(
isLastTile: isLastTile,
selectionActive: currentPage != null,

View file

@ -234,7 +234,7 @@ class WalletListBodyState extends State<WalletListBody> {
auth.hideProgressText();
auth.close();
WidgetsBinding.instance.addPostFrameCallback((_) {
navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
Navigator.of(context).pop();
});
} catch (e) {
auth.changeProcessText(
@ -246,7 +246,7 @@ class WalletListBodyState extends State<WalletListBody> {
changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
await widget.walletListViewModel.loadWallet(wallet);
hideProgressText();
navigatorKey.currentState!.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
Navigator.of(context).pop();
} catch (e) {
changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
}

View file

@ -1,3 +1,6 @@
import 'dart:io';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
@ -100,7 +103,8 @@ class AddressTextField extends StatelessWidget {
width: prefixIconWidth * options.length +
(spaceBetweenPrefixIcons * options.length),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: DeviceInfo.instance.isMobile
? MainAxisAlignment.spaceBetween : MainAxisAlignment.end,
children: [
SizedBox(width: 5),
if (this.options.contains(AddressTextFieldOption.paste)) ...[
@ -130,7 +134,8 @@ class AddressTextField extends StatelessWidget {
)),
)),
],
if (this.options.contains(AddressTextFieldOption.qrCode)) ...[
if (this.options.contains(AddressTextFieldOption.qrCode) && DeviceInfo.instance.isMobile)
...[
Container(
width: prefixIconWidth,
height: prefixIconHeight,
@ -156,7 +161,7 @@ class AddressTextField extends StatelessWidget {
.decorationColor!,
)),
))
],
] else SizedBox(width: 5),
if (this
.options
.contains(AddressTextFieldOption.addressBook)) ...[

View file

@ -24,6 +24,16 @@ class SettingActions {
supportSettingAction,
];
static List<SettingActions> desktopSettings = [
connectionSettingAction,
addressBookSettingAction,
securityBackupSettingAction,
privacySettingAction,
displaySettingAction,
otherSettingAction,
supportSettingAction,
];
static SettingActions connectionSettingAction = SettingActions._(
name: S.current.connection_sync,
image: 'assets/images/nodes_menu.png',

View file

@ -0,0 +1,11 @@
import 'dart:io';
class DeviceInfo {
DeviceInfo._();
static DeviceInfo get instance => DeviceInfo._();
bool get isMobile => Platform.isAndroid || Platform.isIOS;
bool get isDesktop => Platform.isMacOS || Platform.isWindows || Platform.isLinux;
}

View file

@ -1,13 +1,13 @@
import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_type.dart';
class WalletListItem {
const WalletListItem(
{required this.name,
required this.type,
required this.key,
this.isCurrent = false,
this.isEnabled = true});
const WalletListItem({
required this.name,
required this.type,
required this.key,
this.isCurrent = false,
this.isEnabled = true,
});
final String name;
final WalletType type;

View file

@ -1,5 +1,9 @@
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/di.dart';
@ -22,6 +26,7 @@ abstract class WalletListViewModelBase with Store {
this._authService,
) : wallets = ObservableList<WalletListItem>() {
_updateList();
reaction((_) => _appStore.wallet, (_) => _updateList());
}
@observable