chore: Design follow up

This commit is contained in:
krille-chan 2023-12-26 18:19:33 +01:00
parent dd7330ecd3
commit 038cd9cb73
No known key found for this signature in database
6 changed files with 172 additions and 139 deletions

View file

@ -2383,5 +2383,6 @@
"publicSpaces": "Public spaces", "publicSpaces": "Public spaces",
"addChatOrSubSpace": "Add chat or sub space", "addChatOrSubSpace": "Add chat or sub space",
"subspace": "Subspace", "subspace": "Subspace",
"decline": "Decline" "decline": "Decline",
"thisDevice": "This device:"
} }

View file

@ -216,7 +216,7 @@ class ChatController extends State<ChatPageWithRoom> {
EmojiPickerType emojiPickerType = EmojiPickerType.keyboard; EmojiPickerType emojiPickerType = EmojiPickerType.keyboard;
void requestHistory() async { void requestHistory([_]) async {
if (!timeline!.canRequestHistory) return; if (!timeline!.canRequestHistory) return;
Logs().v('Requesting history...'); Logs().v('Requesting history...');
try { try {
@ -269,11 +269,6 @@ class ChatController extends State<ChatPageWithRoom> {
if (scrollController.position.pixels == 0 || if (scrollController.position.pixels == 0 ||
scrollController.position.pixels == 64) { scrollController.position.pixels == 64) {
requestFuture(); requestFuture();
} else if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent ||
scrollController.position.pixels + 64 ==
scrollController.position.maxScrollExtent) {
requestHistory();
} }
} }

View file

@ -82,11 +82,17 @@ class ChatEventList extends StatelessWidget {
); );
} }
if (controller.timeline!.canRequestHistory) { if (controller.timeline!.canRequestHistory) {
return Center( return Builder(
child: IconButton( builder: (context) {
onPressed: controller.requestHistory, WidgetsBinding.instance
icon: const Icon(Icons.refresh_outlined), .addPostFrameCallback(controller.requestHistory);
), return Center(
child: IconButton(
onPressed: controller.requestHistory,
icon: const Icon(Icons.refresh_outlined),
),
);
},
); );
} }
return const SizedBox.shrink(); return const SizedBox.shrink();

View file

@ -47,7 +47,22 @@ class DevicesSettingsView extends StatelessWidget {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (controller.thisDevice != null) if (controller.thisDevice != null) ...[
Container(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
alignment: Alignment.centerLeft,
child: Text(
L10n.of(context)!.thisDevice,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
textAlign: TextAlign.left,
),
),
UserDeviceListItem( UserDeviceListItem(
controller.thisDevice!, controller.thisDevice!,
rename: controller.renameDeviceAction, rename: controller.renameDeviceAction,
@ -56,24 +71,44 @@ class DevicesSettingsView extends StatelessWidget {
block: controller.blockDeviceAction, block: controller.blockDeviceAction,
unblock: controller.unblockDeviceAction, unblock: controller.unblockDeviceAction,
), ),
const Divider(height: 1), const Divider(
height: 16.0,
indent: 16,
endIndent: 16,
),
],
if (controller.notThisDevice.isNotEmpty) if (controller.notThisDevice.isNotEmpty)
ListTile( Padding(
title: Text( padding: const EdgeInsets.symmetric(
controller.errorDeletingDevices ?? horizontal: 16.0,
L10n.of(context)!.removeAllOtherDevices, vertical: 8.0,
style: const TextStyle(color: Colors.red), ),
child: SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
label: Text(
controller.errorDeletingDevices ??
L10n.of(context)!.removeAllOtherDevices,
),
style: OutlinedButton.styleFrom(
foregroundColor:
Theme.of(context).colorScheme.error,
side: BorderSide(
color: Theme.of(context).colorScheme.error,
),
),
icon: controller.loadingDeletingDevices
? const CircularProgressIndicator.adaptive(
strokeWidth: 2,
)
: const Icon(Icons.delete_outline),
onPressed: controller.loadingDeletingDevices
? null
: () => controller.removeDevicesAction(
controller.notThisDevice,
),
),
), ),
trailing: controller.loadingDeletingDevices
? const CircularProgressIndicator.adaptive(
strokeWidth: 2,
)
: const Icon(Icons.delete_outline),
onTap: controller.loadingDeletingDevices
? null
: () => controller.removeDevicesAction(
controller.notThisDevice,
),
) )
else else
Center( Center(
@ -82,7 +117,6 @@ class DevicesSettingsView extends StatelessWidget {
child: Text(L10n.of(context)!.noOtherDevicesFound), child: Text(L10n.of(context)!.noOtherDevicesFound),
), ),
), ),
const Divider(height: 1),
], ],
); );
} }

View file

@ -4,6 +4,7 @@ import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/config/app_config.dart';
import '../../utils/date_time_extension.dart'; import '../../utils/date_time_extension.dart';
import '../../utils/matrix_sdk_extensions/device_extension.dart'; import '../../utils/matrix_sdk_extensions/device_extension.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
@ -41,104 +42,106 @@ class UserDeviceListItem extends StatelessWidget {
?.deviceKeys[userDevice.deviceId]; ?.deviceKeys[userDevice.deviceId];
final isOwnDevice = userDevice.deviceId == client.deviceID; final isOwnDevice = userDevice.deviceId == client.deviceID;
return ListTile( return Padding(
onTap: () async { padding: const EdgeInsets.symmetric(horizontal: 8.0),
final action = await showModalActionSheet<UserDeviceListItemAction>( child: Material(
context: context, borderRadius: BorderRadius.circular(AppConfig.borderRadius),
title: '${userDevice.displayName} (${userDevice.deviceId})', clipBehavior: Clip.hardEdge,
actions: [ child: ListTile(
SheetAction( onTap: () async {
key: UserDeviceListItemAction.rename, final action = await showModalActionSheet<UserDeviceListItemAction>(
label: L10n.of(context)!.changeDeviceName, context: context,
), title: '${userDevice.displayName} (${userDevice.deviceId})',
if (!isOwnDevice && keys != null) ...{ actions: [
SheetAction(
key: UserDeviceListItemAction.verify,
label: L10n.of(context)!.verifyStart,
),
if (!keys.blocked)
SheetAction( SheetAction(
key: UserDeviceListItemAction.block, key: UserDeviceListItemAction.rename,
label: L10n.of(context)!.blockDevice, label: L10n.of(context)!.changeDeviceName,
isDestructiveAction: true,
), ),
if (keys.blocked) if (!isOwnDevice && keys != null) ...{
SheetAction( SheetAction(
key: UserDeviceListItemAction.unblock, key: UserDeviceListItemAction.verify,
label: L10n.of(context)!.unblockDevice, label: L10n.of(context)!.verifyStart,
isDestructiveAction: true, ),
), if (!keys.blocked)
}, SheetAction(
if (!isOwnDevice) key: UserDeviceListItemAction.block,
SheetAction( label: L10n.of(context)!.blockDevice,
key: UserDeviceListItemAction.remove, isDestructiveAction: true,
label: L10n.of(context)!.delete, ),
isDestructiveAction: true, if (keys.blocked)
), SheetAction(
], key: UserDeviceListItemAction.unblock,
); label: L10n.of(context)!.unblockDevice,
if (action == null) return; isDestructiveAction: true,
switch (action) { ),
case UserDeviceListItemAction.rename: },
rename(userDevice); if (!isOwnDevice)
break; SheetAction(
case UserDeviceListItemAction.remove: key: UserDeviceListItemAction.remove,
remove(userDevice); label: L10n.of(context)!.delete,
break; isDestructiveAction: true,
case UserDeviceListItemAction.verify: ),
verify(userDevice); ],
break; );
case UserDeviceListItemAction.block: if (action == null) return;
block(userDevice); switch (action) {
break; case UserDeviceListItemAction.rename:
case UserDeviceListItemAction.unblock: rename(userDevice);
unblock(userDevice); break;
break; case UserDeviceListItemAction.remove:
} remove(userDevice);
}, break;
leading: CircleAvatar( case UserDeviceListItemAction.verify:
foregroundColor: Colors.white, verify(userDevice);
backgroundColor: keys == null break;
? Colors.grey[700] case UserDeviceListItemAction.block:
: keys.blocked block(userDevice);
? Colors.red break;
: keys.verified case UserDeviceListItemAction.unblock:
? Colors.green unblock(userDevice);
: Colors.orange, break;
child: Icon(userDevice.icon), }
), },
title: Row( leading: CircleAvatar(
children: <Widget>[ foregroundColor: Colors.white,
Expanded( backgroundColor: keys == null
child: Text( ? Colors.grey[700]
userDevice.displayname, : keys.blocked
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
if (keys != null)
Text(
keys.blocked
? L10n.of(context)!.blocked
: keys.verified
? L10n.of(context)!.verified
: L10n.of(context)!.unverified,
style: TextStyle(
color: keys.blocked
? Colors.red ? Colors.red
: keys.verified : keys.verified
? Colors.green ? Colors.green
: Colors.orange, : Colors.orange,
), child: Icon(userDevice.icon),
),
title: Text(
userDevice.displayname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(
L10n.of(context)!.lastActiveAgo(
DateTime.fromMillisecondsSinceEpoch(userDevice.lastSeenTs ?? 0)
.localizedTimeShort(context),
), ),
], style: const TextStyle(fontWeight: FontWeight.w300),
), ),
subtitle: Text( trailing: keys == null
L10n.of(context)!.lastActiveAgo( ? null
DateTime.fromMillisecondsSinceEpoch(userDevice.lastSeenTs ?? 0) : Text(
.localizedTimeShort(context), keys.blocked
? L10n.of(context)!.blocked
: keys.verified
? L10n.of(context)!.verified
: L10n.of(context)!.unverified,
style: TextStyle(
color: keys.blocked
? Colors.red
: keys.verified
? Colors.green
: Colors.orange,
),
),
), ),
style: const TextStyle(fontWeight: FontWeight.w300),
), ),
); );
} }

View file

@ -45,26 +45,20 @@ class SettingsNotificationsView extends StatelessWidget {
), ),
), ),
), ),
if (!Matrix.of(context).client.allPushNotificationsMuted) ...{ for (final item in NotificationSettingsItem.items)
const Divider(thickness: 1), SwitchListTile.adaptive(
ListTile( value: Matrix.of(context).client.allPushNotificationsMuted
title: Text( ? false
L10n.of(context)!.pushRules, : controller.getNotificationSetting(item) ?? true,
style: TextStyle( title: Text(item.title(context)),
color: Theme.of(context).colorScheme.secondary, onChanged: Matrix.of(context)
fontWeight: FontWeight.bold, .client
), .allPushNotificationsMuted
), ? null
: (bool enabled) =>
controller.setNotificationSetting(item, enabled),
), ),
for (final item in NotificationSettingsItem.items) const Divider(),
SwitchListTile.adaptive(
value: controller.getNotificationSetting(item) ?? true,
title: Text(item.title(context)),
onChanged: (bool enabled) =>
controller.setNotificationSetting(item, enabled),
),
},
const Divider(thickness: 1),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.devices, L10n.of(context)!.devices,