Merge pull request #201 from cypherstack/desktop

Desktop
This commit is contained in:
Diego Salazar 2022-11-03 19:40:52 -06:00 committed by GitHub
commit fe44b14453
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1970 additions and 1740 deletions

View file

@ -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) {

View file

@ -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),
),
),
],
), ),
), ),
); );

View file

@ -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,
),
);
},
), ),
], ],
), ),

View file

@ -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,
),
],
), ),
), ),
); );

View file

@ -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,
),
],
),
),
),
],
),
),
),
],
),
),
],
), ),
); );
} }

View file

@ -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 {
), ),
), ),
), ),
), );
); }),
}), ),
); );
} }
} }

View file

@ -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);
// }

View file

@ -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,
),
), ),
), ),
), ),

View file

@ -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",

View file

@ -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),

View file

@ -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: () {},
),
)
],
),
),
],
),
);
}
}

View file

@ -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",

View file

@ -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",

View file

@ -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,
),
), ),
), ),
], ],

View file

@ -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 [

View file

@ -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>(

View 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),
),
],
),
),
);
}
}

View file

@ -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"