mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-16 17:27:39 +00:00
desktop forgot password flow and functionality
This commit is contained in:
parent
6a17ddffdf
commit
7436709fa7
11 changed files with 813 additions and 115 deletions
122
lib/hive/db.dart
122
lib/hive/db.dart
|
@ -40,8 +40,6 @@ class DB {
|
||||||
String boxNameUsedSerialsCache({required Coin coin}) =>
|
String boxNameUsedSerialsCache({required Coin coin}) =>
|
||||||
"${coin.name}_usedSerialsCache";
|
"${coin.name}_usedSerialsCache";
|
||||||
|
|
||||||
static bool _initialized = false;
|
|
||||||
|
|
||||||
Box<dynamic>? _boxAddressBook;
|
Box<dynamic>? _boxAddressBook;
|
||||||
Box<String>? _boxDebugInfo;
|
Box<String>? _boxDebugInfo;
|
||||||
Box<NodeModel>? _boxNodeModels;
|
Box<NodeModel>? _boxNodeModels;
|
||||||
|
@ -88,69 +86,65 @@ class DB {
|
||||||
|
|
||||||
// open hive boxes
|
// open hive boxes
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
if (!_initialized) {
|
if (Hive.isBoxOpen(boxNameDBInfo)) {
|
||||||
if (Hive.isBoxOpen(boxNameDBInfo)) {
|
_boxDBInfo = Hive.box<dynamic>(boxNameDBInfo);
|
||||||
_boxDBInfo = Hive.box<dynamic>(boxNameDBInfo);
|
} else {
|
||||||
} else {
|
_boxDBInfo = await Hive.openBox<dynamic>(boxNameDBInfo);
|
||||||
_boxDBInfo = await Hive.openBox<dynamic>(boxNameDBInfo);
|
|
||||||
}
|
|
||||||
await Hive.openBox<String>(boxNameWalletsToDeleteOnStart);
|
|
||||||
|
|
||||||
if (Hive.isBoxOpen(boxNamePrefs)) {
|
|
||||||
_boxPrefs = Hive.box<dynamic>(boxNamePrefs);
|
|
||||||
} else {
|
|
||||||
_boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
_boxAddressBook = await Hive.openBox<dynamic>(boxNameAddressBook);
|
|
||||||
_boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo);
|
|
||||||
|
|
||||||
if (Hive.isBoxOpen(boxNameNodeModels)) {
|
|
||||||
_boxNodeModels = Hive.box<NodeModel>(boxNameNodeModels);
|
|
||||||
} else {
|
|
||||||
_boxNodeModels = await Hive.openBox<NodeModel>(boxNameNodeModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hive.isBoxOpen(boxNamePrimaryNodes)) {
|
|
||||||
_boxPrimaryNodes = Hive.box<NodeModel>(boxNamePrimaryNodes);
|
|
||||||
} else {
|
|
||||||
_boxPrimaryNodes = await Hive.openBox<NodeModel>(boxNamePrimaryNodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hive.isBoxOpen(boxNameAllWalletsData)) {
|
|
||||||
_boxAllWalletsData = Hive.box<dynamic>(boxNameAllWalletsData);
|
|
||||||
} else {
|
|
||||||
_boxAllWalletsData = await Hive.openBox<dynamic>(boxNameAllWalletsData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hive.isBoxOpen(boxNameDesktopData)) {
|
|
||||||
_boxDesktopData = Hive.box<String>(boxNameDesktopData);
|
|
||||||
} else {
|
|
||||||
_boxDesktopData = await Hive.openBox<String>(boxNameDesktopData);
|
|
||||||
}
|
|
||||||
|
|
||||||
_boxNotifications =
|
|
||||||
await Hive.openBox<NotificationModel>(boxNameNotifications);
|
|
||||||
_boxWatchedTransactions =
|
|
||||||
await Hive.openBox<NotificationModel>(boxNameWatchedTransactions);
|
|
||||||
_boxWatchedTrades =
|
|
||||||
await Hive.openBox<NotificationModel>(boxNameWatchedTrades);
|
|
||||||
_boxTrades = await Hive.openBox<ExchangeTransaction>(boxNameTrades);
|
|
||||||
_boxTradesV2 = await Hive.openBox<Trade>(boxNameTradesV2);
|
|
||||||
_boxTradeNotes = await Hive.openBox<String>(boxNameTradeNotes);
|
|
||||||
_boxTradeLookup =
|
|
||||||
await Hive.openBox<TradeWalletLookup>(boxNameTradeLookup);
|
|
||||||
_walletInfoSource =
|
|
||||||
await Hive.openBox<xmr.WalletInfo>(xmr.WalletInfo.boxName);
|
|
||||||
_boxFavoriteWallets = await Hive.openBox<String>(boxNameFavoriteWallets);
|
|
||||||
|
|
||||||
await Future.wait([
|
|
||||||
Hive.openBox<dynamic>(boxNamePriceCache),
|
|
||||||
_loadWalletBoxes(),
|
|
||||||
_loadSharedCoinCacheBoxes(),
|
|
||||||
]);
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
await Hive.openBox<String>(boxNameWalletsToDeleteOnStart);
|
||||||
|
|
||||||
|
if (Hive.isBoxOpen(boxNamePrefs)) {
|
||||||
|
_boxPrefs = Hive.box<dynamic>(boxNamePrefs);
|
||||||
|
} else {
|
||||||
|
_boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_boxAddressBook = await Hive.openBox<dynamic>(boxNameAddressBook);
|
||||||
|
_boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo);
|
||||||
|
|
||||||
|
if (Hive.isBoxOpen(boxNameNodeModels)) {
|
||||||
|
_boxNodeModels = Hive.box<NodeModel>(boxNameNodeModels);
|
||||||
|
} else {
|
||||||
|
_boxNodeModels = await Hive.openBox<NodeModel>(boxNameNodeModels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hive.isBoxOpen(boxNamePrimaryNodes)) {
|
||||||
|
_boxPrimaryNodes = Hive.box<NodeModel>(boxNamePrimaryNodes);
|
||||||
|
} else {
|
||||||
|
_boxPrimaryNodes = await Hive.openBox<NodeModel>(boxNamePrimaryNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hive.isBoxOpen(boxNameAllWalletsData)) {
|
||||||
|
_boxAllWalletsData = Hive.box<dynamic>(boxNameAllWalletsData);
|
||||||
|
} else {
|
||||||
|
_boxAllWalletsData = await Hive.openBox<dynamic>(boxNameAllWalletsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hive.isBoxOpen(boxNameDesktopData)) {
|
||||||
|
_boxDesktopData = Hive.box<String>(boxNameDesktopData);
|
||||||
|
} else {
|
||||||
|
_boxDesktopData = await Hive.openBox<String>(boxNameDesktopData);
|
||||||
|
}
|
||||||
|
|
||||||
|
_boxNotifications =
|
||||||
|
await Hive.openBox<NotificationModel>(boxNameNotifications);
|
||||||
|
_boxWatchedTransactions =
|
||||||
|
await Hive.openBox<NotificationModel>(boxNameWatchedTransactions);
|
||||||
|
_boxWatchedTrades =
|
||||||
|
await Hive.openBox<NotificationModel>(boxNameWatchedTrades);
|
||||||
|
_boxTrades = await Hive.openBox<ExchangeTransaction>(boxNameTrades);
|
||||||
|
_boxTradesV2 = await Hive.openBox<Trade>(boxNameTradesV2);
|
||||||
|
_boxTradeNotes = await Hive.openBox<String>(boxNameTradeNotes);
|
||||||
|
_boxTradeLookup = await Hive.openBox<TradeWalletLookup>(boxNameTradeLookup);
|
||||||
|
_walletInfoSource =
|
||||||
|
await Hive.openBox<xmr.WalletInfo>(xmr.WalletInfo.boxName);
|
||||||
|
_boxFavoriteWallets = await Hive.openBox<String>(boxNameFavoriteWallets);
|
||||||
|
|
||||||
|
await Future.wait([
|
||||||
|
Hive.openBox<dynamic>(boxNamePriceCache),
|
||||||
|
_loadWalletBoxes(),
|
||||||
|
_loadSharedCoinCacheBoxes(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadWalletBoxes() async {
|
Future<void> _loadWalletBoxes() async {
|
||||||
|
|
|
@ -2,12 +2,14 @@ import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/prefs.dart';
|
import 'package:stackwallet/utilities/prefs.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/widgets/background.dart';
|
import 'package:stackwallet/widgets/background.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class IntroView extends StatefulWidget {
|
class IntroView extends StatefulWidget {
|
||||||
|
@ -135,6 +137,20 @@ class _IntroViewState extends State<IntroView> {
|
||||||
GetStartedButton(
|
GetStartedButton(
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
),
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
SecondaryButton(
|
||||||
|
label: "Restore from Stack backup",
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
CreatePasswordView.routeName,
|
||||||
|
arguments: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
const Spacer(
|
const Spacer(
|
||||||
flex: 65,
|
flex: 65,
|
||||||
),
|
),
|
||||||
|
@ -257,7 +273,7 @@ class GetStartedButton extends StatelessWidget {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: SizedBox(
|
: SizedBox(
|
||||||
width: 328,
|
width: double.infinity,
|
||||||
height: 70,
|
height: 70,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
|
@ -270,7 +286,7 @@ class GetStartedButton extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Get started",
|
"Create new Stack",
|
||||||
style: STextStyles.button(context).copyWith(fontSize: 20),
|
style: STextStyles.button(context).copyWith(fontSize: 20),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -12,7 +12,6 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
|
||||||
import 'package:stackwallet/route_generator.dart';
|
import 'package:stackwallet/route_generator.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
|
|
||||||
import 'package:stackwallet/utilities/logger.dart';
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
|
|
@ -9,6 +9,9 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_item_card.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_item_card.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_wallet_card.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_wallet_card.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/desktop_menu.dart';
|
||||||
|
import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart';
|
||||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/providers/stack_restore/stack_restoring_ui_state_provider.dart';
|
import 'package:stackwallet/providers/stack_restore/stack_restoring_ui_state_provider.dart';
|
||||||
|
@ -20,25 +23,23 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
|
import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
|
||||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||||
|
|
||||||
import '../../../../../pages_desktop_specific/desktop_home_view.dart';
|
|
||||||
import '../../../../../pages_desktop_specific/desktop_menu.dart';
|
|
||||||
import '../../../../../providers/desktop/current_desktop_menu_item.dart';
|
|
||||||
import '../../../../../widgets/desktop/primary_button.dart';
|
|
||||||
|
|
||||||
class StackRestoreProgressView extends ConsumerStatefulWidget {
|
class StackRestoreProgressView extends ConsumerStatefulWidget {
|
||||||
const StackRestoreProgressView({
|
const StackRestoreProgressView({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.jsonString,
|
required this.jsonString,
|
||||||
this.fromFile = false,
|
this.fromFile = false,
|
||||||
|
this.shouldPushToHome = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final String jsonString;
|
final String jsonString;
|
||||||
final bool fromFile;
|
final bool fromFile;
|
||||||
|
final bool shouldPushToHome;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<StackRestoreProgressView> createState() =>
|
ConsumerState<StackRestoreProgressView> createState() =>
|
||||||
|
@ -696,11 +697,21 @@ class _StackRestoreProgressViewState
|
||||||
.state)
|
.state)
|
||||||
.state = keyID;
|
.state = keyID;
|
||||||
|
|
||||||
Navigator.of(context, rootNavigator: true)
|
if (widget.shouldPushToHome) {
|
||||||
.popUntil(
|
unawaited(
|
||||||
ModalRoute.withName(
|
Navigator.of(context)
|
||||||
DesktopHomeView.routeName),
|
.pushNamedAndRemoveUntil(
|
||||||
);
|
DesktopHomeView.routeName,
|
||||||
|
(route) => false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context, rootNavigator: true)
|
||||||
|
.popUntil(
|
||||||
|
ModalRoute.withName(
|
||||||
|
DesktopHomeView.routeName),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: SecondaryButton(
|
: SecondaryButton(
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/forgotten_passphrase_restore_from_swb.dart';
|
||||||
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
|
@ -23,9 +24,11 @@ import 'package:zxcvbn/zxcvbn.dart';
|
||||||
class CreatePasswordView extends ConsumerStatefulWidget {
|
class CreatePasswordView extends ConsumerStatefulWidget {
|
||||||
const CreatePasswordView({
|
const CreatePasswordView({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
this.restoreFromSWB = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
static const String routeName = "/createPasswordDesktop";
|
static const String routeName = "/createPasswordDesktop";
|
||||||
|
final bool restoreFromSWB;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<CreatePasswordView> createState() => _CreatePasswordViewState();
|
ConsumerState<CreatePasswordView> createState() => _CreatePasswordViewState();
|
||||||
|
@ -84,7 +87,9 @@ class _CreatePasswordViewState extends ConsumerState<CreatePasswordView> {
|
||||||
|
|
||||||
// load default nodes now as node service requires storage handler to exist
|
// load default nodes now as node service requires storage handler to exist
|
||||||
|
|
||||||
await ref.read(nodeServiceChangeNotifierProvider).updateDefaults();
|
if (!widget.restoreFromSWB) {
|
||||||
|
await ref.read(nodeServiceChangeNotifierProvider).updateDefaults();
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
unawaited(showFloatingFlushBar(
|
unawaited(showFloatingFlushBar(
|
||||||
type: FlushBarType.warning,
|
type: FlushBarType.warning,
|
||||||
|
@ -95,15 +100,28 @@ class _CreatePasswordViewState extends ConsumerState<CreatePasswordView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
unawaited(Navigator.of(context)
|
if (widget.restoreFromSWB) {
|
||||||
.pushReplacementNamed(DesktopHomeView.routeName));
|
unawaited(
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
ForgottenPassphraseRestoreFromSWB.routeName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unawaited(
|
||||||
|
Navigator.of(context).pushReplacementNamed(
|
||||||
|
DesktopHomeView.routeName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unawaited(showFloatingFlushBar(
|
if (!widget.restoreFromSWB) {
|
||||||
type: FlushBarType.success,
|
unawaited(showFloatingFlushBar(
|
||||||
message: "Your password is set up",
|
type: FlushBarType.success,
|
||||||
context: context,
|
message: "Your password is set up",
|
||||||
));
|
context: context,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:stackwallet/hive/db.dart';
|
||||||
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
|
import 'package:stackwallet/pages/intro_view.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
|
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
|
|
||||||
|
class DeletePasswordWarningView extends ConsumerStatefulWidget {
|
||||||
|
const DeletePasswordWarningView({
|
||||||
|
Key? key,
|
||||||
|
required this.shouldCreateNew,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
static const String routeName = "/deletePasswordWarning";
|
||||||
|
|
||||||
|
final bool shouldCreateNew;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<DeletePasswordWarningView> createState() =>
|
||||||
|
_ForgotPasswordDesktopViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ForgotPasswordDesktopViewState
|
||||||
|
extends ConsumerState<DeletePasswordWarningView> {
|
||||||
|
bool _deleteInProgress = false;
|
||||||
|
|
||||||
|
Future<bool> _deleteStack() async {
|
||||||
|
final appRoot = await StackFileSystem.applicationRootDirectory();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Hive.close();
|
||||||
|
await appRoot.delete(recursive: true);
|
||||||
|
await DB.instance.init();
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"$e\n$s",
|
||||||
|
level: LogLevel.Fatal,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DesktopScaffold(
|
||||||
|
appBar: DesktopAppBar(
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (mounted && !_deleteInProgress) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
isCompactHeight: false,
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 480,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.stackIcon(context),
|
||||||
|
width: 100,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 42,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Warning!",
|
||||||
|
style: STextStyles.desktopH1(context),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 480,
|
||||||
|
child: RichText(
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
text: TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: "To ",
|
||||||
|
style: STextStyles.desktopTextSmall(context),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: "create a new Stack",
|
||||||
|
style: STextStyles.desktopTextSmallBold(context),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: ", we need to ",
|
||||||
|
style: STextStyles.desktopTextSmall(context),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: "delete your old wallets",
|
||||||
|
style: STextStyles.desktopTextSmallBold(context),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text:
|
||||||
|
". All wallets will be lost. If you have not written down your recovery phrase for EACH wallet, you may be in danger of losing funds. Continue?",
|
||||||
|
style: STextStyles.desktopTextSmall(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 48,
|
||||||
|
),
|
||||||
|
PrimaryButton(
|
||||||
|
label: "Delete and continue",
|
||||||
|
enabled: !_deleteInProgress,
|
||||||
|
onPressed: () async {
|
||||||
|
final shouldDelete = !_deleteInProgress;
|
||||||
|
setState(() {
|
||||||
|
_deleteInProgress = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (shouldDelete) {
|
||||||
|
unawaited(
|
||||||
|
showFloatingFlushBar(
|
||||||
|
type: FlushBarType.info,
|
||||||
|
message: "Deleting wallet...",
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final success = await _deleteStack();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
await showFloatingFlushBar(
|
||||||
|
type: FlushBarType.success,
|
||||||
|
message: "Wallet deleted",
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
await Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
IntroView.routeName,
|
||||||
|
(_) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await showFloatingFlushBar(
|
||||||
|
type: FlushBarType.warning,
|
||||||
|
message: "Something broke badly. Contact developer",
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_deleteInProgress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
SecondaryButton(
|
||||||
|
label: "Take me back!",
|
||||||
|
enabled: !_deleteInProgress,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: kDesktopAppBarHeight,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/delete_password_warning_view.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
@ -74,18 +75,26 @@ class _ForgotPasswordDesktopViewState extends State<ForgotPasswordDesktopView> {
|
||||||
height: 48,
|
height: 48,
|
||||||
),
|
),
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
label: "Create new wallet",
|
label: "Create new Stack",
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// // todo delete everything and start fresh?
|
const shouldCreateNew = true;
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
DeletePasswordWarningView.routeName,
|
||||||
|
arguments: shouldCreateNew,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
SecondaryButton(
|
SecondaryButton(
|
||||||
label: "Restore from backup",
|
label: "Restore from Stack backup",
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// todo SWB restore
|
const shouldCreateNew = false;
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
DeletePasswordWarningView.routeName,
|
||||||
|
arguments: shouldCreateNew,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
|
|
|
@ -0,0 +1,406 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
import 'package:stackwallet/hive/db.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/swb_file_system.dart';
|
||||||
|
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
||||||
|
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/global/secure_store_provider.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/flutter_secure_storage_interface.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
|
class ForgottenPassphraseRestoreFromSWB extends ConsumerStatefulWidget {
|
||||||
|
const ForgottenPassphraseRestoreFromSWB({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
static const String routeName = "/forgottenPassphraseRestoreFromSWB";
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<ForgottenPassphraseRestoreFromSWB> createState() =>
|
||||||
|
_ForgottenPassphraseRestoreFromSWBState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ForgottenPassphraseRestoreFromSWBState
|
||||||
|
extends ConsumerState<ForgottenPassphraseRestoreFromSWB> {
|
||||||
|
late final TextEditingController fileLocationController;
|
||||||
|
late final TextEditingController passwordController;
|
||||||
|
|
||||||
|
late final FocusNode passwordFocusNode;
|
||||||
|
|
||||||
|
late final SWBFileSystem stackFileSystem;
|
||||||
|
|
||||||
|
bool hidePassword = true;
|
||||||
|
|
||||||
|
bool _enableButton = false;
|
||||||
|
|
||||||
|
Future<void> restore() async {
|
||||||
|
final String fileToRestore = fileLocationController.text;
|
||||||
|
final String passphrase = passwordController.text;
|
||||||
|
|
||||||
|
if (!(await File(fileToRestore).exists())) {
|
||||||
|
await showFloatingFlushBar(
|
||||||
|
type: FlushBarType.warning,
|
||||||
|
message: "Backup file does not exist",
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldPop = false;
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final String? jsonString = await compute(
|
||||||
|
SWB.decryptStackWalletWithPassphrase,
|
||||||
|
Tuple2(fileToRestore, passphrase),
|
||||||
|
debugLabel: "stack wallet decryption compute",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
// pop LoadingIndicator
|
||||||
|
shouldPop = true;
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
passwordController.text = "";
|
||||||
|
|
||||||
|
if (jsonString == null) {
|
||||||
|
await showFloatingFlushBar(
|
||||||
|
type: FlushBarType.warning,
|
||||||
|
message: "Failed to decrypt backup file",
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.read(walletsChangeNotifierProvider);
|
||||||
|
|
||||||
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) {
|
||||||
|
return DesktopDialog(
|
||||||
|
maxWidth: 580,
|
||||||
|
maxHeight: double.infinity,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(32),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Restoring Stack wallet",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 44,
|
||||||
|
),
|
||||||
|
StackRestoreProgressView(
|
||||||
|
jsonString: jsonString,
|
||||||
|
shouldPushToHome: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// await Navigator.of(context).push(
|
||||||
|
// RouteGenerator.getRoute(
|
||||||
|
// builder: (_) => StackRestoreProgressView(
|
||||||
|
// jsonString: jsonString,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
stackFileSystem = SWBFileSystem();
|
||||||
|
fileLocationController = TextEditingController();
|
||||||
|
passwordController = TextEditingController();
|
||||||
|
|
||||||
|
passwordFocusNode = FocusNode();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
fileLocationController.dispose();
|
||||||
|
passwordController.dispose();
|
||||||
|
|
||||||
|
passwordFocusNode.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DesktopScaffold(
|
||||||
|
appBar: DesktopAppBar(
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await (ref.read(secureStoreProvider).store as DesktopSecureStore)
|
||||||
|
.close();
|
||||||
|
ref.refresh(secureStoreProvider);
|
||||||
|
ref.refresh(storageCryptoHandlerProvider);
|
||||||
|
await Hive.deleteBoxFromDisk(DB.boxNameDesktopData);
|
||||||
|
await DB.instance.init();
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context)
|
||||||
|
.popUntil(ModalRoute.withName(CreatePasswordView.routeName));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
isCompactHeight: false,
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 480,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Restore from backup",
|
||||||
|
style: STextStyles.desktopH1(context),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 32,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Use your Stack wallet backup file to restore your wallets, address book, and wallet preferences.",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: STextStyles.desktopTextSmall(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
try {
|
||||||
|
await stackFileSystem.prepareStorage();
|
||||||
|
if (mounted) {
|
||||||
|
await stackFileSystem.openFile(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
fileLocationController.text =
|
||||||
|
stackFileSystem.filePath ?? "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("$e\n$s", level: LogLevel.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: TextField(
|
||||||
|
autocorrect: false,
|
||||||
|
enableSuggestions: false,
|
||||||
|
controller: fileLocationController,
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "Choose file...",
|
||||||
|
hintStyle: STextStyles.desktopTextFieldLabel(context),
|
||||||
|
suffixIcon: SizedBox(
|
||||||
|
height: 70,
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 24,
|
||||||
|
),
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.folder,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark3,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
key: const Key("restoreFromFileLocationTextFieldKey"),
|
||||||
|
readOnly: true,
|
||||||
|
toolbarOptions: const ToolbarOptions(
|
||||||
|
copy: true,
|
||||||
|
cut: false,
|
||||||
|
paste: false,
|
||||||
|
selectAll: false,
|
||||||
|
),
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
_enableButton =
|
||||||
|
passwordController.text.isNotEmpty &&
|
||||||
|
fileLocationController.text.isNotEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
key: const Key("restoreFromFilePasswordFieldKey"),
|
||||||
|
focusNode: passwordFocusNode,
|
||||||
|
controller: passwordController,
|
||||||
|
style: STextStyles.desktopTextMedium(context).copyWith(
|
||||||
|
height: 2,
|
||||||
|
),
|
||||||
|
obscureText: hidePassword,
|
||||||
|
enableSuggestions: false,
|
||||||
|
autocorrect: false,
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Enter passphrase",
|
||||||
|
passwordFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
suffixIcon: UnconstrainedBox(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 70,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 24,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
key: const Key(
|
||||||
|
"restoreFromFilePasswordFieldShowPasswordButtonKey"),
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
hidePassword = !hidePassword;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
hidePassword
|
||||||
|
? Assets.svg.eye
|
||||||
|
: Assets.svg.eyeSlash,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark3,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
_enableButton = passwordController.text.isNotEmpty &&
|
||||||
|
fileLocationController.text.isNotEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
PrimaryButton(
|
||||||
|
label: "Restore",
|
||||||
|
enabled: _enableButton,
|
||||||
|
onPressed: () {
|
||||||
|
restore();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: kDesktopAppBarHeight,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,7 +98,9 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/notifications/desktop_notifications_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/notifications/desktop_notifications_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/delete_password_warning_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/password/forgot_password_desktop_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/password/forgot_password_desktop_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/password/forgotten_passphrase_restore_from_swb.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/settings/desktop_settings_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/settings/desktop_settings_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart';
|
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/appearance_settings.dart';
|
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/appearance_settings.dart';
|
||||||
|
@ -999,6 +1001,17 @@ class RouteGenerator {
|
||||||
|
|
||||||
// == Desktop specific routes ============================================
|
// == Desktop specific routes ============================================
|
||||||
case CreatePasswordView.routeName:
|
case CreatePasswordView.routeName:
|
||||||
|
if (args is bool) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => CreatePasswordView(
|
||||||
|
restoreFromSWB: args,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
return getRoute(
|
return getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
builder: (_) => const CreatePasswordView(),
|
builder: (_) => const CreatePasswordView(),
|
||||||
|
@ -1010,6 +1023,26 @@ class RouteGenerator {
|
||||||
builder: (_) => const ForgotPasswordDesktopView(),
|
builder: (_) => const ForgotPasswordDesktopView(),
|
||||||
settings: RouteSettings(name: settings.name));
|
settings: RouteSettings(name: settings.name));
|
||||||
|
|
||||||
|
case ForgottenPassphraseRestoreFromSWB.routeName:
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => const ForgottenPassphraseRestoreFromSWB(),
|
||||||
|
settings: RouteSettings(name: settings.name));
|
||||||
|
|
||||||
|
case DeletePasswordWarningView.routeName:
|
||||||
|
if (args is bool) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => DeletePasswordWarningView(
|
||||||
|
shouldCreateNew: args,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case DesktopHomeView.routeName:
|
case DesktopHomeView.routeName:
|
||||||
return getRoute(
|
return getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
|
|
@ -997,6 +997,32 @@ class STextStyles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TextStyle desktopTextSmallBold(BuildContext context) {
|
||||||
|
switch (_theme(context).themeType) {
|
||||||
|
case ThemeType.light:
|
||||||
|
return GoogleFonts.inter(
|
||||||
|
color: _theme(context).textDark,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
height: 27 / 18,
|
||||||
|
);
|
||||||
|
case ThemeType.oceanBreeze:
|
||||||
|
return GoogleFonts.inter(
|
||||||
|
color: _theme(context).textDark,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
height: 27 / 18,
|
||||||
|
);
|
||||||
|
case ThemeType.dark:
|
||||||
|
return GoogleFonts.inter(
|
||||||
|
color: _theme(context).buttonTextPrimaryDisabled,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
height: 27 / 18,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static TextStyle desktopTextExtraSmall(BuildContext context) {
|
static TextStyle desktopTextExtraSmall(BuildContext context) {
|
||||||
switch (_theme(context).themeType) {
|
switch (_theme(context).themeType) {
|
||||||
case ThemeType.light:
|
case ThemeType.light:
|
||||||
|
|
45
pubspec.lock
45
pubspec.lock
|
@ -42,7 +42,7 @@ packages:
|
||||||
name: archive
|
name: archive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.11"
|
version: "3.3.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -63,7 +63,7 @@ packages:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.9.0"
|
||||||
barcode_scan2:
|
barcode_scan2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -190,14 +190,7 @@ packages:
|
||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
checked_yaml:
|
checked_yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -218,7 +211,7 @@ packages:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
code_builder:
|
code_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -288,7 +281,7 @@ packages:
|
||||||
name: coverage
|
name: coverage
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.5.0"
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -442,7 +435,7 @@ packages:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -871,21 +864,21 @@ packages:
|
||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.12"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.4"
|
version: "0.1.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.8.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -997,7 +990,7 @@ packages:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
path_drawing:
|
path_drawing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1373,7 +1366,7 @@ packages:
|
||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.9.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1417,7 +1410,7 @@ packages:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
string_validator:
|
string_validator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -1431,35 +1424,35 @@ packages:
|
||||||
name: sync_http
|
name: sync_http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
test:
|
test:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.21.1"
|
version: "1.21.4"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.12"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.13"
|
version: "0.4.16"
|
||||||
time:
|
time:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1508,7 +1501,7 @@ packages:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
universal_io:
|
universal_io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1592,7 +1585,7 @@ packages:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.2.2"
|
version: "9.0.0"
|
||||||
wakelock:
|
wakelock:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Reference in a new issue