design: Adjust settings design

pull/1022/head
krille-chan 1 year ago
parent 23f4c64e50
commit e11195f4fc
No known key found for this signature in database

@ -1384,6 +1384,9 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"overview": "Overview",
"notifyMeFor": "Notify me for",
"passwordRecoverySettings": "Password recovery settings",
"passwordRecovery": "Password recovery", "passwordRecovery": "Password recovery",
"@passwordRecovery": { "@passwordRecovery": {
"type": "text", "type": "text",
@ -2602,5 +2605,10 @@
"unread": {} "unread": {}
} }
}, },
"noDatabaseEncryption": "Database encryption is not supported on this platform" "noDatabaseEncryption": "Database encryption is not supported on this platform",
"thereAreCountUsersBlocked": "Right now there are {count} users blocked.",
"@thereAreCountUsersBlocked": {
"type": "text",
"count": {}
}
} }

@ -140,6 +140,9 @@ abstract class FluffyThemes {
), ),
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: colorScheme.secondaryContainer,
foregroundColor: colorScheme.onSecondaryContainer,
elevation: 0,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
textStyle: const TextStyle(fontSize: 16), textStyle: const TextStyle(fontSize: 16),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(

@ -386,7 +386,10 @@ class BootstrapDialogState extends State<BootstrapDialog> {
const SizedBox(height: 16), const SizedBox(height: 16),
ElevatedButton.icon( ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.red, backgroundColor:
Theme.of(context).colorScheme.errorContainer,
foregroundColor:
Theme.of(context).colorScheme.onErrorContainer,
), ),
icon: const Icon(Icons.delete_outlined), icon: const Icon(Icons.delete_outlined),
label: Text(L10n.of(context)!.recoveryKeyLost), label: Text(L10n.of(context)!.recoveryKeyLost),

@ -221,10 +221,18 @@ class ChatDetailsView extends StatelessWidget {
else else
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: OutlinedButton.icon( child: TextButton.icon(
onPressed: controller.setTopicAction, onPressed: controller.setTopicAction,
label: Text(L10n.of(context)!.setChatDescription), label: Text(L10n.of(context)!.setChatDescription),
icon: const Icon(Icons.edit_outlined), icon: const Icon(Icons.edit_outlined),
style: TextButton.styleFrom(
backgroundColor: Theme.of(context)
.colorScheme
.secondaryContainer,
foregroundColor: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
), ),
), ),
Padding( Padding(

@ -71,11 +71,6 @@ class DevicesSettingsView extends StatelessWidget {
block: controller.blockDeviceAction, block: controller.blockDeviceAction,
unblock: controller.unblockDeviceAction, unblock: controller.unblockDeviceAction,
), ),
const Divider(
height: 16.0,
indent: 16,
endIndent: 16,
),
], ],
if (controller.notThisDevice.isNotEmpty) if (controller.notThisDevice.isNotEmpty)
Padding( Padding(
@ -85,17 +80,18 @@ class DevicesSettingsView extends StatelessWidget {
), ),
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
child: OutlinedButton.icon( child: TextButton.icon(
label: Text( label: Text(
controller.errorDeletingDevices ?? controller.errorDeletingDevices ??
L10n.of(context)!.removeAllOtherDevices, L10n.of(context)!.removeAllOtherDevices,
), ),
style: OutlinedButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: foregroundColor: Theme.of(context)
Theme.of(context).colorScheme.error, .colorScheme
side: BorderSide( .onErrorContainer,
color: Theme.of(context).colorScheme.error, backgroundColor: Theme.of(context)
), .colorScheme
.errorContainer,
), ),
icon: controller.loadingDeletingDevices icon: controller.loadingDeletingDevices
? const CircularProgressIndicator.adaptive( ? const CircularProgressIndicator.adaptive(

@ -198,12 +198,7 @@ class _LoginButton extends StatelessWidget {
width: double.infinity, width: double.infinity,
child: OutlinedButton.icon( child: OutlinedButton.icon(
style: OutlinedButton.styleFrom( style: OutlinedButton.styleFrom(
side: BorderSide( side: BorderSide.none,
width: withBorder ? 1 : 0,
color: withBorder
? Theme.of(context).colorScheme.onBackground
: Colors.transparent,
),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(99), borderRadius: BorderRadius.circular(99),
), ),

@ -136,7 +136,10 @@ class SettingsView extends StatelessWidget {
); );
}, },
), ),
const Divider(thickness: 1), Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
if (showChatBackupBanner == null) if (showChatBackupBanner == null)
ListTile( ListTile(
leading: const Icon(Icons.backup_outlined), leading: const Icon(Icons.backup_outlined),
@ -151,7 +154,10 @@ class SettingsView extends StatelessWidget {
title: Text(L10n.of(context)!.chatBackup), title: Text(L10n.of(context)!.chatBackup),
onChanged: controller.firstRunBootstrapAction, onChanged: controller.firstRunBootstrapAction,
), ),
const Divider(thickness: 1), Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile( ListTile(
leading: const Icon(Icons.format_paint_outlined), leading: const Icon(Icons.format_paint_outlined),
title: Text(L10n.of(context)!.changeTheme), title: Text(L10n.of(context)!.changeTheme),
@ -182,7 +188,10 @@ class SettingsView extends StatelessWidget {
onTap: () => context.go('/rooms/settings/security'), onTap: () => context.go('/rooms/settings/security'),
trailing: const Icon(Icons.chevron_right_outlined), trailing: const Icon(Icons.chevron_right_outlined),
), ),
const Divider(thickness: 1), Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile( ListTile(
leading: const Icon(Icons.help_outline_outlined), leading: const Icon(Icons.help_outline_outlined),
title: Text(L10n.of(context)!.help), title: Text(L10n.of(context)!.help),

@ -91,12 +91,6 @@ class SettingsChatView extends StatelessWidget {
child: Icon(Icons.call), child: Icon(Icons.call),
), ),
), ),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.separateChatTypes,
onChanged: (b) => AppConfig.separateChatTypes = b,
storeKey: SettingKeys.separateChatTypes,
defaultValue: AppConfig.separateChatTypes,
),
], ],
), ),
), ),

@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
import 'settings_notifications_view.dart'; import 'settings_notifications_view.dart';
@ -89,16 +90,52 @@ class SettingsNotificationsController extends State<SettingsNotifications> {
} }
} }
void setNotificationSetting(NotificationSettingsItem item, bool enabled) { bool isLoading = false;
showFutureLoadingDialog(
context: context, void setNotificationSetting(
future: () => Matrix.of(context).client.setPushRuleEnabled( NotificationSettingsItem item,
bool enabled,
) async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
setState(() {
isLoading = true;
});
try {
await Matrix.of(context).client.setPushRuleEnabled(
'global', 'global',
item.type, item.type,
item.key, item.key,
enabled, enabled,
),
); );
} catch (e, s) {
Logs().w('Unable to change notification settings', e, s);
scaffoldMessenger
.showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
} finally {
setState(() {
isLoading = false;
});
}
}
void onToggleMuteAllNotifications() async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
setState(() {
isLoading = true;
});
try {
await Matrix.of(context).client.setMuteAllPushNotifications(
!Matrix.of(context).client.allPushNotificationsMuted,
);
} catch (e, s) {
Logs().w('Unable to change notification settings', e, s);
scaffoldMessenger
.showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
} finally {
setState(() {
isLoading = false;
});
}
} }
void onPusherTap(Pusher pusher) async { void onPusherTap(Pusher pusher) async {

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart';
@ -36,12 +35,17 @@ class SettingsNotificationsView extends StatelessWidget {
title: Text( title: Text(
L10n.of(context)!.notificationsEnabledForThisAccount, L10n.of(context)!.notificationsEnabledForThisAccount,
), ),
onChanged: (_) => showFutureLoadingDialog( onChanged: controller.isLoading
context: context, ? null
future: () => Matrix.of(context) : (_) => controller.onToggleMuteAllNotifications(),
.client ),
.setMuteAllPushNotifications( Divider(color: Theme.of(context).dividerColor),
!Matrix.of(context).client.allPushNotificationsMuted, ListTile(
title: Text(
L10n.of(context)!.notifyMeFor,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
), ),
), ),
), ),
@ -51,14 +55,14 @@ class SettingsNotificationsView extends StatelessWidget {
? false ? false
: controller.getNotificationSetting(item) ?? true, : controller.getNotificationSetting(item) ?? true,
title: Text(item.title(context)), title: Text(item.title(context)),
onChanged: Matrix.of(context) onChanged: controller.isLoading
.client ? null
.allPushNotificationsMuted : Matrix.of(context).client.allPushNotificationsMuted
? null ? null
: (bool enabled) => : (bool enabled) => controller
controller.setNotificationSetting(item, enabled), .setNotificationSetting(item, enabled),
), ),
const Divider(), Divider(color: Theme.of(context).dividerColor),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.devices, L10n.of(context)!.devices,
@ -87,6 +91,14 @@ class SettingsNotificationsView extends StatelessWidget {
); );
} }
final pushers = snapshot.data ?? []; final pushers = snapshot.data ?? [];
if (pushers.isEmpty) {
return Center(
child: Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: Text(L10n.of(context)!.noOtherDevicesFound),
),
);
}
return ListView.builder( return ListView.builder(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:go_router/go_router.dart';
import 'package:fluffychat/pages/settings_password/settings_password.dart'; import 'package:fluffychat/pages/settings_password/settings_password.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart';
@ -12,7 +13,15 @@ class SettingsPasswordView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(L10n.of(context)!.changePassword)), appBar: AppBar(
title: Text(L10n.of(context)!.changePassword),
actions: [
TextButton(
child: Text(L10n.of(context)!.passwordRecoverySettings),
onPressed: () => context.go('/rooms/settings/security/3pid'),
),
],
),
body: ListTileTheme( body: ListTileTheme(
iconColor: Theme.of(context).colorScheme.onBackground, iconColor: Theme.of(context).colorScheme.onBackground,
child: MaxWidthBody( child: MaxWidthBody(

@ -58,6 +58,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
message: L10n.of(context)!.deactivateAccountWarning, message: L10n.of(context)!.deactivateAccountWarning,
okLabel: L10n.of(context)!.ok, okLabel: L10n.of(context)!.ok,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
isDestructiveAction: true,
) == ) ==
OkCancelResult.cancel) { OkCancelResult.cancel) {
return; return;
@ -74,6 +75,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
: L10n.of(context)!.supposedMxid(supposedMxid), : L10n.of(context)!.supposedMxid(supposedMxid),
), ),
], ],
isDestructiveAction: true,
okLabel: L10n.of(context)!.delete, okLabel: L10n.of(context)!.delete,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
); );
@ -86,6 +88,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
title: L10n.of(context)!.pleaseEnterYourPassword, title: L10n.of(context)!.pleaseEnterYourPassword,
okLabel: L10n.of(context)!.ok, okLabel: L10n.of(context)!.ok,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
isDestructiveAction: true,
textFields: [ textFields: [
const DialogTextField( const DialogTextField(
obscureText: true, obscureText: true,

@ -42,6 +42,71 @@ class SettingsSecurityView extends StatelessWidget {
} }
return Column( return Column(
children: [ children: [
ListTile(
title: Text(
L10n.of(context)!.privacy,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.sendTypingNotifications,
subtitle:
L10n.of(context)!.sendTypingNotificationsDescription,
onChanged: (b) => AppConfig.sendTypingNotifications = b,
storeKey: SettingKeys.sendTypingNotifications,
defaultValue: AppConfig.sendTypingNotifications,
),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.sendReadReceipts,
subtitle: L10n.of(context)!.sendReadReceiptsDescription,
onChanged: (b) => AppConfig.sendPublicReadReceipts = b,
storeKey: SettingKeys.sendPublicReadReceipts,
defaultValue: AppConfig.sendPublicReadReceipts,
),
ListTile(
trailing: const Icon(Icons.chevron_right_outlined),
title: Text(L10n.of(context)!.blockedUsers),
subtitle: Text(
L10n.of(context)!.thereAreCountUsersBlocked(
Matrix.of(context).client.ignoredUsers.length,
),
),
onTap: () =>
context.go('/rooms/settings/security/ignorelist'),
),
if (Matrix.of(context).client.encryption != null) ...{
if (PlatformInfos.isMobile)
ListTile(
leading: const Icon(Icons.lock_outlined),
trailing: const Icon(Icons.chevron_right_outlined),
title: Text(L10n.of(context)!.appLock),
onTap: controller.setAppLockAction,
),
},
Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile(
title: Text(
L10n.of(context)!.account,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
ListTile(
title: Text(L10n.of(context)!.yourPublicKey),
leading: const Icon(Icons.vpn_key_outlined),
subtitle: SelectableText(
Matrix.of(context).client.fingerprintKey.beautified,
style: const TextStyle(fontFamily: 'monospace'),
),
),
if (error != null) if (error != null)
ListTile( ListTile(
leading: const Icon( leading: const Icon(
@ -54,9 +119,9 @@ class SettingsSecurityView extends StatelessWidget {
), ),
), ),
if (capabilities?.mChangePassword?.enabled != false || if (capabilities?.mChangePassword?.enabled != false ||
error != null) ...[ error != null)
ListTile( ListTile(
leading: const Icon(Icons.key_outlined), leading: const Icon(Icons.password_outlined),
trailing: error != null trailing: error != null
? null ? null
: const Icon(Icons.chevron_right_outlined), : const Icon(Icons.chevron_right_outlined),
@ -73,48 +138,16 @@ class SettingsSecurityView extends StatelessWidget {
context.go('/rooms/settings/security/password'), context.go('/rooms/settings/security/password'),
), ),
ListTile( ListTile(
leading: const Icon(Icons.mail_outlined), iconColor: Colors.orange,
trailing: error != null
? null
: const Icon(Icons.chevron_right_outlined),
title: Text(
L10n.of(context)!.passwordRecovery,
style: TextStyle(
decoration:
error == null ? null : TextDecoration.lineThrough,
),
),
onTap: error != null
? null
: () => context.go('/rooms/settings/security/3pid'),
),
],
ListTile(
leading: const Icon(Icons.block_outlined),
trailing: const Icon(Icons.chevron_right_outlined),
title: Text(L10n.of(context)!.blockedUsers),
onTap: () =>
context.go('/rooms/settings/security/ignorelist'),
),
if (Matrix.of(context).client.encryption != null) ...{
if (PlatformInfos.isMobile)
ListTile(
leading: const Icon(Icons.lock_outlined),
trailing: const Icon(Icons.chevron_right_outlined),
title: Text(L10n.of(context)!.appLock),
onTap: controller.setAppLockAction,
),
},
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.tap_and_play), leading: const Icon(Icons.tap_and_play),
title: Text( title: Text(
L10n.of(context)!.dehydrate, L10n.of(context)!.dehydrate,
style: const TextStyle(color: Colors.red), style: const TextStyle(color: Colors.orange),
), ),
onTap: controller.dehydrateAction, onTap: controller.dehydrateAction,
), ),
ListTile( ListTile(
iconColor: Colors.red,
leading: const Icon(Icons.delete_outlined), leading: const Icon(Icons.delete_outlined),
title: Text( title: Text(
L10n.of(context)!.deleteAccount, L10n.of(context)!.deleteAccount,
@ -122,30 +155,6 @@ class SettingsSecurityView extends StatelessWidget {
), ),
onTap: controller.deleteAccountAction, onTap: controller.deleteAccountAction,
), ),
ListTile(
title: Text(L10n.of(context)!.yourPublicKey),
subtitle: SelectableText(
Matrix.of(context).client.fingerprintKey.beautified,
style: const TextStyle(fontFamily: 'monospace'),
),
leading: const Icon(Icons.vpn_key_outlined),
),
const Divider(height: 1),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.sendTypingNotifications,
subtitle:
L10n.of(context)!.sendTypingNotificationsDescription,
onChanged: (b) => AppConfig.sendTypingNotifications = b,
storeKey: SettingKeys.sendTypingNotifications,
defaultValue: AppConfig.sendTypingNotifications,
),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.sendReadReceipts,
subtitle: L10n.of(context)!.sendReadReceiptsDescription,
onChanged: (b) => AppConfig.sendPublicReadReceipts = b,
storeKey: SettingKeys.sendPublicReadReceipts,
defaultValue: AppConfig.sendPublicReadReceipts,
),
], ],
); );
}, },

@ -135,7 +135,10 @@ class SettingsStyleView extends StatelessWidget {
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
const Divider(height: 1), Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.setTheme, L10n.of(context)!.setTheme,
@ -163,10 +166,13 @@ class SettingsStyleView extends StatelessWidget {
title: Text(L10n.of(context)!.darkTheme), title: Text(L10n.of(context)!.darkTheme),
onChanged: controller.switchTheme, onChanged: controller.switchTheme,
), ),
const Divider(height: 1), Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.presenceStyle, L10n.of(context)!.overview,
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.secondary, color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -179,7 +185,16 @@ class SettingsStyleView extends StatelessWidget {
storeKey: SettingKeys.showPresences, storeKey: SettingKeys.showPresences,
defaultValue: AppConfig.showPresences, defaultValue: AppConfig.showPresences,
), ),
const Divider(height: 1), SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.separateChatTypes,
onChanged: (b) => AppConfig.separateChatTypes = b,
storeKey: SettingKeys.separateChatTypes,
defaultValue: AppConfig.separateChatTypes,
),
Divider(
height: 1,
color: Theme.of(context).dividerColor,
),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.messagesStyle, L10n.of(context)!.messagesStyle,

Loading…
Cancel
Save