refactor: Switch to Hive Collections DB

This commit is contained in:
Christian Pauly 2022-05-30 13:44:05 +02:00
commit c249ebb97c
29 changed files with 347 additions and 216 deletions

View file

@ -461,11 +461,11 @@ class ChatController extends State<Chat> {
if (selectedEvents.length == 1) {
return selectedEvents.first
.getDisplayEvent(timeline!)
.getLocalizedBody(MatrixLocals(L10n.of(context)!));
.calcLocalizedBodyFallback(MatrixLocals(L10n.of(context)!));
}
for (final event in selectedEvents) {
if (copyString.isNotEmpty) copyString += '\n\n';
copyString += event.getDisplayEvent(timeline!).getLocalizedBody(
copyString += event.getDisplayEvent(timeline!).calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true);
}
@ -773,7 +773,7 @@ class ChatController extends State<Chat> {
editEvent = selectedEvents.first;
inputText = sendController.text = editEvent!
.getDisplayEvent(timeline!)
.getLocalizedBody(MatrixLocals(L10n.of(context)!),
.calcLocalizedBodyFallback(MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false, hideReply: true);
selectedEvents.clear();
});

View file

@ -29,10 +29,11 @@ class ChatAppBarTitle extends StatelessWidget {
? () => showModalBottomSheet(
context: context,
builder: (c) => UserBottomSheet(
user: room.getUserByMXIDSync(directChatMatrixID),
user: room
.unsafeGetUserFromMemoryOrFallback(directChatMatrixID),
outerContext: context,
onMention: () => controller.sendController.text +=
'${room.getUserByMXIDSync(directChatMatrixID).mention} ',
'${room.unsafeGetUserFromMemoryOrFallback(directChatMatrixID).mention} ',
),
)
: () => VRouter.of(context).toSegments(['rooms', room.id, 'details']),

View file

@ -293,14 +293,14 @@ class _ChatAccountPicker extends StatelessWidget {
return Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder<Profile>(
future: controller.sendingClient!.ownProfile,
future: controller.sendingClient!.fetchOwnProfile(),
builder: (context, snapshot) => PopupMenuButton<String>(
onSelected: _popupMenuButtonSelected,
itemBuilder: (BuildContext context) => clients
.map((client) => PopupMenuItem<String>(
value: client!.userID,
child: FutureBuilder<Profile>(
future: client.ownProfile,
future: client.fetchOwnProfile(),
builder: (context, snapshot) => ListTile(
leading: Avatar(
mxContent: snapshot.data?.avatarUrl,

View file

@ -350,12 +350,12 @@ class ChatView extends StatelessWidget {
builder: (c) =>
UserBottomSheet(
user: event
.sender,
.senderFromMemoryOrFallback,
outerContext:
context,
onMention: () => controller
.sendController
.text += '${event.sender.mention} ',
.text += '${event.senderFromMemoryOrFallback.mention} ',
),
),
unfold: controller

View file

@ -48,12 +48,12 @@ class EventInfoDialog extends StatelessWidget {
children: [
ListTile(
leading: Avatar(
mxContent: event.sender.avatarUrl,
name: event.sender.calcDisplayname(),
mxContent: event.senderFromMemoryOrFallback.avatarUrl,
name: event.senderFromMemoryOrFallback.calcDisplayname(),
),
title: Text(L10n.of(context)!.sender),
subtitle:
Text('${event.sender.calcDisplayname()} [${event.senderId}]'),
subtitle: Text(
'${event.senderFromMemoryOrFallback.calcDisplayname()} [${event.senderId}]'),
),
ListTile(
title: Text(L10n.of(context)!.time),

View file

@ -75,7 +75,7 @@ class Message extends StatelessWidget {
EventTypes.Sticker,
EventTypes.Encrypted,
].contains(nextEvent!.type)
? nextEvent!.sender.id == event.sender.id && !displayTime
? nextEvent!.senderId == event.senderId && !displayTime
: false;
final textColor = ownMessage
? Theme.of(context).colorScheme.onPrimary
@ -125,11 +125,16 @@ class Message extends StatelessWidget {
),
),
))
: Avatar(
mxContent: event.sender.avatarUrl,
name: event.sender.calcDisplayname(),
onTap: () => onAvatarTab!(event),
),
: FutureBuilder<User?>(
future: event.fetchSenderUser(),
builder: (context, snapshot) {
final user = snapshot.data ?? event.senderFromMemoryOrFallback;
return Avatar(
mxContent: user.avatarUrl,
name: user.calcDisplayname(),
onTap: () => onAvatarTab!(event),
);
}),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -140,14 +145,22 @@ class Message extends StatelessWidget {
padding: const EdgeInsets.only(left: 8.0, bottom: 4),
child: ownMessage || event.room.isDirectChat
? const SizedBox(height: 12)
: Text(
event.sender.calcDisplayname(),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: event.sender.calcDisplayname().color,
),
),
: FutureBuilder<User?>(
future: event.fetchSenderUser(),
builder: (context, snapshot) {
final displayname =
snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback
.calcDisplayname();
return Text(
displayname,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: displayname.color,
),
);
}),
),
Container(
alignment: alignment,

View file

@ -34,7 +34,7 @@ class MessageContent extends StatelessWidget {
content: Text(
event.type == EventTypes.Encrypted
? L10n.of(context)!.needPantalaimonWarning
: event.getLocalizedBody(
: event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
),
)));
@ -172,48 +172,73 @@ class MessageContent extends StatelessWidget {
textmessage:
default:
if (event.redacted) {
return _ButtonContent(
label: L10n.of(context)!
.redactedAnEvent(event.sender.calcDisplayname()),
icon: const Icon(Icons.delete_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
return FutureBuilder<User?>(
future: event.fetchSenderUser(),
builder: (context, snapshot) {
return _ButtonContent(
label: L10n.of(context)!.redactedAnEvent(snapshot.data
?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname()),
icon: const Icon(Icons.delete_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
});
}
final bigEmotes = event.onlyEmotes &&
event.numberEmotes > 0 &&
event.numberEmotes <= 10;
return LinkText(
text: event.getLocalizedBody(MatrixLocals(L10n.of(context)!),
hideReply: true),
textStyle: TextStyle(
color: textColor,
fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: event.redacted ? TextDecoration.lineThrough : null,
),
linkStyle: TextStyle(
color: textColor.withAlpha(150),
fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: TextDecoration.underline,
),
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(),
);
return FutureBuilder<String>(
future: event.calcLocalizedBody(MatrixLocals(L10n.of(context)!),
hideReply: true),
builder: (context, snapshot) {
return LinkText(
text: snapshot.data ??
event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
hideReply: true),
textStyle: TextStyle(
color: textColor,
fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration:
event.redacted ? TextDecoration.lineThrough : null,
),
linkStyle: TextStyle(
color: textColor.withAlpha(150),
fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: TextDecoration.underline,
),
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(),
);
});
}
case EventTypes.CallInvite:
return _ButtonContent(
label: L10n.of(context)!.startedACall(event.sender.calcDisplayname()),
icon: const Icon(Icons.phone_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
return FutureBuilder<User?>(
future: event.fetchSenderUser(),
builder: (context, snapshot) {
return _ButtonContent(
label: L10n.of(context)!.startedACall(
snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname()),
icon: const Icon(Icons.phone_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
});
default:
return _ButtonContent(
label: L10n.of(context)!
.userSentUnknownEvent(event.sender.calcDisplayname(), event.type),
icon: const Icon(Icons.info_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
return FutureBuilder<User?>(
future: event.fetchSenderUser(),
builder: (context, snapshot) {
return _ButtonContent(
label: L10n.of(context)!.userSentUnknownEvent(
snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname(),
event.type),
icon: const Icon(Icons.info_outlined),
textColor: buttonTextColor,
onPressed: () => onInfoTab!(event),
);
});
}
}
}

View file

@ -39,7 +39,7 @@ class MessageReactions extends StatelessWidget {
);
}
reactionMap[key]!.count++;
reactionMap[key]!.reactors!.add(e.sender);
reactionMap[key]!.reactors!.add(e.senderFromMemoryOrFallback);
reactionMap[key]!.reacted |= e.senderId == e.room.client.userID;
}
}

View file

@ -52,7 +52,7 @@ class ReplyContent extends StatelessWidget {
);
} else {
replyBody = Text(
displayEvent.getLocalizedBody(
displayEvent.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
hideReply: true,
@ -83,18 +83,25 @@ class ReplyContent extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
displayEvent.sender.calcDisplayname() + ':',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
color: ownMessage
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onBackground,
fontSize: fontSize,
),
),
FutureBuilder<User?>(
future: displayEvent.fetchSenderUser(),
builder: (context, snapshot) {
return Text(
(snapshot.data?.calcDisplayname() ??
displayEvent.senderFromMemoryOrFallback
.calcDisplayname()) +
':',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
color: ownMessage
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onBackground,
fontSize: fontSize,
),
);
}),
replyBody,
],
),

View file

@ -39,16 +39,24 @@ class StateMessage extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
event.getLocalizedBody(MatrixLocals(L10n.of(context)!)),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14 * AppConfig.fontSizeFactor,
color: Theme.of(context).textTheme.bodyText2!.color,
decoration:
event.redacted ? TextDecoration.lineThrough : null,
),
),
FutureBuilder<String>(
future: event
.calcLocalizedBody(MatrixLocals(L10n.of(context)!)),
builder: (context, snapshot) {
return Text(
snapshot.data ??
event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!)),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14 * AppConfig.fontSizeFactor,
color: Theme.of(context).textTheme.bodyText2!.color,
decoration: event.redacted
? TextDecoration.lineThrough
: null,
),
);
}),
if (counter != 0)
Text(
L10n.of(context)!.moreEvents(counter),

View file

@ -26,7 +26,7 @@ class PinnedEvents extends StatelessWidget {
actions: events
.map((event) => SheetAction(
key: event?.eventId ?? '',
label: event?.getLocalizedBody(
label: event?.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true,
hideReply: true,
@ -90,32 +90,41 @@ class PinnedEvents extends StatelessWidget {
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: LinkText(
text: event.getLocalizedBody(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true,
hideReply: true,
),
maxLines: 2,
textStyle: TextStyle(
overflow: TextOverflow.ellipsis,
fontSize: fontSize,
decoration: event.redacted
? TextDecoration.lineThrough
: null,
),
linkStyle: TextStyle(
color: Theme.of(context)
.textTheme
.bodyText1
?.color
?.withAlpha(150),
fontSize: fontSize,
decoration: TextDecoration.underline,
),
onLinkTap: (url) =>
UrlLauncher(context, url).launchUrl(),
),
child: FutureBuilder<String>(
future: event.calcLocalizedBody(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true,
hideReply: true,
),
builder: (context, snapshot) {
return LinkText(
text: snapshot.data ??
event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true,
hideReply: true,
),
maxLines: 2,
textStyle: TextStyle(
overflow: TextOverflow.ellipsis,
fontSize: fontSize,
decoration: event.redacted
? TextDecoration.lineThrough
: null,
),
linkStyle: TextStyle(
color: Theme.of(context)
.textTheme
.bodyText1
?.color
?.withAlpha(150),
fontSize: fontSize,
decoration: TextDecoration.underline,
),
onLinkTap: (url) =>
UrlLauncher(context, url).launchUrl(),
);
}),
),
),
],

View file

@ -50,6 +50,7 @@ class _EditContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final event = this.event;
if (event == null) {
return Container();
}
@ -60,19 +61,27 @@ class _EditContent extends StatelessWidget {
color: Theme.of(context).primaryColor,
),
Container(width: 15.0),
Text(
event?.getLocalizedBody(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
hideReply: true,
) ??
'',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Theme.of(context).textTheme.bodyText2!.color,
),
),
FutureBuilder<String>(
future: event.calcLocalizedBody(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
hideReply: true,
),
builder: (context, snapshot) {
return Text(
snapshot.data ??
event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
hideReply: true,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Theme.of(context).textTheme.bodyText2!.color,
),
);
}),
],
);
}

View file

@ -94,15 +94,18 @@ class ChatEncryptionSettingsView extends StatelessWidget {
child: ListTile(
leading: Avatar(
mxContent: room
.getUserByMXIDSync(deviceKeys[i].userId)
.unsafeGetUserFromMemoryOrFallback(
deviceKeys[i].userId)
.avatarUrl,
name: room
.getUserByMXIDSync(deviceKeys[i].userId)
.unsafeGetUserFromMemoryOrFallback(
deviceKeys[i].userId)
.calcDisplayname(),
),
title: Text(
room
.getUserByMXIDSync(deviceKeys[i].userId)
.unsafeGetUserFromMemoryOrFallback(
deviceKeys[i].userId)
.calcDisplayname(),
),
subtitle: Text(

View file

@ -262,32 +262,47 @@ class ChatListItem extends StatelessWidget {
),
softWrap: false,
)
: Text(
room.membership == Membership.invite
? L10n.of(context)!.youAreInvitedToThisChat
: room.lastEvent?.getLocalizedBody(
MatrixLocals(L10n.of(context)!),
hideReply: true,
hideEdit: true,
plaintextBody: true,
removeMarkdown: true,
withSenderNamePrefix: !room.isDirectChat ||
room.directChatMatrixID !=
room.lastEvent?.senderId,
) ??
L10n.of(context)!.emptyChat,
softWrap: false,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: unread
? Theme.of(context).colorScheme.secondary
: Theme.of(context).textTheme.bodyText2!.color,
decoration: room.lastEvent?.redacted == true
? TextDecoration.lineThrough
: null,
),
),
: FutureBuilder<String>(
future: room.lastEvent?.calcLocalizedBody(
MatrixLocals(L10n.of(context)!),
hideReply: true,
hideEdit: true,
plaintextBody: true,
removeMarkdown: true,
withSenderNamePrefix: !room.isDirectChat ||
room.directChatMatrixID !=
room.lastEvent?.senderId,
) ??
Future.value(L10n.of(context)!.emptyChat),
builder: (context, snapshot) {
return Text(
room.membership == Membership.invite
? L10n.of(context)!.youAreInvitedToThisChat
: snapshot.data ??
room.lastEvent?.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
hideReply: true,
hideEdit: true,
plaintextBody: true,
removeMarkdown: true,
withSenderNamePrefix: !room.isDirectChat ||
room.directChatMatrixID !=
room.lastEvent?.senderId,
) ??
L10n.of(context)!.emptyChat,
softWrap: false,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: unread
? Theme.of(context).colorScheme.secondary
: Theme.of(context).textTheme.bodyText2!.color,
decoration: room.lastEvent?.redacted == true
? TextDecoration.lineThrough
: null,
),
);
}),
),
const SizedBox(width: 8),
AnimatedContainer(

View file

@ -48,7 +48,7 @@ class ClientChooserButton extends StatelessWidget {
(client) => PopupMenuItem(
value: client,
child: FutureBuilder<Profile>(
future: client!.ownProfile,
future: client!.fetchOwnProfile(),
builder: (context, snapshot) => Row(
children: [
Avatar(
@ -90,7 +90,7 @@ class ClientChooserButton extends StatelessWidget {
matrix.accountBundles.forEach((key, value) => clientCount += value.length);
return Center(
child: FutureBuilder<Profile>(
future: matrix.client.ownProfile,
future: matrix.client.fetchOwnProfile(),
builder: (context, snapshot) => Stack(
alignment: Alignment.center,
children: [

View file

@ -38,7 +38,7 @@ class InvitationSelectionController extends State<InvitationSelection> {
final participantsIds = participants.map((p) => p.stateKey).toList();
final contacts = client.rooms
.where((r) => r.isDirectChat)
.map((r) => r.getUserByMXIDSync(r.directChatMatrixID!))
.map((r) => r.unsafeGetUserFromMemoryOrFallback(r.directChatMatrixID!))
.toList()
..removeWhere((u) => participantsIds.contains(u.stateKey));
contacts.sort(

View file

@ -111,7 +111,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
if (directChatId != null) {
user = widget.request.client
.getRoomById(directChatId)!
.getUserByMXIDSync(widget.request.userId);
.unsafeGetUserFromMemoryOrFallback(widget.request.userId);
}
final displayName =
user?.calcDisplayname() ?? widget.request.userId.localpart!;

View file

@ -46,13 +46,11 @@ class SearchView extends StatelessWidget {
}).then((QueryPublicRoomsResponse res) {
final genericSearchTerm = controller.genericSearchTerm;
if (genericSearchTerm != null &&
!res.chunk.any((room) =>
(room.aliases?.contains(controller.genericSearchTerm) ?? false) ||
room.canonicalAlias == controller.genericSearchTerm)) {
!res.chunk.any(
(room) => room.canonicalAlias == controller.genericSearchTerm)) {
// we have to tack on the original alias
res.chunk.add(
PublicRoomsChunk(
aliases: [genericSearchTerm],
name: genericSearchTerm,
numJoinedMembers: 0,
roomId: '!unknown',

View file

@ -370,7 +370,7 @@ class StoryPageController extends State<StoryPage> {
.client
.getRoomById(roomId)
?.getState(EventTypes.RoomCreate)
?.sender
?.senderFromMemoryOrFallback
.avatarUrl;
String get title =>
@ -378,7 +378,7 @@ class StoryPageController extends State<StoryPage> {
.client
.getRoomById(roomId)
?.getState(EventTypes.RoomCreate)
?.sender
?.senderFromMemoryOrFallback
.calcDisplayname() ??
'Story not found';
@ -485,7 +485,8 @@ class StoryPageController extends State<StoryPage> {
case PopupStoryAction.message:
final roomIdResult = await showFutureLoadingDialog(
context: context,
future: () => currentEvent!.sender.startDirectChat(),
future: () =>
currentEvent!.senderFromMemoryOrFallback.startDirectChat(),
);
if (roomIdResult.error != null) return;
VRouter.of(context).toSegments(['rooms', roomIdResult.result!]);