Merge pull request #477 from cypherstack/ui-fixes

UI fixes
This commit is contained in:
Diego Salazar 2023-04-13 15:53:17 -06:00 committed by GitHub
commit 6c2d669f46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 801 additions and 704 deletions

View file

@ -134,9 +134,10 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
),
);
} else {
contract = await Navigator.of(context).pushNamed(
final result = await Navigator.of(context).pushNamed(
AddCustomTokenView.routeName,
);
contract = result as EthContract?;
}
if (contract != null) {
@ -442,16 +443,26 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
},
),
actions: [
AspectRatio(
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 20,
),
child: AspectRatio(
aspectRatio: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AppBarIconButton(
size: 36,
shadows: const [],
color:
Theme.of(context).extension<StackColors>()!.background,
icon: SvgPicture.asset(
Assets.svg.circlePlusFilled,
color: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
width: 20,
height: 20,
),
onPressed: _addToken,
),

View file

@ -857,7 +857,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
height: isDesktop ? 20 : 12,
),
SizedBox(
height: 60,
height: isDesktop ? 60 : 40,
child: RateTypeToggle(
key: UniqueKey(),
onChanged: onRateTypeChanged,

View file

@ -358,13 +358,15 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null)
if (feeObject == null &&
manager.coin != Coin.ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null)
if (feeObject != null &&
manager.coin != Coin.ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(
@ -490,13 +492,15 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null)
if (feeObject == null &&
manager.coin != Coin.ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null)
if (feeObject != null &&
manager.coin != Coin.ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(
@ -622,13 +626,15 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null)
if (feeObject == null &&
manager.coin != Coin.ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null)
if (feeObject != null &&
manager.coin != Coin.ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(

View file

@ -0,0 +1,149 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.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 AppearanceSettingsView extends ConsumerWidget {
const AppearanceSettingsView({Key? key}) : super(key: key);
static const String routeName = "/appearanceSettings";
@override
Widget build(BuildContext context, WidgetRef ref) {
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"Appearance",
style: STextStyles.navBarTitle(context),
),
),
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(
child: Consumer(
builder: (_, ref, __) {
return RawMaterialButton(
splashColor: Theme.of(context)
.extension<StackColors>()!
.highlight,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"Display favorite wallets",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
SizedBox(
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: ref.watch(
prefsChangeNotifierProvider.select(
(value) =>
value.showFavoriteWallets),
),
onValueChanged: (newValue) {
ref
.read(
prefsChangeNotifierProvider)
.showFavoriteWallets = newValue;
},
),
)
],
),
),
);
},
),
),
const SizedBox(
height: 10,
),
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: RawMaterialButton(
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
padding: const EdgeInsets.all(0),
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Choose Theme",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
const Padding(
padding: EdgeInsets.all(10),
child: ThemeOptionsWidget(),
),
],
),
],
),
),
),
),
],
),
),
),
);
},
),
),
),
);
}
}

View file

@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
class ThemeOption<T> extends StatelessWidget {
const ThemeOption({
Key? key,
required this.onPressed,
required this.onChanged,
required this.label,
required this.value,
required this.groupValue,
}) : super(key: key);
final VoidCallback onPressed;
final void Function(Object?) onChanged;
final String label;
final T value;
final T groupValue;
@override
Widget build(BuildContext context) {
return MaterialButton(
splashColor: Colors.transparent,
hoverColor: Colors.transparent,
padding: const EdgeInsets.all(0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: onPressed,
child: SizedBox(
width: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
SizedBox(
width: 20,
height: 20,
child: Radio<T>(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: value,
groupValue: groupValue,
onChanged: onChanged,
),
),
const SizedBox(
width: 14,
),
Text(
label,
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.textDark2,
),
),
],
),
],
),
),
);
}
}

View file

@ -0,0 +1,200 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
class ThemeOptionsWidget extends ConsumerStatefulWidget {
const ThemeOptionsWidget({Key? key}) : super(key: key);
@override
ConsumerState<ThemeOptionsWidget> createState() => _ThemeOptionsWidgetState();
}
class _ThemeOptionsWidgetState extends ConsumerState<ThemeOptionsWidget> {
final systemDefault = ThemeType.values.length;
late int _current;
void setTheme(int index) {
if (index == _current) {
return;
}
if (index == systemDefault) {
// update current index
_current = index;
// enable system brightness setting
ref.read(prefsChangeNotifierProvider).enableSystemBrightness = true;
// get theme
final ThemeType theme;
switch (MediaQuery.of(context).platformBrightness) {
case Brightness.dark:
theme = ref
.read(prefsChangeNotifierProvider.notifier)
.systemBrightnessDarkTheme;
break;
case Brightness.light:
theme = ref
.read(prefsChangeNotifierProvider.notifier)
.systemBrightnessLightTheme;
break;
}
// apply theme
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
theme.colorTheme,
);
Assets.precache(context);
} else {
if (_current == systemDefault) {
// disable system brightness setting
ref.read(prefsChangeNotifierProvider).enableSystemBrightness = false;
}
// update current index
_current = index;
// get theme
final theme = ThemeType.values[index];
// save theme setting
ref.read(prefsChangeNotifierProvider.notifier).theme = theme;
// apply theme
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
theme.colorTheme,
);
Assets.precache(context);
}
}
@override
void initState() {
if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) {
_current = ThemeType.values.length;
} else {
_current =
ThemeType.values.indexOf(ref.read(prefsChangeNotifierProvider).theme);
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
MaterialButton(
splashColor: Colors.transparent,
hoverColor: Colors.transparent,
padding: const EdgeInsets.all(0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: () {
setTheme(systemDefault);
},
child: SizedBox(
width: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 26,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: ThemeType.values.length,
groupValue: _current,
onChanged: (newValue) {
if (newValue is int) {
setTheme(newValue);
}
},
),
),
const SizedBox(
width: 14,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"System default",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark2,
),
),
const SizedBox(
height: 2,
),
CustomTextButton(
text: "Options",
onTap: () {
Navigator.of(context).pushNamed(
SystemBrightnessThemeSelectionView.routeName,
);
},
),
],
),
],
),
],
),
),
),
const SizedBox(
height: 10,
),
for (int i = 0; i < ThemeType.values.length; i++)
ConditionalParent(
condition: i > 0,
builder: (child) => Padding(
padding: const EdgeInsets.only(top: 10),
child: child,
),
child: ThemeOption(
label: ThemeType.values[i].prettyName,
onPressed: () {
setTheme(i);
},
onChanged: (newValue) {
if (newValue is int) {
setTheme(newValue);
}
},
value: i,
groupValue: _current,
),
),
],
);
}
}

View file

@ -0,0 +1,216 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class SystemBrightnessThemeSelectionView extends ConsumerWidget {
const SystemBrightnessThemeSelectionView({
Key? key,
}) : super(key: key);
static const String routeName = "/chooseSystemTheme";
void _setTheme({
required BuildContext context,
required bool isDark,
required ThemeType type,
required WidgetRef ref,
}) {
final brightness = MediaQuery.of(context).platformBrightness;
if (isDark) {
ref.read(prefsChangeNotifierProvider).systemBrightnessDarkTheme = type;
if (brightness == Brightness.dark) {
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
type.colorTheme,
);
}
} else {
ref.read(prefsChangeNotifierProvider).systemBrightnessLightTheme = type;
if (brightness == Brightness.light) {
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
type.colorTheme,
);
}
}
}
@override
Widget build(BuildContext context, WidgetRef ref) {
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"System default theme",
style: STextStyles.navBarTitle(context),
),
),
body: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 16,
),
RoundedWhiteContainer(
child: Text(
"Select a light and dark theme that will be"
" activated automatically when your phone system"
" switches light and dark mode.",
style: STextStyles.smallMed12(context),
),
),
const SizedBox(
height: 10,
),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose dark mode theme",
style: STextStyles.titleBold12(context),
),
const SizedBox(
height: 18,
),
for (int i = 0;
i < (2 * ThemeType.values.length) - 1;
i++)
(i % 2 == 1)
? const SizedBox(
height: 10,
)
: ThemeOption(
label:
ThemeType.values[i ~/ 2].prettyName,
onPressed: () {
_setTheme(
context: context,
isDark: false,
type: ThemeType.values[i ~/ 2],
ref: ref,
);
},
onChanged: (newValue) {
final value =
ThemeType.values[i ~/ 2];
if (newValue == value &&
ref
.read(
prefsChangeNotifierProvider)
.systemBrightnessLightTheme !=
value) {
_setTheme(
context: context,
isDark: false,
type: value,
ref: ref,
);
}
},
value: ThemeType.values[i ~/ 2],
groupValue: ref.watch(
prefsChangeNotifierProvider.select(
(value) => value
.systemBrightnessLightTheme)),
),
],
),
),
const SizedBox(
height: 10,
),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose dark mode theme",
style: STextStyles.titleBold12(context),
),
const SizedBox(
height: 18,
),
for (int i = 0;
i < (2 * ThemeType.values.length) - 1;
i++)
(i % 2 == 1)
? const SizedBox(
height: 10,
)
: ThemeOption(
label:
ThemeType.values[i ~/ 2].prettyName,
onPressed: () {
_setTheme(
context: context,
isDark: true,
type: ThemeType.values[i ~/ 2],
ref: ref,
);
},
onChanged: (newValue) {
final value =
ThemeType.values[i ~/ 2];
if (newValue == value &&
ref
.read(
prefsChangeNotifierProvider)
.systemBrightnessDarkTheme !=
value) {
_setTheme(
context: context,
isDark: true,
type: value,
ref: ref,
);
}
},
value: ThemeType.values[i ~/ 2],
groupValue: ref.watch(
prefsChangeNotifierProvider.select(
(value) => value
.systemBrightnessDarkTheme)),
),
],
),
),
const SizedBox(
height: 16,
),
],
),
),
),
),
);
},
),
),
);
}
}

View file

@ -1,628 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.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/expandable.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:tuple/tuple.dart';
class AppearanceSettingsView extends ConsumerWidget {
const AppearanceSettingsView({Key? key}) : super(key: key);
static const String routeName = "/appearanceSettings";
@override
Widget build(BuildContext context, WidgetRef ref) {
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"Appearance",
style: STextStyles.navBarTitle(context),
),
),
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(
child: Consumer(
builder: (_, ref, __) {
return RawMaterialButton(
splashColor: Theme.of(context)
.extension<StackColors>()!
.highlight,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"Display favorite wallets",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
SizedBox(
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: ref.watch(
prefsChangeNotifierProvider.select(
(value) =>
value.showFavoriteWallets),
),
onValueChanged: (newValue) {
ref
.read(
prefsChangeNotifierProvider)
.showFavoriteWallets = newValue;
},
),
)
],
),
),
);
},
),
),
const SizedBox(
height: 10,
),
const SystemBrightnessToggle(),
if (!ref.watch(
prefsChangeNotifierProvider
.select((value) => value.enableSystemBrightness),
))
const SizedBox(
height: 10,
),
if (!ref.watch(
prefsChangeNotifierProvider
.select((value) => value.enableSystemBrightness),
))
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: RawMaterialButton(
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
padding: const EdgeInsets.all(0),
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Choose Theme",
style:
STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
const Padding(
padding: EdgeInsets.all(10),
child: ThemeOptionsView(),
),
],
),
],
),
),
),
),
],
),
),
),
);
},
),
),
),
);
}
}
class SystemBrightnessToggle extends ConsumerStatefulWidget {
const SystemBrightnessToggle({Key? key}) : super(key: key);
@override
ConsumerState<SystemBrightnessToggle> createState() =>
_SystemBrightnessToggleState();
}
class _SystemBrightnessToggleState
extends ConsumerState<SystemBrightnessToggle> {
final controller = ExpandableController();
void _toggle(bool enable) {
ref.read(prefsChangeNotifierProvider).enableSystemBrightness = enable;
if (enable && controller.state == ExpandableState.collapsed) {
controller.toggle?.call();
} else if (!enable && controller.state == ExpandableState.expanded) {
controller.toggle?.call();
}
if (enable) {
final ThemeType type;
switch (MediaQuery.of(context).platformBrightness) {
case Brightness.dark:
type = ref
.read(prefsChangeNotifierProvider.notifier)
.systemBrightnessDarkTheme;
break;
case Brightness.light:
type = ref
.read(prefsChangeNotifierProvider.notifier)
.systemBrightnessLightTheme;
break;
}
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
type.colorTheme,
);
} else {
ref.read(prefsChangeNotifierProvider.notifier).theme =
ref.read(colorThemeProvider.notifier).state.themeType;
}
}
@override
void initState() {
if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) {
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.toggle?.call();
});
}
super.initState();
}
@override
Widget build(BuildContext context) {
final enable = ref.watch(
prefsChangeNotifierProvider
.select((value) => value.enableSystemBrightness),
);
return RoundedWhiteContainer(
child: Expandable(
controller: controller,
expandOverride: () {
_toggle(
!ref.read(prefsChangeNotifierProvider).enableSystemBrightness);
},
header: RawMaterialButton(
splashColor: Theme.of(context).extension<StackColors>()!.highlight,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"System brightness",
style: STextStyles.titleBold12(context),
textAlign: TextAlign.left,
),
SizedBox(
key: Key("${enable}enableSystemBrightnessToggleKey"),
height: 20,
width: 40,
child: DraggableSwitchButton(
isOn: enable,
onValueChanged: _toggle,
),
)
],
),
),
),
body: Column(
children: [
RoundedContainer(
color: Colors.transparent,
padding: EdgeInsets.zero,
onPressed: () async {
final result = await Navigator.of(context).pushNamed(
SystemBrightnessThemeSelectionView.routeName,
arguments: Tuple2(
"light",
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightTheme),
);
if (result is ThemeType) {
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightTheme = result;
if (ref
.read(prefsChangeNotifierProvider)
.enableSystemBrightness) {
if (mounted &&
MediaQuery.of(context).platformBrightness ==
Brightness.light) {
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(result.colorTheme);
}
}
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Light theme",
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
height: 2,
),
Text(
ref
.watch(
prefsChangeNotifierProvider.select((value) =>
value.systemBrightnessLightTheme),
)
.prettyName,
style: STextStyles.itemSubtitle12(context),
),
],
),
),
SvgPicture.asset(
Assets.svg.chevronRight,
color: Theme.of(context).extension<StackColors>()!.textDark,
),
],
),
),
RoundedContainer(
color: Colors.transparent,
padding: EdgeInsets.zero,
onPressed: () async {
final result = await Navigator.of(context).pushNamed(
SystemBrightnessThemeSelectionView.routeName,
arguments: Tuple2(
"dark",
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessDarkTheme),
);
if (result is ThemeType) {
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessDarkTheme = result;
if (ref
.read(prefsChangeNotifierProvider)
.enableSystemBrightness) {
if (mounted &&
MediaQuery.of(context).platformBrightness ==
Brightness.dark) {
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(result.colorTheme);
}
}
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Dark theme",
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
height: 2,
),
Text(
ref.watch(
prefsChangeNotifierProvider.select((value) =>
value.systemBrightnessDarkTheme.prettyName),
),
style: STextStyles.itemSubtitle12(context),
),
],
),
),
SvgPicture.asset(
Assets.svg.chevronRight,
color: Theme.of(context).extension<StackColors>()!.textDark,
),
],
),
)
],
),
),
);
}
}
class ThemeOptionsView extends ConsumerWidget {
const ThemeOptionsView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Column(
children: [
for (int i = 0; i < (2 * ThemeType.values.length) - 1; i++)
(i % 2 == 1)
? const SizedBox(
height: 10,
)
: ThemeOption(
onPressed: () {
ref.read(prefsChangeNotifierProvider.notifier).theme =
ThemeType.values[i ~/ 2];
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
ThemeType.values[i ~/ 2].colorTheme,
);
Assets.precache(context);
},
onChanged: (newValue) {
if (newValue == ThemeType.values[i ~/ 2]) {
ref.read(prefsChangeNotifierProvider.notifier).theme =
ThemeType.values[i ~/ 2];
ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
ThemeType.values[i ~/ 2].colorTheme,
);
Assets.precache(context);
}
},
value: ThemeType.values[i ~/ 2],
groupValue:
Theme.of(context).extension<StackColors>()!.themeType,
),
],
);
}
}
class ThemeOption extends StatelessWidget {
const ThemeOption(
{Key? key,
required this.onPressed,
required this.onChanged,
required this.value,
required this.groupValue})
: super(key: key);
final VoidCallback onPressed;
final void Function(Object?) onChanged;
final ThemeType value;
final ThemeType groupValue;
@override
Widget build(BuildContext context) {
return MaterialButton(
splashColor: Colors.transparent,
hoverColor: Colors.transparent,
padding: const EdgeInsets.all(0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: onPressed,
child: SizedBox(
width: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
SizedBox(
width: 10,
height: 10,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: value,
groupValue: groupValue,
onChanged: onChanged,
),
),
const SizedBox(
width: 14,
),
Text(
value.prettyName,
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.textDark2,
),
),
],
),
],
),
),
);
}
}
class SystemBrightnessThemeSelectionView extends StatelessWidget {
const SystemBrightnessThemeSelectionView({
Key? key,
required this.brightness,
required this.current,
}) : super(key: key);
final String brightness;
final ThemeType current;
static const String routeName = "/chooseSystemTheme";
@override
Widget build(BuildContext context) {
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"Choose $brightness theme",
style: STextStyles.navBarTitle(context),
),
),
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: RawMaterialButton(
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
padding: const EdgeInsets.all(0),
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: null,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Column(
children: [
for (int i = 0;
i <
(2 *
ThemeType.values
.length) -
1;
i++)
(i % 2 == 1)
? const SizedBox(
height: 10,
)
: ThemeOption(
onPressed: () {
Navigator.of(context)
.pop(ThemeType
.values[
i ~/ 2]);
},
onChanged: (newValue) {
if (newValue ==
ThemeType.values[
i ~/ 2]) {
Navigator.of(context)
.pop(ThemeType
.values[
i ~/ 2]);
}
},
value: ThemeType
.values[i ~/ 2],
groupValue: current,
),
],
),
),
],
),
],
),
),
),
),
],
),
),
),
);
},
),
),
),
);
}
}

View file

@ -5,7 +5,7 @@ import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/delete_account_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/language_view.dart';

View file

@ -100,10 +100,10 @@ class _MyTokensViewState extends ConsumerState<MyTokensView> {
color:
Theme.of(context).extension<StackColors>()!.background,
icon: SvgPicture.asset(
Assets.svg.circlePlusDark,
Assets.svg.circlePlusFilled,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
.topNavIconPrimary,
width: 20,
height: 20,
),

View file

@ -19,6 +19,11 @@ import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/animated_text.dart';
final tokenFeeSessionCacheProvider =
ChangeNotifierProvider<FeeSheetSessionCache>((ref) {
return FeeSheetSessionCache();
});
class DesktopFeeDropDown extends ConsumerStatefulWidget {
const DesktopFeeDropDown({
Key? key,
@ -54,7 +59,12 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
}) async {
switch (feeRateType) {
case FeeRateType.fast:
if (ref.read(feeSheetSessionCacheProvider).fast[amount] == null) {
if (ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.fast[amount] ==
null) {
if (widget.isToken == false) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId);
@ -76,13 +86,22 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
} else {
final tokenWallet = ref.read(tokenServiceProvider)!;
final fee = tokenWallet.estimateFeeFor(feeRate);
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
ref.read(tokenFeeSessionCacheProvider).fast[amount] = fee;
}
}
return ref.read(feeSheetSessionCacheProvider).fast[amount]!;
return ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.fast[amount]!;
case FeeRateType.average:
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
if (ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.average[amount] ==
null) {
if (widget.isToken == false) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId);
@ -104,13 +123,22 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
} else {
final tokenWallet = ref.read(tokenServiceProvider)!;
final fee = tokenWallet.estimateFeeFor(feeRate);
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
ref.read(tokenFeeSessionCacheProvider).average[amount] = fee;
}
}
return ref.read(feeSheetSessionCacheProvider).average[amount]!;
return ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.average[amount]!;
case FeeRateType.slow:
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
if (ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.slow[amount] ==
null) {
if (widget.isToken == false) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId);
@ -132,10 +160,14 @@ class _DesktopFeeDropDownState extends ConsumerState<DesktopFeeDropDown> {
} else {
final tokenWallet = ref.read(tokenServiceProvider)!;
final fee = tokenWallet.estimateFeeFor(feeRate);
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
ref.read(tokenFeeSessionCacheProvider).slow[amount] = fee;
}
}
return ref.read(feeSheetSessionCacheProvider).slow[amount]!;
return ref
.read(widget.isToken
? tokenFeeSessionCacheProvider
: feeSheetSessionCacheProvider)
.slow[amount]!;
}
}

View file

@ -9,7 +9,6 @@ import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart';
import 'package:stackwallet/pages/token_view/token_view.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
@ -416,7 +415,7 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
.read(walletsChangeNotifierProvider)
.getManager(walletId)
.validateAddress(address ?? "");
ref.read(previewTxButtonStateProvider.state).state =
ref.read(previewTokenTxButtonStateProvider.state).state =
(isValidAddress && amount != null && amount > Amount.zero);
}
@ -574,8 +573,8 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.refresh(feeSheetSessionCacheProvider);
ref.read(previewTxButtonStateProvider.state).state = false;
ref.refresh(tokenFeeSessionCacheProvider);
ref.read(previewTokenTxButtonStateProvider.state).state = false;
});
// _calculateFeesFuture = calculateFees(0);
@ -605,21 +604,25 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
_cryptoFocus.addListener(() {
if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_amountToSend == null) {
ref.refresh(sendAmountProvider);
} else {
ref.read(sendAmountProvider.state).state = _amountToSend!;
}
});
}
});
_baseFocus.addListener(() {
if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_amountToSend == null) {
ref.refresh(sendAmountProvider);
} else {
ref.read(sendAmountProvider.state).state = _amountToSend!;
}
});
}
});
@ -1064,8 +1067,8 @@ class _DesktopTokenSendState extends ConsumerState<DesktopTokenSend> {
PrimaryButton(
buttonHeight: ButtonHeight.l,
label: "Preview send",
enabled: ref.watch(previewTxButtonStateProvider.state).state,
onPressed: ref.watch(previewTxButtonStateProvider.state).state
enabled: ref.watch(previewTokenTxButtonStateProvider.state).state,
onPressed: ref.watch(previewTokenTxButtonStateProvider.state).state
? previewSend
: null,
)

View file

@ -1,12 +1,9 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
int _count = 0;
final previewTxButtonStateProvider = StateProvider.autoDispose<bool>((_) {
if (kDebugMode) {
_count++;
}
return false;
});
final previewTokenTxButtonStateProvider = StateProvider.autoDispose<bool>((_) {
return false;
});

View file

@ -0,0 +1,60 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/logger.dart';
class ContractWalletId implements Equatable {
final String walletId;
final String tokenContractAddress;
ContractWalletId({
required this.walletId,
required this.tokenContractAddress,
});
@override
List<Object?> get props => [walletId, tokenContractAddress];
@override
bool? get stringify => true;
}
/// provide the wallet for a given wallet id
final walletProvider =
ChangeNotifierProvider.family<Manager?, String>((ref, arg) => null);
/// provide the token wallet given a contract address and eth wallet id
final tokenWalletProvider =
ChangeNotifierProvider.family<EthTokenWallet?, ContractWalletId>(
(ref, arg) {
final ethWallet =
ref.watch(walletProvider(arg.walletId).select((value) => value?.wallet))
as EthereumWallet?;
final contract =
ref.read(mainDBProvider).getEthContractSync(arg.tokenContractAddress);
if (ethWallet == null || contract == null) {
Logging.instance.log(
"Attempted to access a token wallet with walletId=${arg.walletId} where"
" contractAddress=${arg.tokenContractAddress}",
level: LogLevel.Warning,
);
return null;
}
final secureStore = ref.watch(secureStoreProvider);
return EthTokenWallet(
token: contract,
ethWallet: ethWallet,
secureStore: secureStore,
tracker: TransactionNotificationTracker(
walletId: arg.walletId,
),
);
});

View file

@ -63,7 +63,8 @@ import 'package:stackwallet/pages/send_view/token_send_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/delete_account_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart';
@ -147,7 +148,6 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:tuple/tuple.dart';
class RouteGenerator {
@ -761,19 +761,13 @@ class RouteGenerator {
return _routeError("${settings.name} invalid args: ${args.toString()}");
case SystemBrightnessThemeSelectionView.routeName:
if (args is Tuple2<String, ThemeType>) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => SystemBrightnessThemeSelectionView(
brightness: args.item1,
current: args.item2,
),
builder: (_) => const SystemBrightnessThemeSelectionView(),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case WalletNetworkSettingsView.routeName:
if (args is Tuple3<String, WalletSyncStatus, NodeConnectionStatus>) {

View file

@ -23,20 +23,6 @@ abstract class DefaultTokens {
decimals: 18,
type: EthContractType.erc20,
),
EthContract(
address: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52",
name: "BNB Token",
symbol: "BNB",
decimals: 18,
type: EthContractType.erc20,
),
EthContract(
address: "0x4Fabb145d64652a948d72533023f6E7A623C7C53",
name: "BUSD",
symbol: "BUSD",
decimals: 18,
type: EthContractType.erc20,
),
EthContract(
address: "0x514910771af9ca656af840dff83e8264ecf986ca",
name: "Chainlink",