chore: Design follow up
This commit is contained in:
parent
dd7330ecd3
commit
038cd9cb73
6 changed files with 172 additions and 139 deletions
|
|
@ -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:"
|
||||||
}
|
}
|
||||||
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue