mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-25 12:59:24 +00:00
commit
fe44b14453
18 changed files with 1970 additions and 1740 deletions
|
@ -7,13 +7,17 @@ import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.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/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/icon_widgets/x_icon.dart';
|
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||||
|
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import '../../../widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class BaseCurrencySettingsView extends ConsumerStatefulWidget {
|
class BaseCurrencySettingsView extends ConsumerStatefulWidget {
|
||||||
const BaseCurrencySettingsView({Key? key}) : super(key: key);
|
const BaseCurrencySettingsView({Key? key}) : super(key: key);
|
||||||
|
@ -102,31 +106,90 @@ class _CurrencyViewState extends ConsumerState<BaseCurrencySettingsView> {
|
||||||
currenciesWithoutSelected.insert(0, current);
|
currenciesWithoutSelected.insert(0, current);
|
||||||
}
|
}
|
||||||
currenciesWithoutSelected = _filtered();
|
currenciesWithoutSelected = _filtered();
|
||||||
return Scaffold(
|
final isDesktop = Util.isDesktop;
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
|
||||||
appBar: AppBar(
|
return ConditionalParent(
|
||||||
leading: AppBarBackButton(
|
condition: !isDesktop,
|
||||||
onPressed: () async {
|
builder: (child) {
|
||||||
if (FocusScope.of(context).hasFocus) {
|
return Scaffold(
|
||||||
FocusScope.of(context).unfocus();
|
backgroundColor:
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 75));
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
}
|
appBar: AppBar(
|
||||||
if (mounted) {
|
leading: AppBarBackButton(
|
||||||
Navigator.of(context).pop();
|
onPressed: () async {
|
||||||
}
|
if (FocusScope.of(context).hasFocus) {
|
||||||
},
|
FocusScope.of(context).unfocus();
|
||||||
),
|
await Future<void>.delayed(const Duration(milliseconds: 75));
|
||||||
title: Text(
|
}
|
||||||
"Currency",
|
if (mounted) {
|
||||||
style: STextStyles.navBarTitle(context),
|
Navigator.of(context).pop();
|
||||||
),
|
}
|
||||||
),
|
},
|
||||||
body: Padding(
|
),
|
||||||
padding: const EdgeInsets.only(
|
title: Text(
|
||||||
top: 12,
|
"Currency",
|
||||||
left: 16,
|
style: STextStyles.navBarTitle(context),
|
||||||
right: 16,
|
),
|
||||||
),
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 12,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: isDesktop,
|
||||||
|
builder: (child) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
bottom: 32,
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: RoundedWhiteContainer(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
borderColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Cancel",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: Navigator.of(context).pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Save changes",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: Navigator.of(context).pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
floatHeaderSlivers: true,
|
floatHeaderSlivers: true,
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||||
import 'package:stackwallet/models/node_model.dart';
|
import 'package:stackwallet/models/node_model.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/providers/global/node_service_provider.dart';
|
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.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';
|
||||||
|
@ -20,15 +19,18 @@ import 'package:stackwallet/utilities/test_epic_box_connection.dart';
|
||||||
import 'package:stackwallet/utilities/test_monero_node_connection.dart';
|
import 'package:stackwallet/utilities/test_monero_node_connection.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/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/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
|
||||||
|
|
||||||
enum AddEditNodeViewType { add, edit }
|
enum AddEditNodeViewType { add, edit }
|
||||||
|
|
||||||
class AddEditNodeView extends ConsumerStatefulWidget {
|
class AddEditNodeView extends ConsumerStatefulWidget {
|
||||||
|
@ -59,6 +61,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
||||||
late final AddEditNodeViewType viewType;
|
late final AddEditNodeViewType viewType;
|
||||||
late final Coin coin;
|
late final Coin coin;
|
||||||
late final String? nodeId;
|
late final String? nodeId;
|
||||||
|
late final bool isDesktop;
|
||||||
|
|
||||||
late bool saveEnabled;
|
late bool saveEnabled;
|
||||||
late bool testConnectionEnabled;
|
late bool testConnectionEnabled;
|
||||||
|
@ -162,8 +165,198 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
||||||
return testPassed;
|
return testPassed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> attemptSave() async {
|
||||||
|
final canConnect = await _testConnection(showFlushBar: false);
|
||||||
|
|
||||||
|
bool? shouldSave;
|
||||||
|
|
||||||
|
if (!canConnect) {
|
||||||
|
await showDialog<dynamic>(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: true,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (_) => isDesktop
|
||||||
|
? DesktopDialog(
|
||||||
|
maxWidth: 440,
|
||||||
|
maxHeight: 300,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 32,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 32,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Server currently unreachable",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
top: 16,
|
||||||
|
bottom: 32,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
"Would you like to save this node anyways?",
|
||||||
|
style: STextStyles.desktopTextMedium(context),
|
||||||
|
),
|
||||||
|
const Spacer(
|
||||||
|
flex: 2,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Cancel",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: () => Navigator.of(
|
||||||
|
context,
|
||||||
|
rootNavigator: true,
|
||||||
|
).pop(false),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Save",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: () => Navigator.of(
|
||||||
|
context,
|
||||||
|
rootNavigator: true,
|
||||||
|
).pop(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: StackDialog(
|
||||||
|
title: "Server currently unreachable",
|
||||||
|
message: "Would you like to save this node anyways?",
|
||||||
|
leftButton: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
"Cancel",
|
||||||
|
style: STextStyles.button(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.accentColorDark),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
rightButton: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
style: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getPrimaryEnabledButtonColor(context),
|
||||||
|
child: Text(
|
||||||
|
"Save",
|
||||||
|
style: STextStyles.button(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).then((value) {
|
||||||
|
if (value is bool && value) {
|
||||||
|
shouldSave = true;
|
||||||
|
} else {
|
||||||
|
shouldSave = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canConnect && !shouldSave!) {
|
||||||
|
// return without saving
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final formData = ref.read(nodeFormDataProvider);
|
||||||
|
|
||||||
|
// strip unused path
|
||||||
|
String address = formData.host!;
|
||||||
|
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) {
|
||||||
|
if (address.startsWith("http")) {
|
||||||
|
final uri = Uri.parse(address);
|
||||||
|
address = "${uri.scheme}://${uri.host}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (viewType) {
|
||||||
|
case AddEditNodeViewType.add:
|
||||||
|
NodeModel node = NodeModel(
|
||||||
|
host: address,
|
||||||
|
port: formData.port!,
|
||||||
|
name: formData.name!,
|
||||||
|
id: const Uuid().v1(),
|
||||||
|
useSSL: formData.useSSL!,
|
||||||
|
loginName: formData.login,
|
||||||
|
enabled: true,
|
||||||
|
coinName: coin.name,
|
||||||
|
isFailover: formData.isFailover!,
|
||||||
|
isDown: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
await ref.read(nodeServiceChangeNotifierProvider).add(
|
||||||
|
node,
|
||||||
|
formData.password,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context)
|
||||||
|
.popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AddEditNodeViewType.edit:
|
||||||
|
NodeModel node = NodeModel(
|
||||||
|
host: address,
|
||||||
|
port: formData.port!,
|
||||||
|
name: formData.name!,
|
||||||
|
id: nodeId!,
|
||||||
|
useSSL: formData.useSSL!,
|
||||||
|
loginName: formData.login,
|
||||||
|
enabled: true,
|
||||||
|
coinName: coin.name,
|
||||||
|
isFailover: formData.isFailover!,
|
||||||
|
isDown: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
await ref.read(nodeServiceChangeNotifierProvider).add(
|
||||||
|
node,
|
||||||
|
formData.password,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context)
|
||||||
|
.popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
isDesktop = Util.isDesktop;
|
||||||
ref.refresh(nodeFormDataProvider);
|
ref.refresh(nodeFormDataProvider);
|
||||||
|
|
||||||
viewType = widget.viewType;
|
viewType = widget.viewType;
|
||||||
|
@ -196,279 +389,203 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
||||||
.select((value) => value.getNodeById(id: nodeId!)))
|
.select((value) => value.getNodeById(id: nodeId!)))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return Scaffold(
|
return ConditionalParent(
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
condition: !isDesktop,
|
||||||
appBar: AppBar(
|
builder: (child) => Scaffold(
|
||||||
leading: AppBarBackButton(
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
onPressed: () async {
|
appBar: AppBar(
|
||||||
if (FocusScope.of(context).hasFocus) {
|
leading: AppBarBackButton(
|
||||||
FocusScope.of(context).unfocus();
|
onPressed: () async {
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 75));
|
if (FocusScope.of(context).hasFocus) {
|
||||||
}
|
FocusScope.of(context).unfocus();
|
||||||
if (mounted) {
|
await Future<void>.delayed(const Duration(milliseconds: 75));
|
||||||
Navigator.of(context).pop();
|
}
|
||||||
}
|
if (mounted) {
|
||||||
},
|
Navigator.of(context).pop();
|
||||||
),
|
}
|
||||||
title: Text(
|
},
|
||||||
viewType == AddEditNodeViewType.edit ? "Edit node" : "Add node",
|
),
|
||||||
style: STextStyles.navBarTitle(context),
|
title: Text(
|
||||||
),
|
viewType == AddEditNodeViewType.edit ? "Edit node" : "Add node",
|
||||||
actions: [
|
style: STextStyles.navBarTitle(context),
|
||||||
if (viewType == AddEditNodeViewType.edit)
|
),
|
||||||
Padding(
|
actions: [
|
||||||
padding: const EdgeInsets.only(
|
if (viewType == AddEditNodeViewType.edit)
|
||||||
top: 10,
|
Padding(
|
||||||
bottom: 10,
|
padding: const EdgeInsets.only(
|
||||||
right: 10,
|
top: 10,
|
||||||
),
|
bottom: 10,
|
||||||
child: AspectRatio(
|
right: 10,
|
||||||
aspectRatio: 1,
|
),
|
||||||
child: AppBarIconButton(
|
child: AspectRatio(
|
||||||
key: const Key("deleteNodeAppBarButtonKey"),
|
aspectRatio: 1,
|
||||||
size: 36,
|
child: AppBarIconButton(
|
||||||
shadows: const [],
|
key: const Key("deleteNodeAppBarButtonKey"),
|
||||||
color: Theme.of(context).extension<StackColors>()!.background,
|
size: 36,
|
||||||
icon: SvgPicture.asset(
|
shadows: const [],
|
||||||
Assets.svg.trash,
|
color:
|
||||||
color: Theme.of(context)
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
.extension<StackColors>()!
|
icon: SvgPicture.asset(
|
||||||
.accentColorDark,
|
Assets.svg.trash,
|
||||||
width: 20,
|
color: Theme.of(context)
|
||||||
height: 20,
|
.extension<StackColors>()!
|
||||||
),
|
.accentColorDark,
|
||||||
onPressed: () async {
|
width: 20,
|
||||||
Navigator.popUntil(context,
|
height: 20,
|
||||||
ModalRoute.withName(widget.routeOnSuccessOrDelete));
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.popUntil(context,
|
||||||
|
ModalRoute.withName(widget.routeOnSuccessOrDelete));
|
||||||
|
|
||||||
await ref.read(nodeServiceChangeNotifierProvider).delete(
|
await ref.read(nodeServiceChangeNotifierProvider).delete(
|
||||||
nodeId!,
|
nodeId!,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 12,
|
|
||||||
left: 12,
|
|
||||||
right: 12,
|
|
||||||
bottom: 12,
|
|
||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
body: Padding(
|
||||||
builder: (context, constraints) {
|
padding: const EdgeInsets.only(
|
||||||
return SingleChildScrollView(
|
top: 12,
|
||||||
child: Padding(
|
left: 12,
|
||||||
padding: const EdgeInsets.all(4),
|
right: 12,
|
||||||
child: ConstrainedBox(
|
bottom: 12,
|
||||||
constraints:
|
),
|
||||||
BoxConstraints(minHeight: constraints.maxHeight - 8),
|
child: LayoutBuilder(
|
||||||
child: IntrinsicHeight(
|
builder: (context, constraints) {
|
||||||
child: Column(
|
return SingleChildScrollView(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(4),
|
||||||
NodeForm(
|
child: ConstrainedBox(
|
||||||
node: node,
|
constraints:
|
||||||
secureStore: widget.secureStore,
|
BoxConstraints(minHeight: constraints.maxHeight - 8),
|
||||||
readOnly: false,
|
child: IntrinsicHeight(
|
||||||
coin: widget.coin,
|
child: child,
|
||||||
onChanged: (canSave, canTest) {
|
|
||||||
if (canSave != saveEnabled &&
|
|
||||||
canTest != testConnectionEnabled) {
|
|
||||||
setState(() {
|
|
||||||
saveEnabled = canSave;
|
|
||||||
testConnectionEnabled = canTest;
|
|
||||||
});
|
|
||||||
} else if (canSave != saveEnabled) {
|
|
||||||
setState(() {
|
|
||||||
saveEnabled = canSave;
|
|
||||||
});
|
|
||||||
} else if (canTest != testConnectionEnabled) {
|
|
||||||
setState(() {
|
|
||||||
testConnectionEnabled = canTest;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
TextButton(
|
|
||||||
onPressed: testConnectionEnabled
|
|
||||||
? () async {
|
|
||||||
await _testConnection();
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
style: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.getSecondaryEnabledButtonColor(context),
|
|
||||||
child: Text(
|
|
||||||
"Test connection",
|
|
||||||
style: STextStyles.button(context).copyWith(
|
|
||||||
color: testConnectionEnabled
|
|
||||||
? Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textDark
|
|
||||||
: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textWhite,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextButton(
|
|
||||||
style: saveEnabled
|
|
||||||
? Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.getPrimaryEnabledButtonColor(context)
|
|
||||||
: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.getPrimaryDisabledButtonColor(context),
|
|
||||||
onPressed: saveEnabled
|
|
||||||
? () async {
|
|
||||||
final canConnect = await _testConnection(
|
|
||||||
showFlushBar: false);
|
|
||||||
|
|
||||||
bool? shouldSave;
|
|
||||||
|
|
||||||
if (!canConnect) {
|
|
||||||
await showDialog<dynamic>(
|
|
||||||
context: context,
|
|
||||||
useSafeArea: true,
|
|
||||||
barrierDismissible: true,
|
|
||||||
builder: (_) => StackDialog(
|
|
||||||
title: "Server currently unreachable",
|
|
||||||
message:
|
|
||||||
"Would you like to save this node anyways?",
|
|
||||||
leftButton: TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop(false);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
"Cancel",
|
|
||||||
style: STextStyles.button(context)
|
|
||||||
.copyWith(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<
|
|
||||||
StackColors>()!
|
|
||||||
.accentColorDark),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
rightButton: TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop(true);
|
|
||||||
},
|
|
||||||
style: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.getPrimaryEnabledButtonColor(
|
|
||||||
context),
|
|
||||||
child: Text(
|
|
||||||
"Save",
|
|
||||||
style: STextStyles.button(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).then((value) {
|
|
||||||
if (value is bool && value) {
|
|
||||||
shouldSave = true;
|
|
||||||
} else {
|
|
||||||
shouldSave = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canConnect && !shouldSave!) {
|
|
||||||
// return without saving
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final formData =
|
|
||||||
ref.read(nodeFormDataProvider);
|
|
||||||
|
|
||||||
// strip unused path
|
|
||||||
String address = formData.host!;
|
|
||||||
if (coin == Coin.monero ||
|
|
||||||
coin == Coin.wownero ||
|
|
||||||
coin == Coin.epicCash) {
|
|
||||||
if (address.startsWith("http")) {
|
|
||||||
final uri = Uri.parse(address);
|
|
||||||
address = "${uri.scheme}://${uri.host}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (viewType) {
|
|
||||||
case AddEditNodeViewType.add:
|
|
||||||
NodeModel node = NodeModel(
|
|
||||||
host: address,
|
|
||||||
port: formData.port!,
|
|
||||||
name: formData.name!,
|
|
||||||
id: const Uuid().v1(),
|
|
||||||
useSSL: formData.useSSL!,
|
|
||||||
loginName: formData.login,
|
|
||||||
enabled: true,
|
|
||||||
coinName: coin.name,
|
|
||||||
isFailover: formData.isFailover!,
|
|
||||||
isDown: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
await ref
|
|
||||||
.read(
|
|
||||||
nodeServiceChangeNotifierProvider)
|
|
||||||
.add(
|
|
||||||
node,
|
|
||||||
formData.password,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
if (mounted) {
|
|
||||||
Navigator.of(context).popUntil(
|
|
||||||
ModalRoute.withName(
|
|
||||||
widget.routeOnSuccessOrDelete));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AddEditNodeViewType.edit:
|
|
||||||
NodeModel node = NodeModel(
|
|
||||||
host: address,
|
|
||||||
port: formData.port!,
|
|
||||||
name: formData.name!,
|
|
||||||
id: nodeId!,
|
|
||||||
useSSL: formData.useSSL!,
|
|
||||||
loginName: formData.login,
|
|
||||||
enabled: true,
|
|
||||||
coinName: coin.name,
|
|
||||||
isFailover: formData.isFailover!,
|
|
||||||
isDown: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
await ref
|
|
||||||
.read(
|
|
||||||
nodeServiceChangeNotifierProvider)
|
|
||||||
.add(
|
|
||||||
node,
|
|
||||||
formData.password,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
if (mounted) {
|
|
||||||
Navigator.of(context).popUntil(
|
|
||||||
ModalRoute.withName(
|
|
||||||
widget.routeOnSuccessOrDelete));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
child: Text(
|
|
||||||
"Save",
|
|
||||||
style: STextStyles.button(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: isDesktop,
|
||||||
|
builder: (child) => DesktopDialog(
|
||||||
|
maxWidth: 580,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
const AppBarBackButton(
|
||||||
|
iconSize: 24,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Add new node",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
Padding(
|
||||||
},
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
top: 16,
|
||||||
|
bottom: 32,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
NodeForm(
|
||||||
|
node: node,
|
||||||
|
secureStore: widget.secureStore,
|
||||||
|
readOnly: false,
|
||||||
|
coin: widget.coin,
|
||||||
|
onChanged: (canSave, canTest) {
|
||||||
|
if (canSave != saveEnabled &&
|
||||||
|
canTest != testConnectionEnabled) {
|
||||||
|
setState(() {
|
||||||
|
saveEnabled = canSave;
|
||||||
|
testConnectionEnabled = canTest;
|
||||||
|
});
|
||||||
|
} else if (canSave != saveEnabled) {
|
||||||
|
setState(() {
|
||||||
|
saveEnabled = canSave;
|
||||||
|
});
|
||||||
|
} else if (canTest != testConnectionEnabled) {
|
||||||
|
setState(() {
|
||||||
|
testConnectionEnabled = canTest;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (!isDesktop) const Spacer(),
|
||||||
|
if (isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 78,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Test connection",
|
||||||
|
enabled: testConnectionEnabled,
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: testConnectionEnabled
|
||||||
|
? () async {
|
||||||
|
await _testConnection();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Save",
|
||||||
|
enabled: saveEnabled,
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: saveEnabled ? attemptSave : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
if (!isDesktop)
|
||||||
|
TextButton(
|
||||||
|
style: saveEnabled
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getPrimaryEnabledButtonColor(context)
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getPrimaryDisabledButtonColor(context),
|
||||||
|
onPressed: saveEnabled ? attemptSave : null,
|
||||||
|
child: Text(
|
||||||
|
"Save",
|
||||||
|
style: STextStyles.button(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,6 +9,7 @@ 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/custom_buttons/app_bar_icon_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
@ -17,11 +18,13 @@ class CoinNodesView extends ConsumerStatefulWidget {
|
||||||
const CoinNodesView({
|
const CoinNodesView({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.coin,
|
required this.coin,
|
||||||
|
this.rootNavigator = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
static const String routeName = "/coinNodes";
|
static const String routeName = "/coinNodes";
|
||||||
|
|
||||||
final Coin coin;
|
final Coin coin;
|
||||||
|
final bool rootNavigator;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<CoinNodesView> createState() => _CoinNodesViewState();
|
ConsumerState<CoinNodesView> createState() => _CoinNodesViewState();
|
||||||
|
@ -63,12 +66,17 @@ class _CoinNodesViewState extends ConsumerState<CoinNodesView> {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: const DesktopDialogCloseButton(),
|
child: DesktopDialogCloseButton(
|
||||||
|
onPressedOverride: Navigator.of(
|
||||||
|
context,
|
||||||
|
rootNavigator: widget.rootNavigator,
|
||||||
|
).pop,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 32,
|
left: 32,
|
||||||
right: 32,
|
right: 32,
|
||||||
),
|
),
|
||||||
|
@ -83,14 +91,19 @@ class _CoinNodesViewState extends ConsumerState<CoinNodesView> {
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
),
|
),
|
||||||
RichText(
|
BlueTextButton(
|
||||||
text: TextSpan(
|
text: "Add new node",
|
||||||
text: 'Add new nodes',
|
onTap: () {
|
||||||
style:
|
Navigator.of(context).pushNamed(
|
||||||
STextStyles.desktopTextExtraSmall(context).copyWith(
|
AddEditNodeView.routeName,
|
||||||
color: Colors.blueAccent,
|
arguments: Tuple4(
|
||||||
),
|
AddEditNodeViewType.add,
|
||||||
),
|
widget.coin,
|
||||||
|
null,
|
||||||
|
CoinNodesView.routeName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -17,7 +17,13 @@ import 'package:stackwallet/utilities/test_epic_box_connection.dart';
|
||||||
import 'package:stackwallet/utilities/test_monero_node_connection.dart';
|
import 'package:stackwallet/utilities/test_monero_node_connection.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/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/delete_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
class NodeDetailsView extends ConsumerStatefulWidget {
|
class NodeDetailsView extends ConsumerStatefulWidget {
|
||||||
|
@ -48,6 +54,8 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
|
||||||
late final String nodeId;
|
late final String nodeId;
|
||||||
late final String popRouteName;
|
late final String popRouteName;
|
||||||
|
|
||||||
|
bool _desktopReadOnly = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
secureStore = widget.secureStore;
|
secureStore = widget.secureStore;
|
||||||
|
@ -126,130 +134,239 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testPassed) {
|
if (testPassed) {
|
||||||
showFloatingFlushBar(
|
unawaited(
|
||||||
type: FlushBarType.success,
|
showFloatingFlushBar(
|
||||||
message: "Server ping success",
|
type: FlushBarType.success,
|
||||||
context: context,
|
message: "Server ping success",
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showFloatingFlushBar(
|
unawaited(
|
||||||
type: FlushBarType.warning,
|
showFloatingFlushBar(
|
||||||
message: "Server unreachable",
|
type: FlushBarType.warning,
|
||||||
context: context,
|
message: "Server unreachable",
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
final isDesktop = Util.isDesktop;
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
|
||||||
appBar: AppBar(
|
final node = ref.watch(nodeServiceChangeNotifierProvider
|
||||||
leading: AppBarBackButton(
|
.select((value) => value.getNodeById(id: nodeId)));
|
||||||
onPressed: () async {
|
|
||||||
if (FocusScope.of(context).hasFocus) {
|
return ConditionalParent(
|
||||||
FocusScope.of(context).unfocus();
|
condition: !isDesktop,
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 75));
|
builder: (child) => Scaffold(
|
||||||
}
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
if (mounted) {
|
appBar: AppBar(
|
||||||
Navigator.of(context).pop();
|
leading: AppBarBackButton(
|
||||||
}
|
onPressed: () async {
|
||||||
},
|
if (FocusScope.of(context).hasFocus) {
|
||||||
),
|
FocusScope.of(context).unfocus();
|
||||||
title: Text(
|
await Future<void>.delayed(const Duration(milliseconds: 75));
|
||||||
"Node details",
|
}
|
||||||
style: STextStyles.navBarTitle(context),
|
if (mounted) {
|
||||||
),
|
Navigator.of(context).pop();
|
||||||
actions: [
|
}
|
||||||
if (!nodeId.startsWith("default"))
|
},
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.only(
|
title: Text(
|
||||||
top: 10,
|
"Node details",
|
||||||
bottom: 10,
|
style: STextStyles.navBarTitle(context),
|
||||||
right: 10,
|
),
|
||||||
),
|
actions: [
|
||||||
child: AspectRatio(
|
if (!nodeId.startsWith("default"))
|
||||||
aspectRatio: 1,
|
Padding(
|
||||||
child: AppBarIconButton(
|
padding: const EdgeInsets.only(
|
||||||
key: const Key("nodeDetailsEditNodeAppBarButtonKey"),
|
top: 10,
|
||||||
size: 36,
|
bottom: 10,
|
||||||
shadows: const [],
|
right: 10,
|
||||||
color: Theme.of(context).extension<StackColors>()!.background,
|
),
|
||||||
icon: SvgPicture.asset(
|
child: AspectRatio(
|
||||||
Assets.svg.pencil,
|
aspectRatio: 1,
|
||||||
color: Theme.of(context)
|
child: AppBarIconButton(
|
||||||
.extension<StackColors>()!
|
key: const Key("nodeDetailsEditNodeAppBarButtonKey"),
|
||||||
.accentColorDark,
|
size: 36,
|
||||||
width: 20,
|
shadows: const [],
|
||||||
height: 20,
|
color:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.svg.pencil,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.accentColorDark,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
AddEditNodeView.routeName,
|
||||||
|
arguments: Tuple4(
|
||||||
|
AddEditNodeViewType.edit,
|
||||||
|
coin,
|
||||||
|
nodeId,
|
||||||
|
popRouteName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
AddEditNodeView.routeName,
|
|
||||||
arguments: Tuple4(
|
|
||||||
AddEditNodeViewType.edit,
|
|
||||||
coin,
|
|
||||||
nodeId,
|
|
||||||
popRouteName,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 12,
|
|
||||||
left: 12,
|
|
||||||
right: 12,
|
|
||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
body: Padding(
|
||||||
builder: (context, constraints) {
|
padding: const EdgeInsets.only(
|
||||||
final node = ref.watch(nodeServiceChangeNotifierProvider
|
top: 12,
|
||||||
.select((value) => value.getNodeById(id: nodeId)));
|
left: 12,
|
||||||
|
right: 12,
|
||||||
return SingleChildScrollView(
|
),
|
||||||
child: Padding(
|
child: LayoutBuilder(
|
||||||
padding: const EdgeInsets.all(4),
|
builder: (context, constraints) {
|
||||||
child: ConstrainedBox(
|
return SingleChildScrollView(
|
||||||
constraints:
|
child: Padding(
|
||||||
BoxConstraints(minHeight: constraints.maxHeight - 8),
|
padding: const EdgeInsets.all(4),
|
||||||
child: IntrinsicHeight(
|
child: ConstrainedBox(
|
||||||
child: Column(
|
constraints:
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
BoxConstraints(minHeight: constraints.maxHeight - 8),
|
||||||
children: [
|
child: IntrinsicHeight(
|
||||||
NodeForm(
|
child: child,
|
||||||
node: node,
|
|
||||||
secureStore: secureStore,
|
|
||||||
readOnly: true,
|
|
||||||
coin: coin,
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
TextButton(
|
|
||||||
style: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.getSecondaryEnabledButtonColor(context),
|
|
||||||
onPressed: () async {
|
|
||||||
await _testConnection(ref, context);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
"Test connection",
|
|
||||||
style: STextStyles.button(context).copyWith(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.accentColorDark),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: isDesktop,
|
||||||
|
builder: (child) => DesktopDialog(
|
||||||
|
maxWidth: 580,
|
||||||
|
maxHeight: double.infinity,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
const AppBarBackButton(
|
||||||
|
iconSize: 24,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Node details",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
Padding(
|
||||||
},
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
top: 16,
|
||||||
|
bottom: 32,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
NodeForm(
|
||||||
|
node: node,
|
||||||
|
secureStore: secureStore,
|
||||||
|
readOnly: isDesktop ? _desktopReadOnly : true,
|
||||||
|
coin: coin,
|
||||||
|
),
|
||||||
|
if (!isDesktop) const Spacer(),
|
||||||
|
if (isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 22,
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
SizedBox(
|
||||||
|
height: 56,
|
||||||
|
child: _desktopReadOnly
|
||||||
|
? null
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: DeleteButton(
|
||||||
|
label: "Delete node",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
await ref
|
||||||
|
.read(nodeServiceChangeNotifierProvider)
|
||||||
|
.delete(
|
||||||
|
node!.id,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isDesktop && !_desktopReadOnly)
|
||||||
|
const SizedBox(
|
||||||
|
height: 45,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Test connection",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: () async {
|
||||||
|
await _testConnection(ref, context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
if (isDesktop)
|
||||||
|
Expanded(
|
||||||
|
child: !nodeId.startsWith("default")
|
||||||
|
? PrimaryButton(
|
||||||
|
label: _desktopReadOnly ? "Edit" : "Save",
|
||||||
|
desktopMed: true,
|
||||||
|
onPressed: () async {
|
||||||
|
final shouldSave = _desktopReadOnly == false;
|
||||||
|
setState(() {
|
||||||
|
_desktopReadOnly = !_desktopReadOnly;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (shouldSave) {
|
||||||
|
// todo save node
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,7 +6,11 @@ import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/sync_type_enum.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/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/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class SyncingOptionsView extends ConsumerWidget {
|
class SyncingOptionsView extends ConsumerWidget {
|
||||||
|
@ -16,384 +20,390 @@ class SyncingOptionsView extends ConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return Scaffold(
|
final isDesktop = Util.isDesktop;
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
return ConditionalParent(
|
||||||
appBar: AppBar(
|
condition: !isDesktop,
|
||||||
leading: AppBarBackButton(
|
builder: (child) {
|
||||||
onPressed: () async {
|
return Scaffold(
|
||||||
Navigator.of(context).pop();
|
backgroundColor:
|
||||||
},
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
),
|
appBar: AppBar(
|
||||||
title: Text(
|
leading: AppBarBackButton(
|
||||||
"Syncing",
|
onPressed: () async {
|
||||||
style: STextStyles.navBarTitle(context),
|
Navigator.of(context).pop();
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
body: Padding(
|
title: Text(
|
||||||
padding: const EdgeInsets.all(16),
|
"Syncing",
|
||||||
child: LayoutBuilder(
|
style: STextStyles.navBarTitle(context),
|
||||||
builder: (context, constraints) {
|
),
|
||||||
return SingleChildScrollView(
|
),
|
||||||
child: ConstrainedBox(
|
body: Padding(
|
||||||
constraints: BoxConstraints(
|
padding: const EdgeInsets.all(16),
|
||||||
minHeight: constraints.maxHeight,
|
child: LayoutBuilder(
|
||||||
),
|
builder: (context, constraints) {
|
||||||
child: IntrinsicHeight(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: ConstrainedBox(
|
||||||
children: [
|
constraints: BoxConstraints(
|
||||||
RoundedWhiteContainer(
|
minHeight: constraints.maxHeight,
|
||||||
padding: const EdgeInsets.all(0),
|
),
|
||||||
child: Column(
|
child: IntrinsicHeight(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: RawMaterialButton(
|
||||||
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
final state =
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType;
|
||||||
|
if (state != SyncingType.currentWalletOnly) {
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType =
|
||||||
|
SyncingType.currentWalletOnly;
|
||||||
|
|
||||||
|
// disable auto sync on all wallets that aren't active/current
|
||||||
|
ref
|
||||||
|
.read(walletsChangeNotifierProvider)
|
||||||
|
.managers
|
||||||
|
.forEach((e) {
|
||||||
|
if (!e.isActiveWallet) {
|
||||||
|
e.shouldAutoSync = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
SizedBox(
|
||||||
padding: const EdgeInsets.all(4),
|
width: 20,
|
||||||
child: RawMaterialButton(
|
height: 20,
|
||||||
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
child: Radio(
|
||||||
materialTapTargetSize:
|
activeColor: Theme.of(context)
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
.extension<StackColors>()!
|
||||||
shape: RoundedRectangleBorder(
|
.radioButtonIconEnabled,
|
||||||
borderRadius: BorderRadius.circular(
|
value: SyncingType.currentWalletOnly,
|
||||||
Constants.size.circularBorderRadius,
|
groupValue: ref.watch(
|
||||||
),
|
prefsChangeNotifierProvider
|
||||||
|
.select((value) => value.syncType),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onChanged: (value) {
|
||||||
final state = ref
|
if (value is SyncingType) {
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType;
|
|
||||||
if (state != SyncingType.currentWalletOnly) {
|
|
||||||
ref
|
ref
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType =
|
|
||||||
SyncingType.currentWalletOnly;
|
|
||||||
|
|
||||||
// disable auto sync on all wallets that aren't active/current
|
|
||||||
ref
|
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.managers
|
|
||||||
.forEach((e) {
|
|
||||||
if (!e.isActiveWallet) {
|
|
||||||
e.shouldAutoSync = 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: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.radioButtonIconEnabled,
|
|
||||||
value:
|
|
||||||
SyncingType.currentWalletOnly,
|
|
||||||
groupValue: ref.watch(
|
|
||||||
prefsChangeNotifierProvider
|
|
||||||
.select((value) =>
|
|
||||||
value.syncType),
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value is SyncingType) {
|
|
||||||
ref
|
|
||||||
.read(
|
|
||||||
prefsChangeNotifierProvider)
|
|
||||||
.syncType = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Sync only currently open wallet",
|
|
||||||
style: STextStyles.titleBold12(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Sync only the wallet that you are using",
|
|
||||||
style: STextStyles.itemSubtitle(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4.0),
|
|
||||||
child: RawMaterialButton(
|
|
||||||
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
final state = ref
|
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType;
|
|
||||||
if (state !=
|
|
||||||
SyncingType.allWalletsOnStartup) {
|
|
||||||
ref
|
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType =
|
|
||||||
SyncingType.allWalletsOnStartup;
|
|
||||||
|
|
||||||
// enable auto sync on all wallets
|
|
||||||
ref
|
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.managers
|
|
||||||
.forEach(
|
|
||||||
(e) => e.shouldAutoSync = true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.radioButtonIconEnabled,
|
|
||||||
value:
|
|
||||||
SyncingType.allWalletsOnStartup,
|
|
||||||
groupValue: ref.watch(
|
|
||||||
prefsChangeNotifierProvider
|
|
||||||
.select((value) =>
|
|
||||||
value.syncType),
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value is SyncingType) {
|
|
||||||
ref
|
|
||||||
.read(
|
|
||||||
prefsChangeNotifierProvider)
|
|
||||||
.syncType = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Sync all wallets at startup",
|
|
||||||
style: STextStyles.titleBold12(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"All of your wallets will start syncing when you open the app",
|
|
||||||
style: STextStyles.itemSubtitle(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: RawMaterialButton(
|
|
||||||
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
final state = ref
|
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType;
|
|
||||||
if (state !=
|
|
||||||
SyncingType.selectedWalletsAtStartup) {
|
|
||||||
ref
|
|
||||||
.read(prefsChangeNotifierProvider)
|
|
||||||
.syncType =
|
|
||||||
SyncingType.selectedWalletsAtStartup;
|
|
||||||
|
|
||||||
final ids = ref
|
|
||||||
.read(prefsChangeNotifierProvider)
|
.read(prefsChangeNotifierProvider)
|
||||||
.walletIdsSyncOnStartup;
|
.syncType = value;
|
||||||
|
|
||||||
// enable auto sync on selected wallets only
|
|
||||||
ref
|
|
||||||
.read(walletsChangeNotifierProvider)
|
|
||||||
.managers
|
|
||||||
.forEach((e) => e.shouldAutoSync =
|
|
||||||
ids.contains(e.walletId));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.radioButtonIconEnabled,
|
|
||||||
value: SyncingType
|
|
||||||
.selectedWalletsAtStartup,
|
|
||||||
groupValue: ref.watch(
|
|
||||||
prefsChangeNotifierProvider
|
|
||||||
.select((value) =>
|
|
||||||
value.syncType),
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value is SyncingType) {
|
|
||||||
ref
|
|
||||||
.read(
|
|
||||||
prefsChangeNotifierProvider)
|
|
||||||
.syncType = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Sync only selected wallets at startup",
|
|
||||||
style: STextStyles.titleBold12(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Only the wallets you select will start syncing when you open the app",
|
|
||||||
style: STextStyles.itemSubtitle(
|
|
||||||
context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (ref.watch(prefsChangeNotifierProvider
|
const SizedBox(
|
||||||
.select((value) => value.syncType)) !=
|
width: 12,
|
||||||
SyncingType.selectedWalletsAtStartup)
|
),
|
||||||
const SizedBox(
|
Flexible(
|
||||||
height: 12,
|
child: Column(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
if (ref.watch(prefsChangeNotifierProvider
|
children: [
|
||||||
.select((value) => value.syncType)) ==
|
Text(
|
||||||
SyncingType.selectedWalletsAtStartup)
|
"Sync only currently open wallet",
|
||||||
Container(
|
style: STextStyles.titleBold12(context),
|
||||||
color: Colors.transparent,
|
textAlign: TextAlign.left,
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 12.0,
|
|
||||||
right: 12,
|
|
||||||
bottom: 12,
|
|
||||||
),
|
),
|
||||||
child: Row(
|
Text(
|
||||||
crossAxisAlignment:
|
"Sync only the wallet that you are using",
|
||||||
CrossAxisAlignment.start,
|
style: STextStyles.itemSubtitle(context),
|
||||||
children: [
|
textAlign: TextAlign.left,
|
||||||
const SizedBox(
|
|
||||||
width: 12 + 20,
|
|
||||||
height: 12,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: RawMaterialButton(
|
|
||||||
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants
|
|
||||||
.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
WalletSyncingOptionsView
|
|
||||||
.routeName);
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Select wallets...",
|
|
||||||
style:
|
|
||||||
STextStyles.link2(context),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
);
|
padding: const EdgeInsets.all(4.0),
|
||||||
},
|
child: RawMaterialButton(
|
||||||
),
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
final state =
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType;
|
||||||
|
if (state != SyncingType.allWalletsOnStartup) {
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType =
|
||||||
|
SyncingType.allWalletsOnStartup;
|
||||||
|
|
||||||
|
// enable auto sync on all wallets
|
||||||
|
ref
|
||||||
|
.read(walletsChangeNotifierProvider)
|
||||||
|
.managers
|
||||||
|
.forEach((e) => e.shouldAutoSync = true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.radioButtonIconEnabled,
|
||||||
|
value: SyncingType.allWalletsOnStartup,
|
||||||
|
groupValue: ref.watch(
|
||||||
|
prefsChangeNotifierProvider
|
||||||
|
.select((value) => value.syncType),
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value is SyncingType) {
|
||||||
|
ref
|
||||||
|
.read(prefsChangeNotifierProvider)
|
||||||
|
.syncType = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sync all wallets at startup",
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"All of your wallets will start syncing when you open the app",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: RawMaterialButton(
|
||||||
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
final state =
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType;
|
||||||
|
if (state != SyncingType.selectedWalletsAtStartup) {
|
||||||
|
ref.read(prefsChangeNotifierProvider).syncType =
|
||||||
|
SyncingType.selectedWalletsAtStartup;
|
||||||
|
|
||||||
|
final ids = ref
|
||||||
|
.read(prefsChangeNotifierProvider)
|
||||||
|
.walletIdsSyncOnStartup;
|
||||||
|
|
||||||
|
// enable auto sync on selected wallets only
|
||||||
|
ref
|
||||||
|
.read(walletsChangeNotifierProvider)
|
||||||
|
.managers
|
||||||
|
.forEach((e) =>
|
||||||
|
e.shouldAutoSync = ids.contains(e.walletId));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.radioButtonIconEnabled,
|
||||||
|
value: SyncingType.selectedWalletsAtStartup,
|
||||||
|
groupValue: ref.watch(
|
||||||
|
prefsChangeNotifierProvider
|
||||||
|
.select((value) => value.syncType),
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value is SyncingType) {
|
||||||
|
ref
|
||||||
|
.read(prefsChangeNotifierProvider)
|
||||||
|
.syncType = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Sync only selected wallets at startup",
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Only the wallets you select will start syncing when you open the app",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (ref.watch(prefsChangeNotifierProvider
|
||||||
|
.select((value) => value.syncType)) !=
|
||||||
|
SyncingType.selectedWalletsAtStartup)
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
if (ref.watch(prefsChangeNotifierProvider
|
||||||
|
.select((value) => value.syncType)) ==
|
||||||
|
SyncingType.selectedWalletsAtStartup)
|
||||||
|
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: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
materialTapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
!isDesktop
|
||||||
|
? Navigator.of(context).pushNamed(
|
||||||
|
WalletSyncingOptionsView.routeName)
|
||||||
|
: showDialog(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: false,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (context) {
|
||||||
|
return DesktopDialog(
|
||||||
|
maxWidth: 600,
|
||||||
|
maxHeight: 800,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment
|
||||||
|
.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.all(
|
||||||
|
32),
|
||||||
|
child: Text(
|
||||||
|
"Select wallets to sync",
|
||||||
|
style: STextStyles
|
||||||
|
.desktopH3(context),
|
||||||
|
textAlign:
|
||||||
|
TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const DesktopDialogCloseButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
child:
|
||||||
|
WalletSyncingOptionsView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Select wallets...",
|
||||||
|
style: STextStyles.link2(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@ import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
||||||
import 'package:stackwallet/utilities/format.dart';
|
import 'package:stackwallet/utilities/format.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/widgets/animated_text.dart';
|
import 'package:stackwallet/widgets/animated_text.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/custom_buttons/draggable_switch_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
@ -25,30 +27,47 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
||||||
final managers = ref
|
final managers = ref
|
||||||
.watch(walletsChangeNotifierProvider.select((value) => value.managers));
|
.watch(walletsChangeNotifierProvider.select((value) => value.managers));
|
||||||
|
|
||||||
return Scaffold(
|
final isDesktop = Util.isDesktop;
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
return ConditionalParent(
|
||||||
appBar: AppBar(
|
condition: !isDesktop,
|
||||||
leading: AppBarBackButton(
|
builder: (child) {
|
||||||
onPressed: () async {
|
return Scaffold(
|
||||||
Navigator.of(context).pop();
|
backgroundColor:
|
||||||
},
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
),
|
appBar: AppBar(
|
||||||
title: FittedBox(
|
leading: AppBarBackButton(
|
||||||
fit: BoxFit.scaleDown,
|
onPressed: () async {
|
||||||
child: Text(
|
Navigator.of(context).pop();
|
||||||
"Sync only selected wallets at startup",
|
},
|
||||||
style: STextStyles.navBarTitle(context),
|
),
|
||||||
|
title: FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Text(
|
||||||
|
"Sync only selected wallets at startup",
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
body: Padding(
|
||||||
),
|
padding: const EdgeInsets.only(
|
||||||
body: LayoutBuilder(builder: (context, constraints) {
|
left: 12,
|
||||||
return Padding(
|
top: 12,
|
||||||
padding: const EdgeInsets.only(
|
right: 12,
|
||||||
left: 12,
|
),
|
||||||
top: 12,
|
child: child,
|
||||||
right: 12,
|
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
);
|
||||||
|
},
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: isDesktop,
|
||||||
|
builder: (child) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: LayoutBuilder(builder: (context, constraints) {
|
||||||
|
return SingleChildScrollView(
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minHeight: constraints.maxHeight - 24,
|
minHeight: constraints.maxHeight - 24,
|
||||||
|
@ -71,6 +90,11 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
RoundedWhiteContainer(
|
RoundedWhiteContainer(
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
|
borderColor: !isDesktop
|
||||||
|
? Colors.transparent
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.background,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
...managers.map(
|
...managers.map(
|
||||||
|
@ -208,9 +232,9 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}),
|
||||||
}),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'package:stackwallet/utilities/constants.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/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/desktop_app_bar.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||||
|
@ -70,180 +71,195 @@ class _StackPrivacyCalls extends ConsumerState<StackPrivacyCalls> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Padding(
|
child: ConditionalParent(
|
||||||
padding: EdgeInsets.fromLTRB(0, isDesktop ? 0 : 40, 0, 0),
|
condition: !isDesktop,
|
||||||
child: ConstrainedBox(
|
builder: (child) => LayoutBuilder(
|
||||||
constraints: BoxConstraints(
|
builder: (context, constraints) => SingleChildScrollView(
|
||||||
maxWidth: isDesktop ? 480 : double.infinity,
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: constraints.maxHeight,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Padding(
|
||||||
children: [
|
padding: EdgeInsets.fromLTRB(0, isDesktop ? 0 : 40, 0, 0),
|
||||||
Text(
|
child: ConstrainedBox(
|
||||||
"Choose your Stack experience",
|
constraints: BoxConstraints(
|
||||||
style: isDesktop
|
maxWidth: isDesktop ? 480 : double.infinity,
|
||||||
? STextStyles.desktopH2(context)
|
),
|
||||||
: STextStyles.pageTitleH1(context),
|
child: Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
SizedBox(
|
children: [
|
||||||
height: isDesktop ? 16 : 8,
|
Text(
|
||||||
),
|
"Choose your Stack experience",
|
||||||
Text(
|
style: isDesktop
|
||||||
!widget.isSettings
|
? STextStyles.desktopH2(context)
|
||||||
? "You can change it later in Settings"
|
: STextStyles.pageTitleH1(context),
|
||||||
: "",
|
|
||||||
style: isDesktop
|
|
||||||
? STextStyles.desktopSubtitleH2(context)
|
|
||||||
: STextStyles.subtitle(context),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: isDesktop ? 32 : 36,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: isDesktop ? 0 : 16,
|
|
||||||
),
|
),
|
||||||
child: PrivacyToggle(
|
SizedBox(
|
||||||
externalCallsEnabled: isEasy,
|
height: isDesktop ? 16 : 8,
|
||||||
onChanged: (externalCalls) {
|
|
||||||
isEasy = externalCalls;
|
|
||||||
setState(() {
|
|
||||||
infoToggle = isEasy;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
SizedBox(
|
!widget.isSettings
|
||||||
height: isDesktop ? 16 : 36,
|
? "You can change it later in Settings"
|
||||||
),
|
: "",
|
||||||
Padding(
|
style: isDesktop
|
||||||
padding: isDesktop
|
? STextStyles.desktopSubtitleH2(context)
|
||||||
? const EdgeInsets.all(0)
|
: STextStyles.subtitle(context),
|
||||||
: const EdgeInsets.all(16.0),
|
),
|
||||||
child: RoundedWhiteContainer(
|
SizedBox(
|
||||||
child: Center(
|
height: isDesktop ? 32 : 36,
|
||||||
child: RichText(
|
),
|
||||||
textAlign: TextAlign.left,
|
Padding(
|
||||||
text: TextSpan(
|
padding: EdgeInsets.symmetric(
|
||||||
style: isDesktop
|
horizontal: isDesktop ? 0 : 16,
|
||||||
? STextStyles.desktopTextExtraExtraSmall(context)
|
),
|
||||||
: STextStyles.label(context).copyWith(
|
child: PrivacyToggle(
|
||||||
fontSize: 12.0,
|
externalCallsEnabled: isEasy,
|
||||||
),
|
onChanged: (externalCalls) {
|
||||||
children: infoToggle
|
isEasy = externalCalls;
|
||||||
? [
|
setState(() {
|
||||||
const TextSpan(
|
infoToggle = isEasy;
|
||||||
text:
|
});
|
||||||
"Exchange data preloaded for a seamless experience."),
|
},
|
||||||
const TextSpan(
|
),
|
||||||
text:
|
),
|
||||||
"\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."),
|
SizedBox(
|
||||||
TextSpan(
|
height: isDesktop ? 16 : 36,
|
||||||
text:
|
),
|
||||||
"\n\nRecommended for most crypto users.",
|
Padding(
|
||||||
style: isDesktop
|
padding: isDesktop
|
||||||
? STextStyles
|
? const EdgeInsets.all(0)
|
||||||
.desktopTextExtraExtraSmall600(
|
: const EdgeInsets.all(16.0),
|
||||||
context)
|
child: RoundedWhiteContainer(
|
||||||
: TextStyle(
|
child: Center(
|
||||||
color: Theme.of(context)
|
child: RichText(
|
||||||
.extension<StackColors>()!
|
textAlign: TextAlign.left,
|
||||||
.textDark,
|
text: TextSpan(
|
||||||
fontWeight: FontWeight.w600,
|
style: isDesktop
|
||||||
),
|
? STextStyles.desktopTextExtraExtraSmall(context)
|
||||||
|
: STextStyles.label(context).copyWith(
|
||||||
|
fontSize: 12.0,
|
||||||
),
|
),
|
||||||
]
|
children: infoToggle
|
||||||
: [
|
? [
|
||||||
const TextSpan(
|
const TextSpan(
|
||||||
|
text:
|
||||||
|
"Exchange data preloaded for a seamless experience."),
|
||||||
|
const TextSpan(
|
||||||
|
text:
|
||||||
|
"\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."),
|
||||||
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
"Exchange data not preloaded (slower experience)."),
|
"\n\nRecommended for most crypto users.",
|
||||||
const TextSpan(
|
style: isDesktop
|
||||||
|
? STextStyles
|
||||||
|
.desktopTextExtraExtraSmall600(
|
||||||
|
context)
|
||||||
|
: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
const TextSpan(
|
||||||
|
text:
|
||||||
|
"Exchange data not preloaded (slower experience)."),
|
||||||
|
const TextSpan(
|
||||||
|
text:
|
||||||
|
"\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."),
|
||||||
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
"\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."),
|
"\n\nRecommended for the privacy conscious.",
|
||||||
TextSpan(
|
style: isDesktop
|
||||||
text:
|
? STextStyles
|
||||||
"\n\nRecommended for the privacy conscious.",
|
.desktopTextExtraExtraSmall600(
|
||||||
style: isDesktop
|
context)
|
||||||
? STextStyles
|
: TextStyle(
|
||||||
.desktopTextExtraExtraSmall600(
|
color: Theme.of(context)
|
||||||
context)
|
.extension<StackColors>()!
|
||||||
: TextStyle(
|
.textDark,
|
||||||
color: Theme.of(context)
|
fontWeight: FontWeight.w600,
|
||||||
.extension<StackColors>()!
|
),
|
||||||
.textDark,
|
),
|
||||||
fontWeight: FontWeight.w600,
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (!isDesktop)
|
||||||
if (!isDesktop)
|
const Spacer(
|
||||||
const Spacer(
|
flex: 4,
|
||||||
flex: 4,
|
),
|
||||||
),
|
if (isDesktop)
|
||||||
if (isDesktop)
|
const SizedBox(
|
||||||
const SizedBox(
|
height: 32,
|
||||||
height: 32,
|
),
|
||||||
),
|
Padding(
|
||||||
Padding(
|
padding: isDesktop
|
||||||
padding: isDesktop
|
? const EdgeInsets.all(0)
|
||||||
? const EdgeInsets.all(0)
|
: const EdgeInsets.symmetric(
|
||||||
: const EdgeInsets.symmetric(
|
horizontal: 16,
|
||||||
horizontal: 16,
|
vertical: 16,
|
||||||
vertical: 16,
|
),
|
||||||
),
|
child: Row(
|
||||||
child: Row(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: PrimaryButton(
|
||||||
child: PrimaryButton(
|
label:
|
||||||
label:
|
!widget.isSettings ? "Continue" : "Save changes",
|
||||||
!widget.isSettings ? "Continue" : "Save changes",
|
onPressed: () {
|
||||||
onPressed: () {
|
ref
|
||||||
ref
|
.read(prefsChangeNotifierProvider)
|
||||||
.read(prefsChangeNotifierProvider)
|
.externalCalls = isEasy;
|
||||||
.externalCalls = isEasy;
|
|
||||||
|
|
||||||
DB.instance
|
DB.instance
|
||||||
.put<dynamic>(
|
.put<dynamic>(
|
||||||
boxName: DB.boxNamePrefs,
|
boxName: DB.boxNamePrefs,
|
||||||
key: "externalCalls",
|
key: "externalCalls",
|
||||||
value: isEasy)
|
value: isEasy)
|
||||||
.then((_) {
|
.then((_) {
|
||||||
if (isEasy) {
|
if (isEasy) {
|
||||||
unawaited(
|
unawaited(
|
||||||
ExchangeDataLoadingService().loadAll(ref));
|
ExchangeDataLoadingService().loadAll(ref));
|
||||||
ref
|
ref
|
||||||
.read(priceAnd24hChangeNotifierProvider)
|
.read(priceAnd24hChangeNotifierProvider)
|
||||||
.start(true);
|
.start(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!widget.isSettings) {
|
if (!widget.isSettings) {
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
CreatePasswordView.routeName,
|
CreatePasswordView.routeName,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
CreatePinView.routeName,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.pop(context);
|
||||||
CreatePinView.routeName,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
Navigator.pop(context);
|
),
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
if (isDesktop)
|
||||||
if (isDesktop)
|
const SizedBox(
|
||||||
const SizedBox(
|
height: kDesktopAppBarHeight,
|
||||||
height: kDesktopAppBarHeight,
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -494,158 +510,3 @@ class _PrivacyToggleState extends State<PrivacyToggle> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// class ContinueButton extends ConsumerWidget {
|
|
||||||
// const ContinueButton({
|
|
||||||
// Key? key,
|
|
||||||
// required this.isDesktop,
|
|
||||||
// required this.onPressed,
|
|
||||||
// required this.label,
|
|
||||||
// }) : super(key: key);
|
|
||||||
//
|
|
||||||
// final String label;
|
|
||||||
// final bool isDesktop;
|
|
||||||
// final VoidCallback onPressed;
|
|
||||||
//
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
// if (isDesktop) {
|
|
||||||
// return SizedBox(
|
|
||||||
// width: 328,
|
|
||||||
// height: 70,
|
|
||||||
// child: TextButton(
|
|
||||||
// style: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .getPrimaryEnabledButtonColor(context),
|
|
||||||
// onPressed: onPressed,
|
|
||||||
// child: Text(
|
|
||||||
// label,
|
|
||||||
// style: STextStyles.button(context).copyWith(fontSize: 20),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// return TextButton(
|
|
||||||
// style: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .getPrimaryEnabledButtonColor(context),
|
|
||||||
// onPressed: onPressed,
|
|
||||||
// child: Text(
|
|
||||||
// label,
|
|
||||||
// style: STextStyles.button(context),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// class CustomRadio extends StatefulWidget {
|
|
||||||
// CustomRadio(this.upperCall, {Key? key}) : super(key: key);
|
|
||||||
//
|
|
||||||
// Function upperCall;
|
|
||||||
//
|
|
||||||
// @override
|
|
||||||
// createState() {
|
|
||||||
// return CustomRadioState();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// class CustomRadioState extends State<CustomRadio> {
|
|
||||||
// List<RadioModel> sampleData = <RadioModel>[];
|
|
||||||
//
|
|
||||||
// @override
|
|
||||||
// void initState() {
|
|
||||||
// super.initState();
|
|
||||||
// sampleData.add(
|
|
||||||
// RadioModel(true, Assets.svg.personaEasy, 'Easy Crypto', 'Recommended'));
|
|
||||||
// sampleData.add(RadioModel(
|
|
||||||
// false, Assets.svg.personaIncognito, 'Incognito', 'Privacy conscious'));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context) {
|
|
||||||
// return Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
// children: [
|
|
||||||
// InkWell(
|
|
||||||
// onTap: () {
|
|
||||||
// setState(() {
|
|
||||||
// // if (!sampleData[0].isSelected) {
|
|
||||||
// widget.upperCall.call(true);
|
|
||||||
// // }
|
|
||||||
// for (var element in sampleData) {
|
|
||||||
// element.isSelected = false;
|
|
||||||
// }
|
|
||||||
// sampleData[0].isSelected = true;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// child: RadioItem(sampleData[0]),
|
|
||||||
// ),
|
|
||||||
// InkWell(
|
|
||||||
// onTap: () {
|
|
||||||
// setState(() {
|
|
||||||
// // if (!sampleData[1].isSelected) {
|
|
||||||
// widget.upperCall.call(false);
|
|
||||||
// // }
|
|
||||||
// for (var element in sampleData) {
|
|
||||||
// element.isSelected = false;
|
|
||||||
// }
|
|
||||||
// sampleData[1].isSelected = true;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// child: RadioItem(sampleData[1]),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// class RadioItem extends StatelessWidget {
|
|
||||||
// final RadioModel _item;
|
|
||||||
// const RadioItem(this._item, {Key? key}) : super(key: key);
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context) {
|
|
||||||
// return Container(
|
|
||||||
// margin: const EdgeInsets.all(15.0),
|
|
||||||
// child: RoundedWhiteContainer(
|
|
||||||
// borderColor: _item.isSelected ? const Color(0xFF0056D2) : null,
|
|
||||||
// child: Center(
|
|
||||||
// child: Column(
|
|
||||||
// children: [
|
|
||||||
// SvgPicture.asset(
|
|
||||||
// _item.svg,
|
|
||||||
// // color: Theme.of(context).extension<StackColors>()!.textWhite,
|
|
||||||
// width: 140,
|
|
||||||
// height: 140,
|
|
||||||
// ),
|
|
||||||
// RichText(
|
|
||||||
// textAlign: TextAlign.center,
|
|
||||||
// text: TextSpan(
|
|
||||||
// style: STextStyles.label(context).copyWith(fontSize: 12.0),
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: _item.topText,
|
|
||||||
// style: TextStyle(
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .textDark,
|
|
||||||
// fontWeight: FontWeight.bold)),
|
|
||||||
// TextSpan(text: "\n${_item.bottomText}"),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// )),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// class RadioModel {
|
|
||||||
// bool isSelected;
|
|
||||||
// final String svg;
|
|
||||||
// final String topText;
|
|
||||||
// final String bottomText;
|
|
||||||
//
|
|
||||||
// RadioModel(this.isSelected, this.svg, this.topText, this.bottomText);
|
|
||||||
// }
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import 'package:stackwallet/utilities/format.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/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/desktop_app_bar.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
@ -302,68 +303,78 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
ConditionalParent(
|
||||||
width: isDesktop ? 570 : null,
|
condition: isDesktop,
|
||||||
child: ClipRRect(
|
builder: (child) => SizedBox(
|
||||||
borderRadius: BorderRadius.circular(
|
width: 570,
|
||||||
Constants.size.circularBorderRadius,
|
child: child,
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: !isDesktop,
|
||||||
|
builder: (child) => Expanded(
|
||||||
|
child: child,
|
||||||
),
|
),
|
||||||
child: TextField(
|
child: ClipRRect(
|
||||||
autocorrect: !isDesktop,
|
borderRadius: BorderRadius.circular(
|
||||||
enableSuggestions: !isDesktop,
|
Constants.size.circularBorderRadius,
|
||||||
controller: _searchController,
|
),
|
||||||
focusNode: searchFieldFocusNode,
|
child: TextField(
|
||||||
onChanged: (value) {
|
autocorrect: !isDesktop,
|
||||||
setState(() {
|
enableSuggestions: !isDesktop,
|
||||||
_searchString = value;
|
controller: _searchController,
|
||||||
});
|
focusNode: searchFieldFocusNode,
|
||||||
},
|
onChanged: (value) {
|
||||||
style: isDesktop
|
setState(() {
|
||||||
? STextStyles.desktopTextExtraSmall(context)
|
_searchString = value;
|
||||||
.copyWith(
|
});
|
||||||
color: Theme.of(context)
|
},
|
||||||
.extension<StackColors>()!
|
style: isDesktop
|
||||||
.textFieldActiveText,
|
? STextStyles.desktopTextExtraSmall(context)
|
||||||
height: 1.8,
|
.copyWith(
|
||||||
)
|
color: Theme.of(context)
|
||||||
: STextStyles.field(context),
|
.extension<StackColors>()!
|
||||||
decoration: standardInputDecoration(
|
.textFieldActiveText,
|
||||||
"Search...",
|
height: 1.8,
|
||||||
searchFieldFocusNode,
|
|
||||||
context,
|
|
||||||
desktopMed: isDesktop,
|
|
||||||
).copyWith(
|
|
||||||
prefixIcon: Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: isDesktop ? 12 : 10,
|
|
||||||
vertical: isDesktop ? 18 : 16,
|
|
||||||
),
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.svg.search,
|
|
||||||
width: isDesktop ? 20 : 16,
|
|
||||||
height: isDesktop ? 20 : 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
suffixIcon: _searchController.text.isNotEmpty
|
|
||||||
? Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
TextFieldIconButton(
|
|
||||||
child: const XIcon(),
|
|
||||||
onTap: () async {
|
|
||||||
setState(() {
|
|
||||||
_searchController.text = "";
|
|
||||||
_searchString = "";
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: null,
|
: STextStyles.field(context),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Search...",
|
||||||
|
searchFieldFocusNode,
|
||||||
|
context,
|
||||||
|
desktopMed: isDesktop,
|
||||||
|
).copyWith(
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: isDesktop ? 12 : 10,
|
||||||
|
vertical: isDesktop ? 18 : 16,
|
||||||
|
),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.search,
|
||||||
|
width: isDesktop ? 20 : 16,
|
||||||
|
height: isDesktop ? 20 : 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
suffixIcon: _searchController.text.isNotEmpty
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 0),
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
TextFieldIconButton(
|
||||||
|
child: const XIcon(),
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
_searchController.text = "";
|
||||||
|
_searchString = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,6 +10,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
import 'debug_info_dialog.dart';
|
||||||
|
|
||||||
class AdvancedSettings extends ConsumerStatefulWidget {
|
class AdvancedSettings extends ConsumerStatefulWidget {
|
||||||
const AdvancedSettings({Key? key}) : super(key: key);
|
const AdvancedSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -226,16 +228,16 @@ class ShowLogsButton extends ConsumerWidget {
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
// Future<void> viewDebugLogs() async {
|
Future<void> viewDebugLogs() async {
|
||||||
// await showDialog<dynamic>(
|
await showDialog<dynamic>(
|
||||||
// context: context,
|
context: context,
|
||||||
// useSafeArea: false,
|
useSafeArea: false,
|
||||||
// barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
// builder: (context) {
|
builder: (context) {
|
||||||
// return const DebugInfoDialog();
|
return const DebugInfoDialog();
|
||||||
// },
|
},
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 101,
|
width: 101,
|
||||||
|
@ -245,8 +247,7 @@ class ShowLogsButton extends ConsumerWidget {
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getPrimaryEnabledButtonColor(context),
|
.getPrimaryEnabledButtonColor(context),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
//
|
viewDebugLogs();
|
||||||
// viewDebugLogs();
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Show logs",
|
"Show logs",
|
||||||
|
|
|
@ -1,29 +1,33 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/models/isar/models/log.dart';
|
import 'package:stackwallet/models/isar/models/log.dart';
|
||||||
|
import 'package:stackwallet/providers/global/debug_service_provider.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/log_level_enum.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/util.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
import 'package:stackwallet/widgets/desktop/primary_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/x_icon.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||||
|
|
||||||
// import '../../../utilities/assets.dart';
|
class DebugInfoDialog extends ConsumerStatefulWidget {
|
||||||
// import '../../../utilities/util.dart';
|
|
||||||
// import '../../../widgets/icon_widgets/x_icon.dart';
|
|
||||||
// import '../../../widgets/stack_text_field.dart';
|
|
||||||
// import '../../../widgets/textfield_icon_button.dart';
|
|
||||||
|
|
||||||
class DebugInfoDialog extends StatefulWidget {
|
|
||||||
const DebugInfoDialog({Key? key}) : super(key: key);
|
const DebugInfoDialog({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _DebugInfoDialog();
|
ConsumerState<DebugInfoDialog> createState() => _DebugInfoDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DebugInfoDialog extends State<DebugInfoDialog> {
|
class _DebugInfoDialog extends ConsumerState<DebugInfoDialog> {
|
||||||
final _searchController = TextEditingController();
|
late final TextEditingController searchDebugController;
|
||||||
final _searchFocusNode = FocusNode();
|
late final FocusNode searchDebugFocusNode;
|
||||||
|
|
||||||
final scrollController = ScrollController();
|
final scrollController = ScrollController();
|
||||||
|
|
||||||
|
@ -62,15 +66,19 @@ class _DebugInfoDialog extends State<DebugInfoDialog> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// ref.read(debugServiceProvider).updateRecentLogs();
|
searchDebugController = TextEditingController();
|
||||||
|
searchDebugFocusNode = FocusNode();
|
||||||
|
|
||||||
|
ref.read(debugServiceProvider).updateRecentLogs();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_searchController.dispose();
|
searchDebugFocusNode.dispose();
|
||||||
|
searchDebugController.dispose();
|
||||||
|
|
||||||
scrollController.dispose();
|
scrollController.dispose();
|
||||||
_searchFocusNode.dispose();
|
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +86,7 @@ class _DebugInfoDialog extends State<DebugInfoDialog> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DesktopDialog(
|
return DesktopDialog(
|
||||||
maxHeight: 800,
|
maxHeight: 850,
|
||||||
maxWidth: 600,
|
maxWidth: 600,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -96,68 +104,216 @@ class _DebugInfoDialog extends State<DebugInfoDialog> {
|
||||||
const DesktopDialogCloseButton(),
|
const DesktopDialogCloseButton(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Expanded(
|
||||||
children: [
|
flex: 24,
|
||||||
// ClipRRect(
|
child: NestedScrollView(
|
||||||
// borderRadius: BorderRadius.circular(
|
floatHeaderSlivers: true,
|
||||||
// Constants.size.circularBorderRadius,
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
// ),
|
return [
|
||||||
// child: TextField(
|
SliverOverlapAbsorber(
|
||||||
// key: const Key("desktopSettingDebugInfo"),
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
||||||
// autocorrect: Util.isDesktop ? false : true,
|
context),
|
||||||
// enableSuggestions: Util.isDesktop ? false : true,
|
sliver: SliverToBoxAdapter(
|
||||||
// controller: _searchController,
|
child: Padding(
|
||||||
// focusNode: _searchFocusNode,
|
padding: const EdgeInsets.symmetric(
|
||||||
// // onChanged: (newString) {
|
vertical: 16, horizontal: 32),
|
||||||
// // setState(() => _searchTerm = newString);
|
child: Column(
|
||||||
// // },
|
children: [
|
||||||
// style: STextStyles.field(context),
|
Padding(
|
||||||
// decoration: standardInputDecoration(
|
padding: const EdgeInsets.only(bottom: 16),
|
||||||
// "Search",
|
child: ClipRRect(
|
||||||
// _searchFocusNode,
|
borderRadius: BorderRadius.circular(
|
||||||
// context,
|
Constants.size.circularBorderRadius,
|
||||||
// ).copyWith(
|
),
|
||||||
// prefixIcon: Padding(
|
child: TextField(
|
||||||
// padding: const EdgeInsets.symmetric(
|
autocorrect: Util.isDesktop ? false : true,
|
||||||
// horizontal: 10,
|
enableSuggestions:
|
||||||
// vertical: 16,
|
Util.isDesktop ? false : true,
|
||||||
// ),
|
controller: searchDebugController,
|
||||||
// child: SvgPicture.asset(
|
focusNode: searchDebugFocusNode,
|
||||||
// Assets.svg.search,
|
onChanged: (newString) {
|
||||||
// width: 16,
|
setState(() => _searchTerm = newString);
|
||||||
// height: 16,
|
},
|
||||||
// ),
|
style: STextStyles.field(context),
|
||||||
// ),
|
decoration: standardInputDecoration(
|
||||||
// suffixIcon: _searchController.text.isNotEmpty
|
"Search",
|
||||||
// ? Padding(
|
searchDebugFocusNode,
|
||||||
// padding: const EdgeInsets.only(right: 0),
|
context,
|
||||||
// child: UnconstrainedBox(
|
).copyWith(
|
||||||
// child: Row(
|
prefixIcon: Padding(
|
||||||
// children: [
|
padding: const EdgeInsets.symmetric(
|
||||||
// TextFieldIconButton(
|
horizontal: 10,
|
||||||
// child: const XIcon(),
|
vertical: 16,
|
||||||
// onTap: () async {
|
),
|
||||||
// setState(() {
|
child: SvgPicture.asset(
|
||||||
// _searchController.text = "";
|
Assets.svg.search,
|
||||||
// _searchTerm = "";
|
width: 16,
|
||||||
// });
|
height: 16,
|
||||||
// },
|
),
|
||||||
// ),
|
),
|
||||||
// ],
|
suffixIcon: searchDebugController
|
||||||
// ),
|
.text.isNotEmpty
|
||||||
// ),
|
? Padding(
|
||||||
// )
|
padding:
|
||||||
// : null,
|
const EdgeInsets.only(right: 0),
|
||||||
// ),
|
child: UnconstrainedBox(
|
||||||
// ),
|
child: Row(
|
||||||
// ),
|
children: [
|
||||||
],
|
TextFieldIconButton(
|
||||||
|
child: const XIcon(),
|
||||||
|
onTap: () async {
|
||||||
|
setState(() {
|
||||||
|
searchDebugController
|
||||||
|
.text = "";
|
||||||
|
_searchTerm = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final logs = filtered(
|
||||||
|
ref.watch(debugServiceProvider
|
||||||
|
.select((value) => value.recentLogs)),
|
||||||
|
_searchTerm)
|
||||||
|
.reversed
|
||||||
|
.toList(growable: false);
|
||||||
|
return CustomScrollView(
|
||||||
|
reverse: true,
|
||||||
|
// shrinkWrap: true,
|
||||||
|
controller: scrollController,
|
||||||
|
slivers: [
|
||||||
|
SliverOverlapInjector(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
||||||
|
context,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
final log = logs[index];
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
key: Key(
|
||||||
|
"log_${log.id}_${log.timestampInMillisUTC}"),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.popupBG,
|
||||||
|
borderRadius: _borderRadius(index, logs.length),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 32),
|
||||||
|
child: RoundedContainer(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.popupBG,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
" [${log.logLevel.name}]",
|
||||||
|
style: STextStyles.baseXS(context)
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 8,
|
||||||
|
color: (log.logLevel ==
|
||||||
|
LogLevel.Info
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<
|
||||||
|
StackColors>()!
|
||||||
|
.topNavIconGreen
|
||||||
|
: (log.logLevel ==
|
||||||
|
LogLevel.Warning
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<
|
||||||
|
StackColors>()!
|
||||||
|
.topNavIconYellow
|
||||||
|
: (log.logLevel ==
|
||||||
|
LogLevel.Error
|
||||||
|
? Colors.orange
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<
|
||||||
|
StackColors>()!
|
||||||
|
.topNavIconRed))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"[${DateTime.fromMillisecondsSinceEpoch(log.timestampInMillisUTC, isUtc: true)}]: ",
|
||||||
|
style: STextStyles.baseXS(context)
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SelectableText(
|
||||||
|
log.message,
|
||||||
|
style: STextStyles.baseXS(
|
||||||
|
context)
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 11.5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
childCount: logs.length,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// Column(
|
|
||||||
// children: [
|
|
||||||
//
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(32),
|
||||||
|
|
|
@ -1,371 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:flutter_svg/svg.dart';
|
|
||||||
import 'package:stackwallet/providers/global/base_currencies_provider.dart';
|
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
|
||||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
|
||||||
|
|
||||||
class CurrencyDialog extends ConsumerStatefulWidget {
|
|
||||||
const CurrencyDialog({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
ConsumerState<CurrencyDialog> createState() => _CurrencyDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CurrencyDialog extends ConsumerState<CurrencyDialog> {
|
|
||||||
late String current;
|
|
||||||
late List<String> currenciesWithoutSelected;
|
|
||||||
|
|
||||||
late final TextEditingController searchCurrencyController;
|
|
||||||
|
|
||||||
late final FocusNode searchCurrencyFocusNode;
|
|
||||||
|
|
||||||
void onTap(int index) {
|
|
||||||
if (currenciesWithoutSelected[index] == current || current.isEmpty) {
|
|
||||||
// ignore if already selected currency
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
current = currenciesWithoutSelected[index];
|
|
||||||
currenciesWithoutSelected.remove(current);
|
|
||||||
currenciesWithoutSelected.insert(0, current);
|
|
||||||
ref.read(prefsChangeNotifierProvider).currency = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
BorderRadius? _borderRadius(int index) {
|
|
||||||
if (index == 0 && currenciesWithoutSelected.length == 1) {
|
|
||||||
return BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
);
|
|
||||||
} else if (index == 0) {
|
|
||||||
return BorderRadius.vertical(
|
|
||||||
top: Radius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else if (index == currenciesWithoutSelected.length - 1) {
|
|
||||||
return BorderRadius.vertical(
|
|
||||||
bottom: Radius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String filter = "";
|
|
||||||
|
|
||||||
List<String> _filtered() {
|
|
||||||
final currencyMap = ref.read(baseCurrenciesProvider).map;
|
|
||||||
return currenciesWithoutSelected.where((element) {
|
|
||||||
return element.toLowerCase().contains(filter.toLowerCase()) ||
|
|
||||||
(currencyMap[element]?.toLowerCase().contains(filter.toLowerCase()) ??
|
|
||||||
false);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
searchCurrencyController = TextEditingController();
|
|
||||||
|
|
||||||
searchCurrencyFocusNode = FocusNode();
|
|
||||||
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
searchCurrencyController.dispose();
|
|
||||||
|
|
||||||
searchCurrencyFocusNode.dispose();
|
|
||||||
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
current = ref
|
|
||||||
.watch(prefsChangeNotifierProvider.select((value) => value.currency));
|
|
||||||
|
|
||||||
currenciesWithoutSelected = ref
|
|
||||||
.watch(baseCurrenciesProvider.select((value) => value.map))
|
|
||||||
.keys
|
|
||||||
.toList();
|
|
||||||
if (current.isNotEmpty) {
|
|
||||||
currenciesWithoutSelected.remove(current);
|
|
||||||
currenciesWithoutSelected.insert(0, current);
|
|
||||||
}
|
|
||||||
currenciesWithoutSelected = _filtered();
|
|
||||||
|
|
||||||
return DesktopDialog(
|
|
||||||
maxHeight: 800,
|
|
||||||
maxWidth: 600,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(32),
|
|
||||||
child: Text(
|
|
||||||
"Select currency",
|
|
||||||
style: STextStyles.desktopH3(context),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const DesktopDialogCloseButton(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 24,
|
|
||||||
child: NestedScrollView(
|
|
||||||
floatHeaderSlivers: true,
|
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
|
||||||
return [
|
|
||||||
SliverOverlapAbsorber(
|
|
||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
|
||||||
context),
|
|
||||||
sliver: SliverToBoxAdapter(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 16, horizontal: 32),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 16),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
autocorrect: Util.isDesktop ? false : true,
|
|
||||||
enableSuggestions:
|
|
||||||
Util.isDesktop ? false : true,
|
|
||||||
controller: searchCurrencyController,
|
|
||||||
focusNode: searchCurrencyFocusNode,
|
|
||||||
onChanged: (newString) {
|
|
||||||
setState(() => filter = newString);
|
|
||||||
},
|
|
||||||
style: STextStyles.field(context),
|
|
||||||
decoration: standardInputDecoration(
|
|
||||||
"Search",
|
|
||||||
searchCurrencyFocusNode,
|
|
||||||
context,
|
|
||||||
).copyWith(
|
|
||||||
prefixIcon: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 10,
|
|
||||||
vertical: 16,
|
|
||||||
),
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.svg.search,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
suffixIcon: searchCurrencyController
|
|
||||||
.text.isNotEmpty
|
|
||||||
? Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
TextFieldIconButton(
|
|
||||||
child: const XIcon(),
|
|
||||||
onTap: () async {
|
|
||||||
setState(() {
|
|
||||||
searchCurrencyController
|
|
||||||
.text = "";
|
|
||||||
filter = "";
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
},
|
|
||||||
body: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverOverlapInjector(
|
|
||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
|
||||||
context,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.popupBG,
|
|
||||||
borderRadius: _borderRadius(index),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
key: Key(
|
|
||||||
"desktopSettingsCurrencySelect_${currenciesWithoutSelected[index]}"),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 32),
|
|
||||||
child: RoundedContainer(
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
color: currenciesWithoutSelected[index] ==
|
|
||||||
current
|
|
||||||
? Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.currencyListItemBG
|
|
||||||
: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.popupBG,
|
|
||||||
child: RawMaterialButton(
|
|
||||||
onPressed: () async {
|
|
||||||
onTap(index);
|
|
||||||
},
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: Radio(
|
|
||||||
activeColor: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.radioButtonIconEnabled,
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize
|
|
||||||
.shrinkWrap,
|
|
||||||
value: true,
|
|
||||||
groupValue:
|
|
||||||
currenciesWithoutSelected[
|
|
||||||
index] ==
|
|
||||||
current,
|
|
||||||
onChanged: (_) {
|
|
||||||
onTap(index);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
currenciesWithoutSelected[
|
|
||||||
index],
|
|
||||||
key: (currenciesWithoutSelected[
|
|
||||||
index] ==
|
|
||||||
current)
|
|
||||||
? const Key(
|
|
||||||
"desktopSettingsSelectedCurrencyText")
|
|
||||||
: null,
|
|
||||||
style:
|
|
||||||
STextStyles.largeMedium14(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 2,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
ref.watch(baseCurrenciesProvider
|
|
||||||
.select((value) =>
|
|
||||||
value.map))[
|
|
||||||
currenciesWithoutSelected[
|
|
||||||
index]] ??
|
|
||||||
"",
|
|
||||||
key: (currenciesWithoutSelected[
|
|
||||||
index] ==
|
|
||||||
current)
|
|
||||||
? const Key(
|
|
||||||
"desktopSelectedCurrencyTextDescription")
|
|
||||||
: null,
|
|
||||||
style:
|
|
||||||
STextStyles.itemSubtitle(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: currenciesWithoutSelected.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(32),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: SecondaryButton(
|
|
||||||
label: "Cancel",
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 16,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: PrimaryButton(
|
|
||||||
label: "Save Changes",
|
|
||||||
onPressed: () {},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +1,14 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/pages/settings_views/global_settings_view/currency_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';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
import 'currency_dialog.dart';
|
|
||||||
|
|
||||||
class CurrencySettings extends ConsumerStatefulWidget {
|
class CurrencySettings extends ConsumerStatefulWidget {
|
||||||
const CurrencySettings({Key? key}) : super(key: key);
|
const CurrencySettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -84,19 +84,51 @@ class NewPasswordButton extends ConsumerWidget {
|
||||||
const NewPasswordButton({
|
const NewPasswordButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
Future<void> chooseCurrency(BuildContext context) async {
|
||||||
|
// await showDialog<dynamic>(
|
||||||
|
// context: context,
|
||||||
|
// useSafeArea: false,
|
||||||
|
// barrierDismissible: true,
|
||||||
|
// builder: (context) {
|
||||||
|
// return CurrencyDialog();
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
await showDialog<dynamic>(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: false,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (context) {
|
||||||
|
return DesktopDialog(
|
||||||
|
maxHeight: 800,
|
||||||
|
maxWidth: 600,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(32),
|
||||||
|
child: Text(
|
||||||
|
"Select currency",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const DesktopDialogCloseButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
child: BaseCurrencySettingsView(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
Future<void> chooseCurrency() async {
|
|
||||||
await showDialog<dynamic>(
|
|
||||||
context: context,
|
|
||||||
useSafeArea: false,
|
|
||||||
barrierDismissible: true,
|
|
||||||
builder: (context) {
|
|
||||||
return CurrencyDialog();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -105,7 +137,7 @@ class NewPasswordButton extends ConsumerWidget {
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getPrimaryEnabledButtonColor(context),
|
.getPrimaryEnabledButtonColor(context),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
chooseCurrency();
|
chooseCurrency(context);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Change currency",
|
"Change currency",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/language_settings/language_dialog.dart';
|
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/language_settings/language_dialog.dart';
|
||||||
|
@ -86,19 +85,20 @@ class ChangeLanguageButton extends ConsumerWidget {
|
||||||
const ChangeLanguageButton({
|
const ChangeLanguageButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
Future<void> chooseLanguage(BuildContext context) async {
|
||||||
|
await showDialog<dynamic>(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: false,
|
||||||
|
barrierDismissible: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const LanguageDialog();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
Future<void> chooseLanguage() async {
|
|
||||||
await showDialog<dynamic>(
|
|
||||||
context: context,
|
|
||||||
useSafeArea: false,
|
|
||||||
barrierDismissible: true,
|
|
||||||
builder: (context) {
|
|
||||||
return LanguageDialog();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 48,
|
height: 48,
|
||||||
|
@ -107,7 +107,7 @@ class ChangeLanguageButton extends ConsumerWidget {
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getPrimaryEnabledButtonColor(context),
|
.getPrimaryEnabledButtonColor(context),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
chooseLanguage();
|
chooseLanguage(context);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Change language",
|
"Change language",
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart';
|
||||||
import 'package:stackwallet/providers/global/node_service_provider.dart';
|
import 'package:stackwallet/providers/global/node_service_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
import 'package:stackwallet/providers/global/prefs_provider.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/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.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/util.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
|
||||||
class NodesSettings extends ConsumerStatefulWidget {
|
class NodesSettings extends ConsumerStatefulWidget {
|
||||||
const NodesSettings({Key? key}) : super(key: key);
|
const NodesSettings({Key? key}) : super(key: key);
|
||||||
|
@ -23,15 +26,27 @@ class NodesSettings extends ConsumerStatefulWidget {
|
||||||
class _NodesSettings extends ConsumerState<NodesSettings> {
|
class _NodesSettings extends ConsumerState<NodesSettings> {
|
||||||
List<Coin> _coins = [...Coin.values];
|
List<Coin> _coins = [...Coin.values];
|
||||||
|
|
||||||
|
late final TextEditingController searchNodeController;
|
||||||
|
late final FocusNode searchNodeFocusNode;
|
||||||
|
|
||||||
|
String filter = "";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_coins = _coins.toList();
|
_coins = _coins.toList();
|
||||||
_coins.remove(Coin.firoTestNet);
|
_coins.remove(Coin.firoTestNet);
|
||||||
|
|
||||||
|
searchNodeController = TextEditingController();
|
||||||
|
searchNodeFocusNode = FocusNode();
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
searchNodeController.dispose();
|
||||||
|
searchNodeFocusNode.dispose();
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +62,7 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
||||||
|
|
||||||
debugPrint("BUILD: $runtimeType");
|
debugPrint("BUILD: $runtimeType");
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
@ -55,6 +71,7 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
||||||
child: RoundedWhiteContainer(
|
child: RoundedWhiteContainer(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.svg.circleNode,
|
Assets.svg.circleNode,
|
||||||
|
@ -63,6 +80,7 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
|
@ -85,88 +103,145 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
//TODO: add search bar
|
Padding(
|
||||||
SingleChildScrollView(
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: Column(
|
child: ClipRRect(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
borderRadius: BorderRadius.circular(
|
||||||
children: [
|
Constants.size.circularBorderRadius,
|
||||||
...coins.map(
|
),
|
||||||
(coin) {
|
child: TextField(
|
||||||
final count = ref
|
autocorrect: Util.isDesktop ? false : true,
|
||||||
.watch(nodeServiceChangeNotifierProvider
|
enableSuggestions: Util.isDesktop ? false : true,
|
||||||
.select((value) => value.getNodesFor(coin)))
|
controller: searchNodeController,
|
||||||
.length;
|
focusNode: searchNodeFocusNode,
|
||||||
|
onChanged: (newString) {
|
||||||
|
setState(() => filter = newString);
|
||||||
|
},
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Search",
|
||||||
|
searchNodeFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.search,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: RoundedWhiteContainer(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
borderColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
child: ListView.separated(
|
||||||
|
primary: false,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final coin = coins[index];
|
||||||
|
final count = ref
|
||||||
|
.watch(nodeServiceChangeNotifierProvider
|
||||||
|
.select((value) => value.getNodesFor(coin)))
|
||||||
|
.length;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
child: RawMaterialButton(
|
child: RawMaterialButton(
|
||||||
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(
|
borderRadius: BorderRadius.circular(
|
||||||
Constants.size.circularBorderRadius,
|
Constants.size.circularBorderRadius,
|
||||||
),
|
|
||||||
// side: BorderSide(
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .shadow),
|
|
||||||
),
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
CoinNodesView.routeName,
|
|
||||||
arguments: coin,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(
|
|
||||||
12.0,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
SvgPicture.asset(
|
|
||||||
Assets.svg.iconFor(coin: coin),
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"${coin.prettyName} nodes",
|
|
||||||
style: STextStyles.titleBold12(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
count > 1
|
|
||||||
? "$count nodes"
|
|
||||||
: "Default",
|
|
||||||
style: STextStyles.label(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.svg.chevronRight,
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
materialTapTargetSize:
|
||||||
},
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
onPressed: () {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Navigator(
|
||||||
|
initialRoute: CoinNodesView.routeName,
|
||||||
|
onGenerateRoute: RouteGenerator.generateRoute,
|
||||||
|
onGenerateInitialRoutes: (_, __) {
|
||||||
|
return [
|
||||||
|
FadePageRoute(
|
||||||
|
CoinNodesView(
|
||||||
|
coin: coin,
|
||||||
|
rootNavigator: true,
|
||||||
|
),
|
||||||
|
const RouteSettings(
|
||||||
|
name: CoinNodesView.routeName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(
|
||||||
|
12.0,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.iconFor(coin: coin),
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${coin.prettyName} nodes",
|
||||||
|
style: STextStyles.titleBold12(
|
||||||
|
context),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
count > 1
|
||||||
|
? "$count nodes"
|
||||||
|
: "Default",
|
||||||
|
style: STextStyles.label(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.chevronRight,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (context, index) => Container(
|
||||||
|
height: 1,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.background,
|
||||||
),
|
),
|
||||||
],
|
itemCount: coins.length,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -7,6 +7,8 @@ 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/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
import '../../../pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart';
|
||||||
|
|
||||||
class SyncingPreferencesSettings extends ConsumerStatefulWidget {
|
class SyncingPreferencesSettings extends ConsumerStatefulWidget {
|
||||||
const SyncingPreferencesSettings({Key? key}) : super(key: key);
|
const SyncingPreferencesSettings({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -62,6 +64,13 @@ class _SyncingPreferencesSettings
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
///TODO: ONLY SHOW SYNC OPTIONS ON BUTTON PRESS
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SyncingOptionsView(),
|
||||||
|
],
|
||||||
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: const [
|
children: const [
|
||||||
|
|
|
@ -1468,6 +1468,20 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ButtonStyle? getDeleteEnabledButtonColor(BuildContext context) =>
|
||||||
|
Theme.of(context).textButtonTheme.style?.copyWith(
|
||||||
|
backgroundColor: MaterialStateProperty.all<Color>(
|
||||||
|
textFieldErrorBG,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
ButtonStyle? getDeleteDisabledButtonColor(BuildContext context) =>
|
||||||
|
Theme.of(context).textButtonTheme.style?.copyWith(
|
||||||
|
backgroundColor: MaterialStateProperty.all<Color>(
|
||||||
|
buttonBackSecondaryDisabled,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
ButtonStyle? getPrimaryEnabledButtonColor(BuildContext context) =>
|
ButtonStyle? getPrimaryEnabledButtonColor(BuildContext context) =>
|
||||||
Theme.of(context).textButtonTheme.style?.copyWith(
|
Theme.of(context).textButtonTheme.style?.copyWith(
|
||||||
backgroundColor: MaterialStateProperty.all<Color>(
|
backgroundColor: MaterialStateProperty.all<Color>(
|
||||||
|
|
98
lib/widgets/desktop/delete_button.dart
Normal file
98
lib/widgets/desktop/delete_button.dart
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/custom_text_button.dart';
|
||||||
|
|
||||||
|
class DeleteButton extends StatelessWidget {
|
||||||
|
const DeleteButton({
|
||||||
|
Key? key,
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
|
this.label,
|
||||||
|
this.onPressed,
|
||||||
|
this.enabled = true,
|
||||||
|
this.desktopMed = false,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
final String? label;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final bool enabled;
|
||||||
|
final bool desktopMed;
|
||||||
|
|
||||||
|
TextStyle getStyle(bool isDesktop, BuildContext context) {
|
||||||
|
if (isDesktop) {
|
||||||
|
if (desktopMed) {
|
||||||
|
return STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||||
|
color: enabled
|
||||||
|
? Theme.of(context).extension<StackColors>()!.accentColorRed
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextSecondaryDisabled,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return enabled
|
||||||
|
? STextStyles.desktopButtonSecondaryEnabled(context).copyWith(
|
||||||
|
color:
|
||||||
|
Theme.of(context).extension<StackColors>()!.accentColorRed)
|
||||||
|
: STextStyles.desktopButtonSecondaryDisabled(context);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return STextStyles.button(context).copyWith(
|
||||||
|
color: enabled
|
||||||
|
? Theme.of(context).extension<StackColors>()!.accentColorRed
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextSecondaryDisabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
|
return CustomTextButtonBase(
|
||||||
|
height: desktopMed ? 56 : height,
|
||||||
|
width: width,
|
||||||
|
textButton: TextButton(
|
||||||
|
onPressed: enabled ? onPressed : null,
|
||||||
|
style: enabled
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getDeleteEnabledButtonColor(context)
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getDeleteDisabledButtonColor(context),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.trash,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
color: enabled
|
||||||
|
? Theme.of(context).extension<StackColors>()!.accentColorRed
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextSecondaryDisabled,
|
||||||
|
),
|
||||||
|
if (label != null)
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
if (label != null)
|
||||||
|
Text(
|
||||||
|
label!,
|
||||||
|
style: getStyle(isDesktop, context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ description: Stack Wallet
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.5.13+85
|
version: 1.5.14+86
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
Loading…
Reference in a new issue