refactoring for recipient addition page
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class ChoiceChips<T> extends StatelessWidget {
|
||||
final String label;
|
||||
final List<T> values;
|
||||
final T selected;
|
||||
final ValueChanged<T> onChanged;
|
||||
|
||||
final double spacing;
|
||||
final double runSpacing;
|
||||
final double labelSpacing;
|
||||
|
||||
const ChoiceChips({
|
||||
super.key,
|
||||
required this.label,
|
||||
required this.values,
|
||||
required this.selected,
|
||||
required this.onChanged,
|
||||
this.spacing = 8,
|
||||
this.runSpacing = 8,
|
||||
this.labelSpacing = 8,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: theme.textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
SizedBox(height: labelSpacing),
|
||||
Wrap(
|
||||
spacing: spacing,
|
||||
runSpacing: runSpacing,
|
||||
children: values.map((v) {
|
||||
final isSelected = v == selected;
|
||||
return ChoiceChip(
|
||||
selectedColor: theme.colorScheme.primary,
|
||||
backgroundColor: theme.colorScheme.onSecondary,
|
||||
showCheckmark: false,
|
||||
label: Text(
|
||||
v.toString().split('.').last,
|
||||
style: TextStyle(
|
||||
color: isSelected
|
||||
? theme.colorScheme.onSecondary
|
||||
: theme.colorScheme.inverseSurface,
|
||||
),
|
||||
),
|
||||
selected: isSelected,
|
||||
onSelected: (_) => onChanged(v),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
import 'package:pweb/pages/address_book/form/widgets/feilds/recipient_text_field.dart';
|
||||
|
||||
|
||||
class EmailField extends StatelessWidget {
|
||||
@@ -20,17 +21,16 @@ class EmailField extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return TextFormField(
|
||||
return RecipientTextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: loc.username,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
contentPadding: contentPadding,
|
||||
),
|
||||
validator: (v) =>
|
||||
v == null || v.isEmpty ? loc.usernameErrorInvalid : null,
|
||||
labelText: loc.username,
|
||||
hintText: loc.usernameHint,
|
||||
icon: Icons.alternate_email,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
autofillHints: const [AutofillHints.email],
|
||||
validator: (v) => v == null || v.isEmpty ? loc.usernameErrorInvalid : null,
|
||||
borderRadius: borderRadius,
|
||||
contentPadding: contentPadding,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
import 'package:pweb/pages/address_book/form/widgets/feilds/recipient_text_field.dart';
|
||||
|
||||
|
||||
class NameField extends StatelessWidget {
|
||||
@@ -20,16 +21,16 @@ class NameField extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return TextFormField(
|
||||
return RecipientTextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: loc.recipientName,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
contentPadding: contentPadding,
|
||||
),
|
||||
labelText: loc.recipientName,
|
||||
hintText: loc.recipientNameHint,
|
||||
icon: Icons.person_outline,
|
||||
textCapitalization: TextCapitalization.words,
|
||||
autofillHints: const [AutofillHints.name],
|
||||
validator: (v) => v == null || v.isEmpty ? loc.enterRecipientName : null,
|
||||
borderRadius: borderRadius,
|
||||
contentPadding: contentPadding,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class RecipientTextField extends StatelessWidget {
|
||||
final TextEditingController controller;
|
||||
final String labelText;
|
||||
final String hintText;
|
||||
final String? helperText;
|
||||
final IconData icon;
|
||||
final TextInputType keyboardType;
|
||||
final TextInputAction textInputAction;
|
||||
final TextCapitalization textCapitalization;
|
||||
final Iterable<String>? autofillHints;
|
||||
final FormFieldValidator<String>? validator;
|
||||
final double borderRadius;
|
||||
final EdgeInsetsGeometry contentPadding;
|
||||
|
||||
const RecipientTextField({
|
||||
super.key,
|
||||
required this.controller,
|
||||
required this.labelText,
|
||||
required this.hintText,
|
||||
required this.icon,
|
||||
this.helperText,
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.textInputAction = TextInputAction.next,
|
||||
this.textCapitalization = TextCapitalization.none,
|
||||
this.autofillHints,
|
||||
this.validator,
|
||||
this.borderRadius = 12,
|
||||
this.contentPadding = const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return ValueListenableBuilder<TextEditingValue>(
|
||||
valueListenable: controller,
|
||||
builder: (context, value, _) {
|
||||
final isEmpty = value.text.trim().isEmpty;
|
||||
final errorColor = theme.colorScheme.error;
|
||||
final neutralBorder = theme.colorScheme.onSurface.withAlpha(40);
|
||||
final borderColor = isEmpty ? errorColor : neutralBorder;
|
||||
final focusedColor = isEmpty ? errorColor : theme.colorScheme.primary;
|
||||
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
keyboardType: keyboardType,
|
||||
textInputAction: textInputAction,
|
||||
textCapitalization: textCapitalization,
|
||||
autofillHints: autofillHints,
|
||||
decoration: InputDecoration(
|
||||
labelText: labelText,
|
||||
hintText: hintText,
|
||||
helperText: helperText,
|
||||
prefixIcon: Icon(icon, color: isEmpty ? errorColor : null),
|
||||
filled: true,
|
||||
fillColor: theme.colorScheme.onSecondary,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
borderSide: BorderSide(color: borderColor),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
borderSide: BorderSide(color: focusedColor, width: 1.4),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
borderSide: BorderSide(color: errorColor),
|
||||
),
|
||||
focusedErrorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
borderSide: BorderSide(color: errorColor, width: 1.4),
|
||||
),
|
||||
contentPadding: contentPadding,
|
||||
),
|
||||
validator: validator,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/icon.dart';
|
||||
import 'package:pweb/utils/payment/label.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class AddPaymentMethodButton extends StatelessWidget {
|
||||
final List<PaymentType> types;
|
||||
final Set<PaymentType> disabledTypes;
|
||||
final ValueChanged<PaymentType> onAdd;
|
||||
|
||||
static const double _borderRadius = 14;
|
||||
static const double _iconSize = 18;
|
||||
static const double _iconTextSpacing = 8;
|
||||
static const double _menuIconSize = 18;
|
||||
static const double _menuIconTextSpacing = 8;
|
||||
static const double _buttonHeight = 70;
|
||||
static const EdgeInsets _buttonPadding = EdgeInsets.symmetric(horizontal: 14, vertical: 10);
|
||||
static const FontWeight _labelWeight = FontWeight.w600;
|
||||
|
||||
const AddPaymentMethodButton({
|
||||
required this.types,
|
||||
required this.disabledTypes,
|
||||
required this.onAdd,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final hasEnabled = types.any((type) => !disabledTypes.contains(type));
|
||||
final borderColor = hasEnabled
|
||||
? theme.colorScheme.primary.withValues(alpha: 0.5)
|
||||
: theme.colorScheme.onSurface.withValues(alpha: 0.2);
|
||||
final textColor = hasEnabled
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface.withValues(alpha: 0.4);
|
||||
|
||||
return PopupMenuButton<PaymentType>(
|
||||
enabled: hasEnabled,
|
||||
onSelected: onAdd,
|
||||
itemBuilder: (context) => types
|
||||
.map((type) {
|
||||
final isDisabled = disabledTypes.contains(type);
|
||||
return PopupMenuItem<PaymentType>(
|
||||
value: type,
|
||||
enabled: !isDisabled,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
iconForPaymentType(type),
|
||||
size: _menuIconSize,
|
||||
color: isDisabled
|
||||
? theme.colorScheme.onSurface.withValues(alpha: 0.4)
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: _menuIconTextSpacing),
|
||||
Text(getPaymentTypeLabel(context, type)),
|
||||
],
|
||||
),
|
||||
);
|
||||
})
|
||||
.toList(),
|
||||
child: Container(
|
||||
height: _buttonHeight,
|
||||
padding: _buttonPadding,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(_borderRadius),
|
||||
border: Border.all(color: borderColor),
|
||||
color: theme.colorScheme.onSecondary,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.add, size: _iconSize, color: textColor),
|
||||
const SizedBox(width: _iconTextSpacing),
|
||||
Text(
|
||||
l10n.addPaymentMethod,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
color: textColor,
|
||||
fontWeight: _labelWeight,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/payment_method_draft.dart';
|
||||
|
||||
import 'package:pweb/pages/payment_methods/form.dart';
|
||||
import 'package:pweb/pages/payment_methods/icon.dart';
|
||||
import 'package:pweb/widgets/dialogs/confirmation_dialog.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentMethodPanel extends StatelessWidget {
|
||||
final PaymentType selectedType;
|
||||
final int selectedIndex;
|
||||
final List<RecipientMethodDraft> entries;
|
||||
final ValueChanged<int> onRemove;
|
||||
final void Function(int, PaymentMethodData) onChanged;
|
||||
|
||||
final double padding;
|
||||
|
||||
const PaymentMethodPanel({
|
||||
super.key,
|
||||
required this.selectedType,
|
||||
required this.selectedIndex,
|
||||
required this.entries,
|
||||
required this.onRemove,
|
||||
required this.onChanged,
|
||||
this.padding = 16,
|
||||
});
|
||||
|
||||
Future<void> _confirmDelete(BuildContext context, VoidCallback onConfirmed) async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final confirmed = await showConfirmationDialog(
|
||||
context: context,
|
||||
title: l10n.delete,
|
||||
message: l10n.deletePaymentConfirmation,
|
||||
confirmLabel: l10n.delete,
|
||||
);
|
||||
if (confirmed) {
|
||||
onConfirmed();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final label = l10n.paymentMethodDetails;
|
||||
final entry = selectedIndex >= 0 && selectedIndex < entries.length
|
||||
? entries[selectedIndex]
|
||||
: null;
|
||||
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 3000),
|
||||
padding: EdgeInsets.all(padding),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.onSecondary,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: theme.colorScheme.onSurface.withAlpha(30)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
iconForPaymentType(selectedType),
|
||||
size: 18,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (entry != null)
|
||||
TextButton.icon(
|
||||
onPressed: () => _confirmDelete(context, () => onRemove(selectedIndex)),
|
||||
icon: Icon(Icons.delete, color: theme.colorScheme.error),
|
||||
label: Text(
|
||||
l10n.delete,
|
||||
style: TextStyle(color: theme.colorScheme.error),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
if (entry != null)
|
||||
PaymentMethodForm(
|
||||
key: ValueKey('${selectedType.name}-${entry.existing?.id ?? selectedIndex}-form'),
|
||||
selectedType: selectedType,
|
||||
initialData: entry.data,
|
||||
onChanged: (data) {
|
||||
if (data == null) return;
|
||||
onChanged(selectedIndex, data);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/payment_method_draft.dart';
|
||||
|
||||
import 'package:pweb/models/payment_method_tile/availability.dart';
|
||||
import 'package:pweb/models/payment_method_tile/selection.dart';
|
||||
import 'package:pweb/pages/address_book/form/widgets/payment_methods/add_button.dart';
|
||||
import 'package:pweb/pages/address_book/form/widgets/payment_methods/tile.dart';
|
||||
|
||||
|
||||
class PaymentMethodSelectorRow extends StatelessWidget {
|
||||
final List<PaymentType> types;
|
||||
final PaymentType selectedType;
|
||||
final int? selectedIndex;
|
||||
final Map<PaymentType, List<RecipientMethodDraft>> methods;
|
||||
final void Function(PaymentType type, int index) onSelected;
|
||||
final ValueChanged<PaymentType> onAdd;
|
||||
final Set<PaymentType> disabledTypes;
|
||||
|
||||
final double spacing;
|
||||
final double tilePadding;
|
||||
final double runSpacing;
|
||||
|
||||
const PaymentMethodSelectorRow({
|
||||
super.key,
|
||||
required this.types,
|
||||
required this.selectedType,
|
||||
required this.selectedIndex,
|
||||
required this.methods,
|
||||
required this.onSelected,
|
||||
required this.onAdd,
|
||||
this.disabledTypes = const {},
|
||||
this.spacing = 12,
|
||||
this.tilePadding = 10,
|
||||
this.runSpacing = 12,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tiles = <Widget>[];
|
||||
for (final type in types) {
|
||||
final entries = methods[type] ?? const <RecipientMethodDraft>[];
|
||||
for (var index = 0; index < entries.length; index += 1) {
|
||||
final entry = entries[index];
|
||||
final isSelected = type == selectedType && selectedIndex == index;
|
||||
final selection = isSelected
|
||||
? PaymentMethodTileSelection.selected
|
||||
: PaymentMethodTileSelection.idle;
|
||||
final isAdded = entry.data != null || entry.existing != null;
|
||||
final availability = isAdded
|
||||
? PaymentMethodTileAvailability.added
|
||||
: PaymentMethodTileAvailability.available;
|
||||
tiles.add(
|
||||
PaymentMethodTile(
|
||||
type: type,
|
||||
selection: selection,
|
||||
availability: availability,
|
||||
padding: tilePadding,
|
||||
onTap: () => onSelected(type, index),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
tiles.add(
|
||||
AddPaymentMethodButton(
|
||||
types: types,
|
||||
disabledTypes: disabledTypes,
|
||||
onAdd: onAdd,
|
||||
),
|
||||
);
|
||||
|
||||
return Wrap(
|
||||
spacing: spacing,
|
||||
runSpacing: runSpacing,
|
||||
alignment: WrapAlignment.start,
|
||||
children: tiles,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
import 'package:pweb/models/payment_method_tile/availability.dart';
|
||||
import 'package:pweb/models/payment_method_tile/selection.dart';
|
||||
import 'package:pweb/pages/payment_methods/icon.dart';
|
||||
import 'package:pweb/utils/payment/label.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentMethodTile extends StatelessWidget {
|
||||
final PaymentType type;
|
||||
final PaymentMethodTileSelection selection;
|
||||
final PaymentMethodTileAvailability availability;
|
||||
final double padding;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
const PaymentMethodTile({
|
||||
required this.type,
|
||||
required this.selection,
|
||||
required this.availability,
|
||||
required this.padding,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final label = getPaymentTypeLabel(context, type);
|
||||
final badgeLabel = switch (availability) {
|
||||
PaymentMethodTileAvailability.added => l10n.paymentMethodAdded,
|
||||
PaymentMethodTileAvailability.comingSoon => l10n.paymentMethodComingSoon,
|
||||
PaymentMethodTileAvailability.available => l10n.paymentMethodNotAdded,
|
||||
};
|
||||
final isSelected = selection == PaymentMethodTileSelection.selected;
|
||||
final isDisabled = availability == PaymentMethodTileAvailability.comingSoon;
|
||||
final disabledOpacity = isDisabled ? 0.55 : 1.0;
|
||||
final badgeColor = availability == PaymentMethodTileAvailability.added
|
||||
? theme.colorScheme.primary.withValues(alpha: 0.12)
|
||||
: theme.colorScheme.onSurface.withValues(alpha: isDisabled ? 0.06 : 0.08);
|
||||
final badgeTextColor = availability == PaymentMethodTileAvailability.added
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface.withValues(alpha: isDisabled ? 0.6 : 1.0);
|
||||
final borderColor = isSelected
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface.withValues(alpha: 0.12);
|
||||
final backgroundColor = isSelected
|
||||
? theme.colorScheme.primary.withValues(alpha: 0.08)
|
||||
: theme.colorScheme.onSecondary;
|
||||
|
||||
return IntrinsicWidth(
|
||||
child: Opacity(
|
||||
opacity: disabledOpacity,
|
||||
child: Material(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 160),
|
||||
padding: EdgeInsets.all(padding),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: borderColor),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
iconForPaymentType(type),
|
||||
size: 20,
|
||||
color: isSelected ? theme.colorScheme.primary : theme.colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
label,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isSelected ? theme.colorScheme.primary : theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: badgeColor,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
badgeLabel,
|
||||
style: theme.textTheme.labelSmall?.copyWith(
|
||||
color: badgeTextColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,10 @@ class SaveButton extends StatelessWidget {
|
||||
child: Text(
|
||||
text ?? AppLocalizations.of(context)!.saveRecipient,
|
||||
style: textStyle ??
|
||||
theme.textTheme.labelLarge?.copyWith(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
theme.textTheme.labelLarge?.copyWith(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Reference in New Issue
Block a user