add load into selected wallet immediately on startup setting

This commit is contained in:
julian 2022-09-09 10:51:34 -06:00
parent 4eccef774e
commit 9229aa4ce3
7 changed files with 583 additions and 18 deletions

View file

@ -589,9 +589,16 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
_loadChangeNowData();
}
return const LockscreenView(
String? startupWalletId;
if (ref.read(prefsChangeNotifierProvider).gotoWalletOnStartup) {
startupWalletId =
ref.read(prefsChangeNotifierProvider).startupWalletId;
}
return LockscreenView(
isInitialAppLogin: true,
routeOnSuccess: HomeView.routeName,
routeOnSuccessArguments: startupWalletId,
biometricsAuthenticationTitle: "Unlock Stack",
biometricsLocalizedReason:
"Unlock your stack wallet using biometrics",

View file

@ -1,9 +1,14 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/home_view/home_view.dart';
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
// import 'package:stackwallet/providers/global/has_authenticated_start_state_provider.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
// import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/biometrics.dart';
@ -15,6 +20,7 @@ import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_pin_put/custom_pin_put.dart';
import 'package:stackwallet/widgets/shake/shake.dart';
import 'package:tuple/tuple.dart';
class LockscreenView extends ConsumerStatefulWidget {
const LockscreenView({
@ -75,10 +81,20 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
if (widget.popOnSuccess) {
Navigator.of(context).pop(widget.routeOnSuccessArguments);
} else {
Navigator.of(context).pushReplacementNamed(
unawaited(Navigator.of(context).pushReplacementNamed(
widget.routeOnSuccess,
arguments: widget.routeOnSuccessArguments,
);
));
if (widget.routeOnSuccess == HomeView.routeName &&
widget.routeOnSuccessArguments is String) {
final walletId = widget.routeOnSuccessArguments as String;
unawaited(Navigator.of(context).pushNamed(WalletView.routeName,
arguments: Tuple2(
walletId,
ref
.read(walletsChangeNotifierProvider)
.getManagerProvider(walletId))));
}
}
}
@ -105,7 +121,7 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
// await walletsService.getWalletId(currentWalletName));
// }
_onUnlock();
unawaited(_onUnlock());
}
// leave this commented to enable pin fall back should biometrics not work properly
// else {
@ -250,10 +266,10 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
_timeout = const Duration(minutes: 60);
}
Future<void>.delayed(_timeout).then((_) {
unawaited(Future<void>.delayed(_timeout).then((_) {
_attemptLock = false;
_attempts = 0;
});
}));
}
if (_attemptLock) {
@ -264,13 +280,13 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
prettyTime += "${_timeout.inSeconds} seconds";
}
showFloatingFlushBar(
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message:
"Incorrect PIN entered too many times. Please wait $prettyTime",
context: context,
iconAsset: Assets.svg.alertCircle,
);
));
await Future<void>.delayed(
const Duration(milliseconds: 100));
@ -286,15 +302,15 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
if (storedPin == pin) {
await Future<void>.delayed(
const Duration(milliseconds: 200));
_onUnlock();
unawaited(_onUnlock());
} else {
_shakeController.shake();
showFloatingFlushBar(
unawaited(_shakeController.shake());
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Incorrect PIN. Please try again",
context: context,
iconAsset: Assets.svg.alertCircle,
);
));
await Future<void>.delayed(
const Duration(milliseconds: 100));

View file

@ -9,6 +9,7 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/language_v
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/security_views/security_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/startup_preferences/startup_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/support_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/sub_widgets/settings_list_button.dart';
@ -166,6 +167,18 @@ class GlobalSettingsView extends StatelessWidget {
const SizedBox(
height: 8,
),
SettingsListButton(
iconAssetName: Assets.svg.arrowUpRight,
iconSize: 16,
title: "Startup",
onPressed: () {
Navigator.of(context).pushNamed(
StartupPreferencesView.routeName);
},
),
const SizedBox(
height: 8,
),
SettingsListButton(
iconAssetName: Assets.svg.sun,
iconSize: 18,

View file

@ -0,0 +1,269 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class StartupPreferencesView extends ConsumerStatefulWidget {
const StartupPreferencesView({Key? key}) : super(key: key);
static const String routeName = "/startupPreferences";
@override
ConsumerState<StartupPreferencesView> createState() =>
_StartupPreferencesViewState();
}
class _StartupPreferencesViewState
extends ConsumerState<StartupPreferencesView> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: CFColors.almostWhite,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"Startup preferences",
style: STextStyles.navBarTitle,
),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: RawMaterialButton(
// splashColor: CFColors.splashLight,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: () {
ref
.read(prefsChangeNotifierProvider)
.gotoWalletOnStartup = false;
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: CFColors.link2,
value: false,
groupValue: ref.watch(
prefsChangeNotifierProvider
.select((value) => value
.gotoWalletOnStartup),
),
onChanged: (value) {
if (value is bool) {
ref
.read(
prefsChangeNotifierProvider)
.gotoWalletOnStartup = value;
}
},
),
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Home screen",
style: STextStyles.titleBold12,
textAlign: TextAlign.left,
),
Text(
"Stack Wallet home screen",
style: STextStyles.itemSubtitle,
textAlign: TextAlign.left,
),
],
),
),
],
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(4),
child: RawMaterialButton(
// splashColor: CFColors.splashLight,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: () {
ref
.read(prefsChangeNotifierProvider)
.gotoWalletOnStartup = true;
},
child: Container(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: CFColors.link2,
value: true,
groupValue: ref.watch(
prefsChangeNotifierProvider
.select((value) => value
.gotoWalletOnStartup),
),
onChanged: (value) {
if (value is bool) {
ref
.read(
prefsChangeNotifierProvider)
.gotoWalletOnStartup = value;
}
},
),
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Specific wallet",
style: STextStyles.titleBold12,
textAlign: TextAlign.left,
),
Text(
"Select a specific wallet to load into on startup",
style: STextStyles.itemSubtitle,
textAlign: TextAlign.left,
),
],
),
),
],
),
),
),
),
),
if (!ref.watch(prefsChangeNotifierProvider
.select((value) => value.gotoWalletOnStartup)))
const SizedBox(
height: 12,
),
if (ref.watch(prefsChangeNotifierProvider
.select((value) => value.gotoWalletOnStartup)))
Container(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.only(
left: 12.0,
right: 12,
bottom: 12,
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const SizedBox(
width: 12 + 20,
height: 12,
),
Flexible(
child: RawMaterialButton(
// splashColor: CFColors.splashLight,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants
.size.circularBorderRadius,
),
),
onPressed: () {
Navigator.of(context).pushNamed(
StartupWalletSelectionView
.routeName);
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Select wallet...",
style: STextStyles.link2,
textAlign: TextAlign.left,
),
],
),
),
),
],
),
),
),
],
),
),
],
),
),
),
);
},
),
),
);
}
}

View file

@ -0,0 +1,197 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class StartupWalletSelectionView extends ConsumerStatefulWidget {
const StartupWalletSelectionView({Key? key}) : super(key: key);
static const String routeName = "/startupWalletSelection";
@override
ConsumerState<StartupWalletSelectionView> createState() =>
_StartupWalletSelectionViewState();
}
class _StartupWalletSelectionViewState
extends ConsumerState<StartupWalletSelectionView> {
final Map<String, DSBController> _controllers = {};
@override
Widget build(BuildContext context) {
final managers = ref
.watch(walletsChangeNotifierProvider.select((value) => value.managers));
_controllers.clear();
for (final manager in managers) {
_controllers[manager.walletId] = DSBController();
}
return Scaffold(
backgroundColor: CFColors.almostWhite,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
"Select startup wallet",
style: STextStyles.navBarTitle,
),
),
),
body: LayoutBuilder(builder: (context, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 4,
),
Text(
"Select a wallet to load into immediately on startup",
style: STextStyles.smallMed12,
),
const SizedBox(
height: 12,
),
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: Column(
children: [
...managers.map(
(manager) => Padding(
padding: const EdgeInsets.all(12),
child: Row(
key: Key(
"startupWalletSelectionGroupKey_${manager.walletId}"),
children: [
Container(
decoration: BoxDecoration(
color: CFColors.coin
.forCoin(manager.coin)
.withOpacity(0.5),
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
Assets.svg
.iconFor(coin: manager.coin),
width: 20,
height: 20,
),
),
),
const SizedBox(
width: 12,
),
Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
manager.walletName,
style: STextStyles.titleBold12,
),
// const SizedBox(
// height: 2,
// ),
// FutureBuilder(
// future: manager.totalBalance,
// builder: (builderContext,
// AsyncSnapshot<Decimal> snapshot) {
// if (snapshot.connectionState ==
// ConnectionState.done &&
// snapshot.hasData) {
// return Text(
// "${Format.localizedStringAsFixed(
// value: snapshot.data!,
// locale: ref.watch(
// localeServiceChangeNotifierProvider
// .select((value) =>
// value.locale)),
// decimalPlaces: 8,
// )} ${manager.coin.ticker}",
// style: STextStyles.itemSubtitle,
// );
// } else {
// return AnimatedText(
// stringsToLoopThrough: const [
// "Loading balance",
// "Loading balance.",
// "Loading balance..",
// "Loading balance..."
// ],
// style: STextStyles.itemSubtitle,
// );
// }
// },
// ),
],
),
const Spacer(),
SizedBox(
height: 20,
width: 20,
child: Radio(
activeColor: CFColors.link2,
value: manager.walletId,
groupValue: ref.watch(
prefsChangeNotifierProvider.select(
(value) => value.startupWalletId),
),
onChanged: (value) {
if (value is String) {
ref
.read(
prefsChangeNotifierProvider)
.startupWalletId = value;
}
},
),
),
],
),
),
),
],
),
),
],
),
),
),
),
),
);
}),
);
}
}

View file

@ -56,6 +56,8 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_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/startup_preferences/startup_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/support_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
@ -224,6 +226,18 @@ class RouteGenerator {
builder: (_) => const SyncingPreferencesView(),
settings: RouteSettings(name: settings.name));
case StartupPreferencesView.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => const StartupPreferencesView(),
settings: RouteSettings(name: settings.name));
case StartupWalletSelectionView.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => const StartupWalletSelectionView(),
settings: RouteSettings(name: settings.name));
case ManageNodesView.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,

View file

@ -34,6 +34,8 @@ class Prefs extends ChangeNotifier {
_backupFrequencyType = await _getBackupFrequencyType();
_lastAutoBackup = await _getLastAutoBackup();
_hideBlockExplorerWarning = await _getHideBlockExplorerWarning();
_gotoWalletOnStartup = await _getGotoWalletOnStartup();
_startupWalletId = await _getStartupWalletId();
_initialized = true;
}
@ -468,8 +470,6 @@ class Prefs extends ChangeNotifier {
boxName: DB.boxNamePrefs, key: "autoBackupFileUri") as DateTime?;
}
// auto backup
bool _hideBlockExplorerWarning = false;
@ -480,9 +480,9 @@ class Prefs extends ChangeNotifier {
if (_hideBlockExplorerWarning != hideBlockExplorerWarning) {
DB.instance
.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "hideBlockExplorerWarning",
value: hideBlockExplorerWarning)
boxName: DB.boxNamePrefs,
key: "hideBlockExplorerWarning",
value: hideBlockExplorerWarning)
.then((_) {
_hideBlockExplorerWarning = hideBlockExplorerWarning;
notifyListeners();
@ -492,7 +492,56 @@ class Prefs extends ChangeNotifier {
Future<bool> _getHideBlockExplorerWarning() async {
return await DB.instance.get<dynamic>(
boxName: DB.boxNamePrefs, key: "hideBlockExplorerWarning") as bool? ??
boxName: DB.boxNamePrefs,
key: "hideBlockExplorerWarning") as bool? ??
false;
}
// auto backup
bool _gotoWalletOnStartup = false;
bool get gotoWalletOnStartup => _gotoWalletOnStartup;
set gotoWalletOnStartup(bool gotoWalletOnStartup) {
if (_gotoWalletOnStartup != gotoWalletOnStartup) {
DB.instance
.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "gotoWalletOnStartup",
value: gotoWalletOnStartup)
.then((_) {
_gotoWalletOnStartup = gotoWalletOnStartup;
notifyListeners();
});
}
}
Future<bool> _getGotoWalletOnStartup() async {
return await DB.instance.get<dynamic>(
boxName: DB.boxNamePrefs, key: "gotoWalletOnStartup") as bool? ??
false;
}
// startup wallet id
String? _startupWalletId;
String? get startupWalletId => _startupWalletId;
set startupWalletId(String? startupWalletId) {
if (this.startupWalletId != startupWalletId) {
DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs,
key: "startupWalletId",
value: startupWalletId);
_startupWalletId = startupWalletId;
notifyListeners();
}
}
Future<String?> _getStartupWalletId() async {
return await DB.instance.get<dynamic>(
boxName: DB.boxNamePrefs, key: "startupWalletId") as String?;
}
}