💄 Update the account settings to match the app settings style
This commit is contained in:
@@ -135,81 +135,73 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
ref
|
ref
|
||||||
.watch(accountConnectionsProvider)
|
.watch(accountConnectionsProvider)
|
||||||
.when(
|
.when(
|
||||||
data:
|
data: (connections) => Column(
|
||||||
(connections) => Column(
|
children: [
|
||||||
children: [
|
for (final connection in connections)
|
||||||
for (final connection in connections)
|
ListTile(
|
||||||
ListTile(
|
minLeadingWidth: 48,
|
||||||
minLeadingWidth: 48,
|
contentPadding: const EdgeInsets.only(
|
||||||
contentPadding: const EdgeInsets.only(
|
left: 16,
|
||||||
left: 16,
|
right: 17,
|
||||||
right: 17,
|
top: 2,
|
||||||
top: 2,
|
bottom: 4,
|
||||||
bottom: 4,
|
|
||||||
),
|
|
||||||
title:
|
|
||||||
Text(
|
|
||||||
getLocalizedProviderName(connection.provider),
|
|
||||||
).tr(),
|
|
||||||
subtitle:
|
|
||||||
connection.meta['email'] != null
|
|
||||||
? Text(connection.meta['email'])
|
|
||||||
: Text(connection.providedIdentifier),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
child: getProviderIcon(
|
|
||||||
connection.provider,
|
|
||||||
size: 16,
|
|
||||||
color:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onPrimaryContainer,
|
|
||||||
),
|
|
||||||
).padding(top: 4),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => AccountConnectionSheet(
|
|
||||||
connection: connection,
|
|
||||||
),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(accountConnectionsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (connections.isNotEmpty) const Divider(height: 1),
|
|
||||||
ListTile(
|
|
||||||
minLeadingWidth: 48,
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 24,
|
|
||||||
right: 17,
|
|
||||||
),
|
|
||||||
title: Text('accountConnectionAdd').tr(),
|
|
||||||
leading: const Icon(Symbols.add),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) =>
|
|
||||||
const AccountConnectionNewSheet(),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(accountConnectionsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
title: Text(
|
||||||
),
|
getLocalizedProviderName(connection.provider),
|
||||||
error:
|
).tr(),
|
||||||
(err, _) => ResponseErrorWidget(
|
subtitle: connection.meta['email'] != null
|
||||||
error: err,
|
? Text(connection.meta['email'])
|
||||||
onRetry: () => ref.invalidate(accountConnectionsProvider),
|
: Text(connection.providedIdentifier),
|
||||||
|
leading: CircleAvatar(
|
||||||
|
child: getProviderIcon(
|
||||||
|
connection.provider,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onPrimaryContainer,
|
||||||
|
),
|
||||||
|
).padding(top: 4),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
AccountConnectionSheet(connection: connection),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(accountConnectionsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (connections.isNotEmpty) const Divider(height: 1),
|
||||||
|
ListTile(
|
||||||
|
minLeadingWidth: 48,
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
left: 24,
|
||||||
|
right: 17,
|
||||||
|
),
|
||||||
|
title: Text('accountConnectionAdd').tr(),
|
||||||
|
leading: const Icon(Symbols.add),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
const AccountConnectionNewSheet(),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(accountConnectionsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (err, _) => ResponseErrorWidget(
|
||||||
|
error: err,
|
||||||
|
onRetry: () => ref.invalidate(accountConnectionsProvider),
|
||||||
|
),
|
||||||
loading: () => const ResponseLoadingWidget(),
|
loading: () => const ResponseLoadingWidget(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -223,95 +215,76 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
tilePadding: const EdgeInsets.only(left: 24, right: 17),
|
tilePadding: const EdgeInsets.only(left: 24, right: 17),
|
||||||
children: [
|
children: [
|
||||||
authFactors.when(
|
authFactors.when(
|
||||||
data:
|
data: (factors) => Column(
|
||||||
(factors) => Column(
|
children: [
|
||||||
children: [
|
for (final factor in factors)
|
||||||
for (final factor in factors)
|
ListTile(
|
||||||
ListTile(
|
minLeadingWidth: 48,
|
||||||
minLeadingWidth: 48,
|
contentPadding: const EdgeInsets.only(
|
||||||
contentPadding: const EdgeInsets.only(
|
left: 16,
|
||||||
left: 16,
|
right: 17,
|
||||||
right: 17,
|
top: 2,
|
||||||
top: 2,
|
bottom: 4,
|
||||||
bottom: 4,
|
|
||||||
),
|
|
||||||
title:
|
|
||||||
Text(
|
|
||||||
kFactorTypes[factor.type]!.$1,
|
|
||||||
style:
|
|
||||||
factor.enabledAt == null
|
|
||||||
? TextStyle(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
).tr(),
|
|
||||||
subtitle:
|
|
||||||
Text(
|
|
||||||
kFactorTypes[factor.type]!.$2,
|
|
||||||
style:
|
|
||||||
factor.enabledAt == null
|
|
||||||
? TextStyle(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
).tr(),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
factor.enabledAt == null
|
|
||||||
? Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.secondaryContainer
|
|
||||||
: Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.primaryContainer,
|
|
||||||
child: Icon(kFactorTypes[factor.type]!.$3),
|
|
||||||
).padding(top: 4),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
isThreeLine: true,
|
|
||||||
onTap: () {
|
|
||||||
if (factor.type == 0) {
|
|
||||||
requestResetPassword();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => AuthFactorSheet(factor: factor),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(authFactorsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (factors.isNotEmpty) Divider(height: 1),
|
|
||||||
ListTile(
|
|
||||||
minLeadingWidth: 48,
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 24,
|
|
||||||
right: 17,
|
|
||||||
),
|
|
||||||
title: Text('authFactorNew').tr(),
|
|
||||||
leading: const Icon(Symbols.add),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => const AuthFactorNewSheet(),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(authFactorsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
title: Text(
|
||||||
),
|
kFactorTypes[factor.type]!.$1,
|
||||||
error:
|
style: factor.enabledAt == null
|
||||||
(err, _) => ResponseErrorWidget(
|
? TextStyle(decoration: TextDecoration.lineThrough)
|
||||||
error: err,
|
: null,
|
||||||
onRetry: () => ref.invalidate(authFactorsProvider),
|
).tr(),
|
||||||
|
subtitle: Text(
|
||||||
|
kFactorTypes[factor.type]!.$2,
|
||||||
|
style: factor.enabledAt == null
|
||||||
|
? TextStyle(decoration: TextDecoration.lineThrough)
|
||||||
|
: null,
|
||||||
|
).tr(),
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor: factor.enabledAt == null
|
||||||
|
? Theme.of(context).colorScheme.secondaryContainer
|
||||||
|
: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
child: Icon(kFactorTypes[factor.type]!.$3),
|
||||||
|
).padding(top: 4),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
isThreeLine: true,
|
||||||
|
onTap: () {
|
||||||
|
if (factor.type == 0) {
|
||||||
|
requestResetPassword();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AuthFactorSheet(factor: factor),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(authFactorsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (factors.isNotEmpty) Divider(height: 1),
|
||||||
|
ListTile(
|
||||||
|
minLeadingWidth: 48,
|
||||||
|
contentPadding: const EdgeInsets.only(left: 24, right: 17),
|
||||||
|
title: Text('authFactorNew').tr(),
|
||||||
|
leading: const Icon(Symbols.add),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const AuthFactorNewSheet(),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(authFactorsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (err, _) => ResponseErrorWidget(
|
||||||
|
error: err,
|
||||||
|
onRetry: () => ref.invalidate(authFactorsProvider),
|
||||||
|
),
|
||||||
loading: () => ResponseLoadingWidget(),
|
loading: () => ResponseLoadingWidget(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -327,97 +300,84 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
ref
|
ref
|
||||||
.watch(contactMethodsProvider)
|
.watch(contactMethodsProvider)
|
||||||
.when(
|
.when(
|
||||||
data:
|
data: (contacts) => Column(
|
||||||
(contacts) => Column(
|
children: [
|
||||||
children: [
|
for (final contact in contacts)
|
||||||
for (final contact in contacts)
|
ListTile(
|
||||||
ListTile(
|
minLeadingWidth: 48,
|
||||||
minLeadingWidth: 48,
|
contentPadding: const EdgeInsets.only(
|
||||||
contentPadding: const EdgeInsets.only(
|
left: 16,
|
||||||
left: 16,
|
right: 17,
|
||||||
right: 17,
|
top: 2,
|
||||||
top: 2,
|
bottom: 4,
|
||||||
bottom: 4,
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
contact.content,
|
|
||||||
style:
|
|
||||||
contact.verifiedAt == null
|
|
||||||
? TextStyle(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
contact.type == 0
|
|
||||||
? 'contactMethodTypeEmail'.tr()
|
|
||||||
: 'contactMethodTypePhone'.tr(),
|
|
||||||
style:
|
|
||||||
contact.verifiedAt == null
|
|
||||||
? TextStyle(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
contact.verifiedAt == null
|
|
||||||
? Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.secondaryContainer
|
|
||||||
: Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.primaryContainer,
|
|
||||||
child: Icon(
|
|
||||||
contact.type == 0
|
|
||||||
? Symbols.mail
|
|
||||||
: Symbols.phone,
|
|
||||||
),
|
|
||||||
).padding(top: 4),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
isThreeLine: false,
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) =>
|
|
||||||
ContactMethodSheet(contact: contact),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(contactMethodsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (contacts.isNotEmpty) const Divider(height: 1),
|
|
||||||
ListTile(
|
|
||||||
minLeadingWidth: 48,
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 24,
|
|
||||||
right: 17,
|
|
||||||
),
|
|
||||||
title: Text('contactMethodNew').tr(),
|
|
||||||
leading: const Icon(Symbols.add),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => const ContactMethodNewSheet(),
|
|
||||||
).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
ref.invalidate(contactMethodsProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
title: Text(
|
||||||
),
|
contact.content,
|
||||||
error:
|
style: contact.verifiedAt == null
|
||||||
(err, _) => ResponseErrorWidget(
|
? TextStyle(
|
||||||
error: err,
|
decoration: TextDecoration.lineThrough,
|
||||||
onRetry: () => ref.invalidate(contactMethodsProvider),
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
contact.type == 0
|
||||||
|
? 'contactMethodTypeEmail'.tr()
|
||||||
|
: 'contactMethodTypePhone'.tr(),
|
||||||
|
style: contact.verifiedAt == null
|
||||||
|
? TextStyle(
|
||||||
|
decoration: TextDecoration.lineThrough,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor: contact.verifiedAt == null
|
||||||
|
? Theme.of(context).colorScheme.secondaryContainer
|
||||||
|
: Theme.of(context).colorScheme.primaryContainer,
|
||||||
|
child: Icon(
|
||||||
|
contact.type == 0 ? Symbols.mail : Symbols.phone,
|
||||||
|
),
|
||||||
|
).padding(top: 4),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
isThreeLine: false,
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) =>
|
||||||
|
ContactMethodSheet(contact: contact),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(contactMethodsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (contacts.isNotEmpty) const Divider(height: 1),
|
||||||
|
ListTile(
|
||||||
|
minLeadingWidth: 48,
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
left: 24,
|
||||||
|
right: 17,
|
||||||
|
),
|
||||||
|
title: Text('contactMethodNew').tr(),
|
||||||
|
leading: const Icon(Symbols.add),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => const ContactMethodNewSheet(),
|
||||||
|
).then((value) {
|
||||||
|
if (value == true) {
|
||||||
|
ref.invalidate(contactMethodsProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (err, _) => ResponseErrorWidget(
|
||||||
|
error: err,
|
||||||
|
onRetry: () => ref.invalidate(contactMethodsProvider),
|
||||||
|
),
|
||||||
loading: () => const ResponseLoadingWidget(),
|
loading: () => const ResponseLoadingWidget(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -439,6 +399,7 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
// Create a responsive layout based on screen width
|
// Create a responsive layout based on screen width
|
||||||
Widget buildSettingsList() {
|
Widget buildSettingsList() {
|
||||||
return Column(
|
return Column(
|
||||||
|
spacing: 16,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_SettingsSection(
|
_SettingsSection(
|
||||||
@@ -450,38 +411,36 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
children: dangerZoneSettings,
|
children: dangerZoneSettings,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
).padding(horizontal: 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('accountSettings').tr(),
|
title: Text('accountSettings').tr(),
|
||||||
actions:
|
actions: isDesktop
|
||||||
isDesktop
|
? [
|
||||||
? [
|
IconButton(
|
||||||
IconButton(
|
icon: const Icon(Symbols.help_outline),
|
||||||
icon: const Icon(Symbols.help_outline),
|
onPressed: () {
|
||||||
onPressed: () {
|
// Show help dialog
|
||||||
// Show help dialog
|
showDialog(
|
||||||
showDialog(
|
context: context,
|
||||||
context: context,
|
builder: (context) => AlertDialog(
|
||||||
builder:
|
title: Text('accountSettingsHelp').tr(),
|
||||||
(context) => AlertDialog(
|
content: Text('accountSettingsHelpContent').tr(),
|
||||||
title: Text('accountSettingsHelp').tr(),
|
actions: [
|
||||||
content: Text('accountSettingsHelpContent').tr(),
|
TextButton(
|
||||||
actions: [
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
TextButton(
|
child: Text('Close').tr(),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
),
|
||||||
child: Text('Close').tr(),
|
],
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
),
|
||||||
},
|
const Gap(8),
|
||||||
),
|
]
|
||||||
const Gap(8),
|
: null,
|
||||||
]
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
body: Focus(
|
body: Focus(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
@@ -513,22 +472,25 @@ class _SettingsSection extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Card(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
margin: EdgeInsets.zero,
|
||||||
children: [
|
child: Column(
|
||||||
Padding(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
padding: const EdgeInsets.fromLTRB(24, 16, 24, 8),
|
children: [
|
||||||
child: Text(
|
Padding(
|
||||||
title.tr(),
|
padding: const EdgeInsets.fromLTRB(24, 16, 24, 8),
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
child: Text(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
title.tr(),
|
||||||
fontWeight: FontWeight.bold,
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
...children,
|
||||||
...children,
|
const SizedBox(height: 16),
|
||||||
const SizedBox(height: 16),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user