♻️ Refactor channel list
💄 Stop previewing encrypted message raw message
This commit is contained in:
parent
cdaa8cfe58
commit
ce6e9c185a
@ -761,5 +761,7 @@
|
|||||||
"enrollNewKeyPairDescription": "Generate a new key pair.",
|
"enrollNewKeyPairDescription": "Generate a new key pair.",
|
||||||
"keyPairHasPrivateKey": "With private key",
|
"keyPairHasPrivateKey": "With private key",
|
||||||
"decrypting": "Decrypting……",
|
"decrypting": "Decrypting……",
|
||||||
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online"
|
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
|
||||||
|
"messageUnablePreview": "Unable preview",
|
||||||
|
"messageUnablePreviewEncrypted": "Unable preview encrypted message"
|
||||||
}
|
}
|
||||||
|
@ -759,5 +759,7 @@
|
|||||||
"enrollNewKeyPairDescription": "生成一对新密钥对。",
|
"enrollNewKeyPairDescription": "生成一对新密钥对。",
|
||||||
"keyPairHasPrivateKey": "有私钥",
|
"keyPairHasPrivateKey": "有私钥",
|
||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线"
|
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
|
||||||
|
"messageUnablePreview": "无法预览消息",
|
||||||
|
"messageUnablePreviewEncrypted": "无法预览加密消息"
|
||||||
}
|
}
|
||||||
|
@ -759,5 +759,7 @@
|
|||||||
"enrollNewKeyPairDescription": "生成一對新密鑰對。",
|
"enrollNewKeyPairDescription": "生成一對新密鑰對。",
|
||||||
"keyPairHasPrivateKey": "有私鑰",
|
"keyPairHasPrivateKey": "有私鑰",
|
||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線"
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
|
"messageUnablePreview": "無法預覽消息",
|
||||||
|
"messageUnablePreviewEncrypted": "無法預覽加密消息"
|
||||||
}
|
}
|
||||||
|
@ -759,5 +759,7 @@
|
|||||||
"enrollNewKeyPairDescription": "生成一對新密鑰對。",
|
"enrollNewKeyPairDescription": "生成一對新密鑰對。",
|
||||||
"keyPairHasPrivateKey": "有私鑰",
|
"keyPairHasPrivateKey": "有私鑰",
|
||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線"
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
|
"messageUnablePreview": "無法預覽消息",
|
||||||
|
"messageUnablePreviewEncrypted": "無法預覽加密消息"
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,6 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final ud = context.read<UserDirectoryProvider>();
|
|
||||||
final ua = context.read<UserProvider>();
|
final ua = context.read<UserProvider>();
|
||||||
|
|
||||||
if (!ua.isAuthorized) {
|
if (!ua.isAuthorized) {
|
||||||
@ -266,144 +265,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
final channel = _channels![idx];
|
final channel = _channels![idx];
|
||||||
final lastMessage = _lastMessages?[channel.id];
|
final lastMessage = _lastMessages?[channel.id];
|
||||||
|
|
||||||
if (channel.type == 1) {
|
return _ChatChannelEntry(
|
||||||
final otherMember =
|
channel: channel,
|
||||||
channel.members?.cast<SnChannelMember?>().firstWhere(
|
lastMessage: lastMessage,
|
||||||
(ele) => ele?.accountId != ua.user?.id,
|
unreadCount: _unreadCounts?[channel.id],
|
||||||
orElse: () => null,
|
|
||||||
);
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(ud
|
|
||||||
.getAccountFromCache(
|
|
||||||
otherMember?.accountId)
|
|
||||||
?.nick ??
|
|
||||||
channel.name),
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
if (_unreadCounts?[channel.id] != null &&
|
|
||||||
_unreadCounts![channel.id]! > 0)
|
|
||||||
Badge(
|
|
||||||
label: Text('${_unreadCounts![channel.id]}'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
subtitle: lastMessage != null
|
|
||||||
? Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
lastMessage.body['text'] ??
|
|
||||||
'Unable preview',
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
Text(
|
|
||||||
DateFormat(
|
|
||||||
lastMessage.createdAt.toLocal().day ==
|
|
||||||
DateTime.now().day
|
|
||||||
? 'HH:mm'
|
|
||||||
: lastMessage.createdAt
|
|
||||||
.toLocal()
|
|
||||||
.year ==
|
|
||||||
DateTime.now().year
|
|
||||||
? 'MM/dd'
|
|
||||||
: 'yy/MM/dd',
|
|
||||||
).format(lastMessage.createdAt.toLocal()),
|
|
||||||
style: GoogleFonts.robotoMono(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
channel.description,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
leading: AccountImage(
|
|
||||||
content: ud
|
|
||||||
.getAccountFromCache(otherMember?.accountId)
|
|
||||||
?.avatar,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
_onTapChannel(channel);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text(channel.name)),
|
|
||||||
const Gap(8),
|
|
||||||
if (_unreadCounts?[channel.id] != null &&
|
|
||||||
_unreadCounts![channel.id]! > 0)
|
|
||||||
Badge(
|
|
||||||
label: Text('${_unreadCounts![channel.id]}'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
subtitle: lastMessage != null
|
|
||||||
? Row(
|
|
||||||
children: [
|
|
||||||
Badge(
|
|
||||||
label: Text(ud
|
|
||||||
.getAccountFromCache(
|
|
||||||
lastMessage.sender.accountId)
|
|
||||||
?.nick ??
|
|
||||||
'unknown'.tr()),
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).colorScheme.primary,
|
|
||||||
textColor:
|
|
||||||
Theme.of(context).colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
const Gap(6),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
lastMessage.body['text'] ??
|
|
||||||
'Unable preview',
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
Text(
|
|
||||||
DateFormat(
|
|
||||||
lastMessage.createdAt.toLocal().day ==
|
|
||||||
DateTime.now().day
|
|
||||||
? 'HH:mm'
|
|
||||||
: lastMessage.createdAt
|
|
||||||
.toLocal()
|
|
||||||
.year ==
|
|
||||||
DateTime.now().year
|
|
||||||
? 'MM/dd'
|
|
||||||
: 'yy/MM/dd',
|
|
||||||
).format(lastMessage.createdAt.toLocal()),
|
|
||||||
style: GoogleFonts.robotoMono(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
channel.description,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
leading: AccountImage(
|
|
||||||
content: channel.realm?.avatar,
|
|
||||||
fallbackWidget: const Icon(Symbols.chat, size: 20),
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (doExpand) {
|
if (doExpand) {
|
||||||
_unreadCounts?[channel.id] = 0;
|
_unreadCounts?[channel.id] = 0;
|
||||||
@ -445,3 +310,101 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
return chatList;
|
return chatList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ChatChannelEntry extends StatelessWidget {
|
||||||
|
final SnChannel channel;
|
||||||
|
final int? unreadCount;
|
||||||
|
final SnChatMessage? lastMessage;
|
||||||
|
final Function? onTap;
|
||||||
|
const _ChatChannelEntry({
|
||||||
|
required this.channel,
|
||||||
|
this.unreadCount,
|
||||||
|
this.lastMessage,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final ud = context.read<UserDirectoryProvider>();
|
||||||
|
final ua = context.read<UserProvider>();
|
||||||
|
|
||||||
|
final otherMember = channel.type == 1
|
||||||
|
? channel.members?.cast<SnChannelMember?>().firstWhere(
|
||||||
|
(ele) => ele?.accountId != ua.user?.id,
|
||||||
|
orElse: () => null,
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
final title = otherMember != null
|
||||||
|
? ud.getAccountFromCache(otherMember.accountId)?.nick ?? channel.name
|
||||||
|
: channel.name;
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Text(title)),
|
||||||
|
const Gap(8),
|
||||||
|
if (unreadCount != null && unreadCount! > 0)
|
||||||
|
Badge(
|
||||||
|
label: Text(unreadCount.toString()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: lastMessage != null
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Badge(
|
||||||
|
label: Text(ud
|
||||||
|
.getAccountFromCache(lastMessage!.sender.accountId)
|
||||||
|
?.nick ??
|
||||||
|
'unknown'.tr()),
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
const Gap(6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
lastMessage!.body['algorithm'] == 'plain'
|
||||||
|
? lastMessage!.body['text'] ??
|
||||||
|
'messageUnablePreview'.tr()
|
||||||
|
: 'messageUnablePreviewEncrypted'.tr(),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: lastMessage!.body['algorithm'] != 'plain' ||
|
||||||
|
lastMessage!.body['text'] == null
|
||||||
|
? TextStyle(fontStyle: FontStyle.italic)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
|
DateFormat(
|
||||||
|
lastMessage!.createdAt.toLocal().day == DateTime.now().day
|
||||||
|
? 'HH:mm'
|
||||||
|
: lastMessage!.createdAt.toLocal().year ==
|
||||||
|
DateTime.now().year
|
||||||
|
? 'MM/dd'
|
||||||
|
: 'yy/MM/dd',
|
||||||
|
).format(lastMessage!.createdAt.toLocal()),
|
||||||
|
style: GoogleFonts.robotoMono(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
channel.description,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
leading: AccountImage(
|
||||||
|
content: otherMember != null
|
||||||
|
? ud.getAccountFromCache(otherMember.accountId)?.avatar
|
||||||
|
: channel.realm?.avatar,
|
||||||
|
fallbackWidget: const Icon(Symbols.chat, size: 20),
|
||||||
|
),
|
||||||
|
onTap: () => onTap?.call(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user