Merge pull request #211 from cypherstack/desktop

Desktop
This commit is contained in:
Rylee Davis 2022-11-09 17:45:45 -07:00 committed by GitHub
commit 23d2de26d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 737 additions and 130 deletions

View file

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
@ -315,42 +316,45 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
}
bool shouldPop = false;
await showDialog<dynamic>(
barrierDismissible: false,
context: context,
builder: (_) => WillPopScope(
onWillPop: () async {
return shouldPop;
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Material(
color: Colors.transparent,
child: Center(
child: Text(
"Decrypting Stack backup file",
style:
STextStyles.pageTitleH2(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textWhite,
unawaited(
showDialog<dynamic>(
barrierDismissible: false,
context: context,
builder: (_) => WillPopScope(
onWillPop: () async {
return shouldPop;
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Material(
color: Colors.transparent,
child: Center(
child: Text(
"Decrypting Stack backup file",
style: STextStyles.pageTitleH2(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textWhite,
),
),
),
),
),
const SizedBox(
height: 64,
),
const Center(
child: LoadingIndicator(
width: 100,
const SizedBox(
height: 64,
),
),
],
const Center(
child: LoadingIndicator(
width: 100,
),
),
],
),
),
),
);
@ -424,43 +428,47 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
}
bool shouldPop = false;
await showDialog<dynamic>(
barrierDismissible: false,
context: context,
builder: (_) => WillPopScope(
onWillPop: () async {
return shouldPop;
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Material(
color: Colors.transparent,
child: Center(
child: Text(
"Decrypting Stack backup file",
style: STextStyles.pageTitleH2(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textWhite,
unawaited(
showDialog<dynamic>(
barrierDismissible: false,
context: context,
builder: (_) => WillPopScope(
onWillPop: () async {
return shouldPop;
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Material(
color: Colors.transparent,
child: Center(
child: Text(
"Decrypting Stack backup file",
style:
STextStyles.pageTitleH2(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textWhite,
),
),
),
),
),
const SizedBox(
height: 64,
),
const Center(
child: LoadingIndicator(
width: 100,
const SizedBox(
height: 64,
),
),
],
const Center(
child: LoadingIndicator(
width: 100,
),
),
],
),
),
),
);
@ -475,7 +483,10 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
if (mounted) {
// pop LoadingIndicator
shouldPop = true;
Navigator.of(context).pop();
Navigator.of(
context,
rootNavigator: true,
).pop();
passwordController.text = "";

View file

@ -0,0 +1,139 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
class DesktopAddressBook extends ConsumerStatefulWidget {
const DesktopAddressBook({Key? key}) : super(key: key);
static const String routeName = "/desktopAddressBook";
@override
ConsumerState<DesktopAddressBook> createState() => _DesktopAddressBook();
}
class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
late final TextEditingController _searchController;
late final FocusNode _searchFocusNode;
String filter = "";
@override
void initState() {
_searchController = TextEditingController();
_searchFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final hasWallets = ref.watch(walletsChangeNotifierProvider).hasWallets;
return Column(
mainAxisSize: MainAxisSize.min,
children: [
DesktopAppBar(
isCompactHeight: true,
leading: Row(
children: [
const SizedBox(
width: 24,
),
Text(
"Address Book",
style: STextStyles.desktopH3(context),
)
],
),
),
const SizedBox(height: 53),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Row(
children: [
SizedBox(
height: 60,
width: 489,
child: ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
autocorrect: false,
enableSuggestions: false,
controller: _searchController,
focusNode: _searchFocusNode,
onChanged: (newString) {
setState(() => filter = newString);
},
style: STextStyles.field(context),
decoration: standardInputDecoration(
"Search...",
_searchFocusNode,
context,
).copyWith(
labelStyle: STextStyles.fieldLabel(context)
.copyWith(fontSize: 16),
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 16,
),
child: SvgPicture.asset(
Assets.svg.search,
width: 16,
height: 16,
),
),
suffixIcon: _searchController.text.isNotEmpty
? Padding(
padding: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
_searchController.text = "";
filter = "";
});
},
),
],
),
),
)
: null,
),
),
),
),
],
),
),
// Expanded(
// child: hasWallets ? const MyWallets() : const EmptyWallets(),
// ),
],
);
}
}

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages_desktop_specific/home/address_book_view/desktop_address_book.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_menu.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
@ -31,8 +32,10 @@ class _DesktopHomeViewState extends ConsumerState<DesktopHomeView> {
Container(
color: Colors.red,
),
Container(
color: Colors.orange,
const Navigator(
key: Key("desktopAddressBookHomeKey"),
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: DesktopAddressBook.routeName,
),
const Navigator(
key: Key("desktopSettingHomeKey"),

View file

@ -2,15 +2,27 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:intl/intl.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/backup_and_restore/enable_backup_dialog.dart';
import 'package:stackwallet/providers/global/locale_provider.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../providers/global/auto_swb_service_provider.dart';
import '../../../../widgets/custom_buttons/blue_text_button.dart';
class BackupRestoreSettings extends ConsumerStatefulWidget {
const BackupRestoreSettings({Key? key}) : super(key: key);
@ -24,6 +36,49 @@ class BackupRestoreSettings extends ConsumerStatefulWidget {
class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
late bool createBackup = false;
late bool restoreBackup = false;
// late bool isEnabledAutoBackup;
final toggleController = DSBController();
late final TextEditingController fileLocationController;
late final TextEditingController passwordController;
late final TextEditingController frequencyController;
late final FocusNode fileLocationFocusNode;
late final FocusNode passwordFocusNode;
String prettySinceLastBackupString(DateTime? time) {
if (time == null) {
return "-";
}
final difference = DateTime.now().difference(time);
int value;
String postfix;
if (difference < const Duration(seconds: 60)) {
value = difference.inSeconds;
postfix = "seconds";
} else if (difference < const Duration(minutes: 60)) {
value = difference.inMinutes;
postfix = "minutes";
} else if (difference < const Duration(hours: 24)) {
value = difference.inHours;
postfix = "hours";
} else if (difference.inDays < 8) {
value = difference.inDays;
postfix = "days";
} else {
// if greater than a week return the actual date
return DateFormat.yMMMMd(
ref.read(localeServiceChangeNotifierProvider).locale)
.format(time);
}
if (value == 1) {
postfix = postfix.substring(0, postfix.length - 1);
}
return "$value $postfix ago";
}
Future<void> enableAutoBackup(BuildContext context) async {
await showDialog<dynamic>(
@ -36,10 +91,105 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
);
}
Future<void> attemptDisable() async {
final result = await showDialog<bool?>(
context: context,
useSafeArea: false,
barrierDismissible: true,
builder: (context) {
return StackDialog(
title: "Disable Auto Backup",
message:
"You are turning off Auto Backup. You can turn it back on at any time. Your previous Auto Backup file will not be deleted. Remember to backup your wallets manually so you don't lose important information.",
leftButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Back",
style: STextStyles.button(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.accentColorDark,
),
),
onPressed: () {
Navigator.of(context).pop();
},
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
child: Text(
"Disable",
style: STextStyles.button(context),
),
onPressed: () {
Navigator.of(context).pop();
setState(() {
ref.watch(prefsChangeNotifierProvider).isAutoBackupEnabled =
false;
});
},
),
);
},
);
if (mounted) {
if (result is bool && result) {
ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled = false;
Navigator.of(context).pop();
} else {
toggleController.activate?.call();
}
}
}
@override
void initState() {
fileLocationController = TextEditingController();
passwordController = TextEditingController();
frequencyController = TextEditingController();
passwordController.text = "---------------";
fileLocationController.text =
ref.read(prefsChangeNotifierProvider).autoBackupLocation ?? " ";
frequencyController.text = Format.prettyFrequencyType(
ref.read(prefsChangeNotifierProvider).backupFrequencyType);
fileLocationFocusNode = FocusNode();
passwordFocusNode = FocusNode();
// _toggle = ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled;
super.initState();
}
@override
void dispose() {
fileLocationController.dispose();
passwordController.dispose();
frequencyController.dispose();
fileLocationFocusNode.dispose();
passwordFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
bool isEnabledAutoBackup = ref.watch(prefsChangeNotifierProvider
.select((value) => value.isAutoBackupEnabled));
ref.listen(
prefsChangeNotifierProvider
.select((value) => value.backupFrequencyType),
(previous, BackupFrequencyType next) {
frequencyController.text = Format.prettyFrequencyType(next);
});
return LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
@ -120,17 +270,80 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(
10,
),
child: PrimaryButton(
desktopMed: true,
width: 200,
label: "Enable auto backup",
onPressed: () {
enableAutoBackup(context);
},
),
padding: const EdgeInsets.all(10),
child: !isEnabledAutoBackup
? PrimaryButton(
desktopMed: true,
width: 200,
label: "Enable auto backup",
onPressed: () {
enableAutoBackup(context);
},
)
: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
width: 403,
color: Theme.of(context)
.extension<StackColors>()!
.background,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
"Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}",
style: STextStyles
.itemSubtitle(
context),
),
BlueTextButton(
text: "Back up now",
onTap: () {
ref
.read(
autoSWBServiceProvider)
.doBackup();
},
),
],
),
],
),
),
),
const SizedBox(
height: 20,
),
Row(
children: [
PrimaryButton(
desktopMed: true,
width: 190,
label: "Disable auto backup",
onPressed: () {
attemptDisable();
},
),
const SizedBox(width: 16),
SecondaryButton(
desktopMed: true,
width: 190,
label: "Edit auto backup",
onPressed: () {},
),
],
)
],
),
),
],
),

View file

@ -1,12 +1,24 @@
import 'dart:convert';
import 'dart:io';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/helpers/stack_file_system.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/enums/log_level_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
@ -16,21 +28,31 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/progress_bar.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:zxcvbn/zxcvbn.dart';
class CreateAutoBackup extends StatefulWidget {
const CreateAutoBackup({Key? key}) : super(key: key);
class CreateAutoBackup extends ConsumerStatefulWidget {
const CreateAutoBackup({
Key? key,
this.secureStore = const SecureStorageWrapper(
FlutterSecureStorage(),
),
}) : super(key: key);
final FlutterSecureStorageInterface secureStore;
@override
State<StatefulWidget> createState() => _CreateAutoBackup();
ConsumerState<CreateAutoBackup> createState() => _CreateAutoBackup();
}
class _CreateAutoBackup extends State<CreateAutoBackup> {
class _CreateAutoBackup extends ConsumerState<CreateAutoBackup> {
late final TextEditingController fileLocationController;
late final TextEditingController passphraseController;
late final TextEditingController passphraseRepeatController;
late final FlutterSecureStorageInterface secureStore;
late final StackFileSystem stackFileSystem;
late final FocusNode passphraseFocusNode;
late final FocusNode passphraseRepeatFocusNode;
@ -52,16 +74,18 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
bool get fieldsMatch =>
passphraseController.text == passphraseRepeatController.text;
String _currentDropDownValue = "Every 10 minutes";
BackupFrequencyType _currentDropDownValue =
BackupFrequencyType.everyTenMinutes;
final List<String> _dropDownItems = [
"Every 10 minutes",
"Every 20 minutes",
"Every 30 minutes",
final List<BackupFrequencyType> _dropDownItems = [
BackupFrequencyType.everyTenMinutes,
BackupFrequencyType.everyAppStart,
BackupFrequencyType.afterClosingAWallet,
];
@override
void initState() {
secureStore = widget.secureStore;
stackFileSystem = StackFileSystem();
fileLocationController = TextEditingController();
@ -101,6 +125,9 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType ");
bool isEnabledAutoBackup = ref.watch(prefsChangeNotifierProvider
.select((value) => value.isAutoBackupEnabled));
String? selectedItem = "Every 10 minutes";
final isDesktop = Util.isDesktop;
return DesktopDialog(
@ -225,9 +252,7 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
paste: false,
selectAll: false,
),
onChanged: (newValue) {
// ref.read(addressEntryDataProvider(widget.id)).address = newValue;
},
onChanged: (newValue) {},
),
);
}),
@ -361,7 +386,7 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
),
child: ProgressBar(
key: const Key("createStackBackUpProgressBar"),
width: 510,
width: 512,
height: 5,
fillColor: passwordStrength < 0.51
? Theme.of(context)
@ -465,38 +490,83 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
left: 32,
right: 32,
),
child: DropdownButtonFormField(
isExpanded: true,
elevation: 0,
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,
),
icon: SvgPicture.asset(
Assets.svg.chevronDown,
width: 10,
height: 5,
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
dropdownColor:
Theme.of(context).extension<StackColors>()!.textFieldActiveBG,
// focusColor: ,
value: _currentDropDownValue,
items: _dropDownItems
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(e),
child: isDesktop
? DropdownButtonHideUnderline(
child: DropdownButton2(
offset: Offset(0, -10),
isExpanded: true,
dropdownElevation: 0,
value: _currentDropDownValue,
items: [
..._dropDownItems.map(
(e) {
String message = "";
switch (e) {
case BackupFrequencyType.everyTenMinutes:
message = "Every 10 minutes";
break;
case BackupFrequencyType.everyAppStart:
message = "Every app startup";
break;
case BackupFrequencyType.afterClosingAWallet:
message =
"After closing a cryptocurrency wallet";
break;
}
return DropdownMenuItem(
value: e,
child: Text(message),
);
},
),
],
onChanged: (value) {
if (value is BackupFrequencyType) {
if (ref
.read(prefsChangeNotifierProvider)
.backupFrequencyType !=
value) {
ref
.read(prefsChangeNotifierProvider)
.backupFrequencyType = value;
}
setState(() {
_currentDropDownValue = value;
});
}
},
icon: SvgPicture.asset(
Assets.svg.chevronDown,
width: 10,
height: 5,
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
buttonPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
buttonDecoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
dropdownDecoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
),
)
.toList(),
onChanged: (value) {
if (value is String) {
setState(() {
_currentDropDownValue = value;
});
}
},
),
: null,
),
const Spacer(),
Padding(
@ -518,8 +588,164 @@ class _CreateAutoBackup extends State<CreateAutoBackup> {
Expanded(
child: PrimaryButton(
label: "Enable Auto Backup",
enabled: false,
onPressed: () {},
enabled: shouldEnableCreate,
onPressed: !shouldEnableCreate
? null
: () async {
final String pathToSave =
fileLocationController.text;
final String passphrase = passphraseController.text;
final String repeatPassphrase =
passphraseRepeatController.text;
if (pathToSave.isEmpty) {
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Directory not chosen",
context: context,
);
return;
}
if (!(await Directory(pathToSave).exists())) {
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Directory does not exist",
context: context,
);
return;
}
if (passphrase.isEmpty) {
showFloatingFlushBar(
type: FlushBarType.warning,
message: "A passphrase is required",
context: context,
);
return;
}
if (passphrase != repeatPassphrase) {
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Passphrase does not match",
context: context,
);
return;
}
showDialog<dynamic>(
context: context,
barrierDismissible: false,
builder: (_) => const StackDialog(
title: "Encrypting initial backup",
message: "This shouldn't take long",
),
);
// make sure the dialog is able to be displayed for at least some time
final fut = Future<void>.delayed(
const Duration(milliseconds: 300));
String adkString;
int adkVersion;
try {
final adk =
await compute(generateAdk, passphrase);
adkString = Format.uint8listToString(adk.item2);
adkVersion = adk.item1;
} on Exception catch (e, s) {
String err = getErrorMessageFromSWBException(e);
Logging.instance
.log("$err\n$s", level: LogLevel.Error);
// pop encryption progress dialog
Navigator.of(context).pop();
showFloatingFlushBar(
type: FlushBarType.warning,
message: err,
context: context,
);
return;
} catch (e, s) {
Logging.instance
.log("$e\n$s", level: LogLevel.Error);
// pop encryption progress dialog
Navigator.of(context).pop();
showFloatingFlushBar(
type: FlushBarType.warning,
message: "$e",
context: context,
);
return;
}
await secureStore.write(
key: "auto_adk_string", value: adkString);
await secureStore.write(
key: "auto_adk_version_string",
value: adkVersion.toString());
final DateTime now = DateTime.now();
final String fileToSave =
createAutoBackupFilename(pathToSave, now);
final backup = await SWB.createStackWalletJSON();
bool result = await SWB.encryptStackWalletWithADK(
fileToSave,
adkString,
jsonEncode(backup),
adkVersion: adkVersion,
);
// this future should already be complete unless there was an error encrypting
await Future.wait([fut]);
if (mounted) {
// pop encryption progress dialog
int count = 0;
Navigator.of(context)
.popUntil((_) => count++ >= 2);
if (result) {
ref
.read(prefsChangeNotifierProvider)
.autoBackupLocation = pathToSave;
ref
.read(prefsChangeNotifierProvider)
.lastAutoBackup = now;
ref
.read(prefsChangeNotifierProvider)
.isAutoBackupEnabled = true;
await showDialog<dynamic>(
context: context,
barrierDismissible: false,
builder: (_) => Platform.isAndroid
? StackOkDialog(
title:
"Stack Auto Backup enabled and saved to:",
message: fileToSave,
)
: const StackOkDialog(
title: "Stack Auto Backup enabled!"),
);
if (mounted) {
passphraseController.text = "";
passphraseRepeatController.text = "";
int count = 0;
Navigator.of(context)
.popUntil((_) => count++ >= 2);
}
} else {
await showDialog<dynamic>(
context: context,
barrierDismissible: false,
builder: (_) => const StackOkDialog(
title: "Failed to enable Auto Backup"),
);
}
}
},
),
)
],

View file

@ -86,6 +86,7 @@ import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/pages/wallets_view/wallets_view.dart';
import 'package:stackwallet/pages_desktop_specific/create_password/create_password_view.dart';
import 'package:stackwallet/pages_desktop_specific/forgot_password_desktop_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/address_book_view/desktop_address_book.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
@ -1105,6 +1106,12 @@ class RouteGenerator {
builder: (_) => const DesktopAboutView(),
settings: RouteSettings(name: settings.name));
case DesktopAddressBook.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => const DesktopAddressBook(),
settings: RouteSettings(name: settings.name));
case WalletKeysDesktopPopup.routeName:
if (args is List<String>) {
return FadePageRoute(

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
class StackDialogBase extends StatelessWidget {
const StackDialogBase({
@ -17,7 +18,8 @@ class StackDialogBase extends StatelessWidget {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment:
!Util.isDesktop ? MainAxisAlignment.end : MainAxisAlignment.center,
children: [
Material(
borderRadius: BorderRadius.circular(
@ -179,10 +181,16 @@ class StackOkDialog extends StatelessWidget {
),
Expanded(
child: TextButton(
onPressed: () {
Navigator.of(context).pop();
onOkPressed?.call("OK");
},
onPressed: !Util.isDesktop
? () {
Navigator.of(context).pop();
onOkPressed?.call("OK");
}
: () {
int count = 0;
Navigator.of(context).popUntil((_) => count++ >= 2);
// onOkPressed?.call("OK");
},
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.5.14+86
version: 1.5.16+88
environment:
sdk: ">=2.17.0 <3.0.0"