Commit 801f1391 authored by Wilko Manger's avatar Wilko Manger

Always use current display name

This changes brings some structural changes with it,
namely that now in widgets ChatMember should be used
instead of the Matrix SDK's User directly.
parent 3afc89a9
......@@ -24,12 +24,12 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import '../auth/bloc.dart';
import '../matrix.dart';
import '../util/room.dart';
import '../util/user.dart';
import '../util/url.dart';
import 'event.dart';
......@@ -115,7 +115,7 @@ class NotificationsBloc extends Bloc<NotificationsEvent, NotificationsState> {
static Message _eventToMessage(RoomEvent event, Person person) {
if (event is EmoteMessageEvent) {
return Message(
'${event.sender.displayName} ${event.content.body}',
'${person.name} ${event.content.body}',
event.time,
person,
);
......@@ -150,15 +150,19 @@ class NotificationsBloc extends Bloc<NotificationsEvent, NotificationsState> {
final room = await user.rooms[message.roomId];
final event = await room.timeline[message.eventId];
final senderName = event.sender.displayName;
final icon = await DefaultCacheManager().getSingleFile(
event.sender.avatarUrl.toThumbnailStringWith(user.homeserver),
);
final sender = await ChatMember.fromUser(
room,
event.sender,
isYou: false,
);
final senderPerson = Person(
bot: false,
name: senderName,
name: sender.name,
icon: icon.path,
iconSource: IconSource.FilePath,
);
......
......@@ -172,20 +172,20 @@ class ChatBloc extends Bloc<ChatEvent, ChatState> {
final inReplyToEvent = await room.timeline[event.content.inReplyToId];
if (inReplyToEvent != null) {
inReplyTo = ChatMessage(
inReplyTo = await ChatMessage.create(
room,
inReplyToEvent,
isMine: inReplyToEvent.sender == me,
isMe: (u) => u == matrix.user,
);
}
}
messages.add(
ChatMessage(
await ChatMessage.create(
room,
event,
inReplyTo: inReplyTo,
isMine: event.sender == me,
isMe: (u) => u == matrix.user,
),
);
}
......
......@@ -18,6 +18,7 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../../matrix.dart';
import 'event.dart';
......@@ -54,7 +55,13 @@ class ImageBloc extends Bloc<ImageEvent, ImageState> {
}
}
yield ImagesLoaded(imageMessageEvents);
final messages = await Future.wait(
imageMessageEvents.map(
(i) => ChatMessage.create(_room, i, isMe: (u) => u == _matrix.user),
),
);
yield ImagesLoaded(messages);
}
}
......
......@@ -19,28 +19,28 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import '../../../../matrix.dart';
import '../../../../util/date_format.dart';
import '../../../../util/user.dart';
import '../../../../util/url.dart';
import 'bloc.dart';
class ImagePage extends StatefulWidget {
final ImageMessageEvent event;
final ChatMessage message;
ImagePage._(this.event);
ImagePage._(this.message);
static Widget withBloc(ChatMessage message) {
assert(message.event is ImageMessageEvent);
return BlocProvider<ImageBloc>(
create: (c) => ImageBloc(Matrix.of(c), message.room),
child: ImagePage._(message.event),
child: ImagePage._(message),
);
}
......@@ -49,7 +49,7 @@ class ImagePage extends StatefulWidget {
}
class _ImagePageState extends State<ImagePage> {
User _messageSender;
ChatMember _messageSender;
String _date;
@override
......@@ -63,10 +63,10 @@ class _ImagePageState extends State<ImagePage> {
BlocProvider.of<ImageBloc>(context).add(FetchImages());
_messageSender = widget.event.sender;
_messageSender = widget.message.sender;
_date = '${formatAsDate(context, widget.event.time)},'
' ${formatAsTime(widget.event.time)}';
_date = '${formatAsDate(context, widget.message.event.time)},'
' ${formatAsTime(widget.message.event.time)}';
}
@override
......@@ -85,7 +85,7 @@ class _ImagePageState extends State<ImagePage> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_messageSender.displayName),
Text(_messageSender.name),
SizedBox(height: 2),
Text(
_date,
......@@ -108,28 +108,30 @@ class _ImagePageState extends State<ImagePage> {
return BlocBuilder<ImageBloc, ImageState>(
builder: (context, state) {
if (state is ImagesLoaded) {
final events = state.events;
final messages = state.messages;
return PhotoViewGallery.builder(
itemCount: events.length,
itemCount: messages.length,
reverse: true,
builder: (context, index) {
final event = messages[index].event as ImageMessageEvent;
return PhotoViewGalleryPageOptions(
imageProvider: CachedNetworkImageProvider(
events[index].content.url.toDownloadString(context),
event.content.url.toDownloadString(context),
),
heroTag: widget.event.id,
heroTag: widget.message.event.id,
minScale: PhotoViewComputedScale.contained,
);
},
onPageChanged: (index) {
setState(() {
_messageSender = events[index].sender;
_date = '${formatAsDate(context, events[index].time)}, '
'${formatAsTime(events[index].time)}';
_messageSender = messages[index].sender;
_date = '${formatAsDate(context, messages[index].event.time)}, '
'${formatAsTime(messages[index].event.time)}';
});
},
pageController: PageController(
initialPage: events.indexOf(widget.event),
initialPage: messages.indexOf(widget.message),
),
);
}
......
import 'package:equatable/equatable.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
abstract class ImageState extends Equatable {
@override
......@@ -11,10 +11,10 @@ class ImagesUninitialized extends ImageState {}
class ImagesLoading extends ImageState {}
class ImagesLoaded extends ImageState {
final List<ImageMessageEvent> events;
final List<ChatMessage> messages;
ImagesLoaded(this.events);
ImagesLoaded(this.messages);
@override
List<Object> get props => [events];
List<Object> get props => [messages];
}
......@@ -19,6 +19,7 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import '../../../../matrix.dart';
import 'event.dart';
......@@ -41,14 +42,20 @@ class ChatSettingsBloc extends Bloc<ChatSettingsEvent, ChatSettingsState> {
if (event is FetchMembers) {
final me = await _room.members[_matrix.user.id];
var members = List.of(
var user = List.of(
await _room.members.get(upTo: !event.all ? 6 : _room.members.count),
);
members = members.where((u) => u.state.membership is Joined).toList();
user = user.where((u) => u.state.membership is Joined).toList();
members.remove(me);
members.insert(0, me);
user.remove(me);
user.insert(0, me);
final members = await Future.wait(
user.map(
(u) => ChatMember.fromUser(_room, u, isYou: _matrix.user == u),
),
);
yield MembersLoaded(members);
}
......
......@@ -24,8 +24,9 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/resources/theme.dart';
import 'package:pattle/src/section/main/chats/models/chat.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import 'package:pattle/src/section/main/widgets/chat_name.dart';
import 'package:pattle/src/section/main/widgets/user_item.dart';
import 'package:pattle/src/section/main/widgets/chat_member_tile.dart';
import '../../../../matrix.dart';
import '../../../../util/url.dart';
......@@ -200,7 +201,7 @@ class _MemberListState extends State<_MemberList> {
SizedBox(height: 4),
BlocBuilder<ChatSettingsBloc, ChatSettingsState>(
builder: (context, state) {
var members = List<User>();
var members = List<ChatMember>();
if (state is MembersLoaded) {
members = state.members;
}
......@@ -235,8 +236,8 @@ class _MemberListState extends State<_MemberList> {
);
}
return UserItem(
user: members[index],
return ChatMemberTile(
member: members[index],
);
},
),
......
import 'package:equatable/equatable.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
abstract class ChatSettingsState extends Equatable {
@override
......@@ -11,7 +11,7 @@ class ChatSettingsUninitialized extends ChatSettingsState {}
class MembersLoading extends ChatSettingsState {}
class MembersLoaded extends ChatSettingsState {
final List<User> members;
final List<ChatMember> members;
MembersLoaded(this.members);
......
......@@ -19,8 +19,7 @@ import 'package:flutter/widgets.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/resources/localizations.dart';
import '../../../../util/user.dart';
// TODO: Use Widget and ChatMember
List<TextSpan> typingSpan(BuildContext context, Room room) {
if (room.isDirect) {
return l(context).typing;
......@@ -29,7 +28,7 @@ List<TextSpan> typingSpan(BuildContext context, Room room) {
if (room.typingUsers.length == 1) {
return l(context).isTyping(
TextSpan(
text: room.typingUsers.first.displayName,
text: room.typingUsers.first.name,
),
);
}
......@@ -37,20 +36,20 @@ List<TextSpan> typingSpan(BuildContext context, Room room) {
if (room.typingUsers.length == 2) {
return l(context).areTyping(
TextSpan(
text: room.typingUsers.first.displayName,
text: room.typingUsers.first.name,
),
TextSpan(
text: room.typingUsers[1].displayName,
text: room.typingUsers[1].name,
),
);
}
return l(context).andMoreAreTyping(
TextSpan(
text: room.typingUsers.first.displayName,
text: room.typingUsers.first.name,
),
TextSpan(
text: room.typingUsers[1].displayName,
text: room.typingUsers[1].name,
),
);
}
......@@ -54,7 +54,7 @@ class RedactedContent extends StatelessWidget {
dark: bubble.message.isMine ? Colors.white30 : Colors.white70,
),
),
child: Redacted(event: bubble.message.event),
child: Redacted(redaction: bubble.message.redaction),
),
if (MessageInfo.necessary(context))
Padding(
......
......@@ -21,7 +21,7 @@ import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_html/flutter_html.dart';
import '../../../../../../../util/color.dart';
import '../../../../../../../util/user.dart';
import '../../../../../../../util/chat_member.dart';
import '../../message.dart';
......@@ -45,7 +45,7 @@ class TextContent extends StatelessWidget {
? _ReplyBorderPainter(
color: bubble.message.isMine && bubble.reply?.isMine == true
? Colors.white
: bubble.message.event.sender.getColor(context),
: bubble.message.sender.color(context),
borderRadius: bubble.borderRadius,
)
: null,
......
......@@ -19,6 +19,7 @@ import 'package:flutter/material.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/resources/theme.dart';
import 'package:pattle/src/section/main/chat/widgets/bubble/message/content/loading.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import 'package:pattle/src/section/main/widgets/message_state.dart';
import 'package:pattle/src/util/color.dart';
......@@ -29,7 +30,7 @@ import 'content/image.dart';
import 'content/redacted.dart';
import 'content/text.dart';
import '../../../../../../util/user.dart';
import '../../../../../../util/chat_member.dart';
class MessageBubble extends StatelessWidget {
final ChatMessage message;
......@@ -144,7 +145,18 @@ class MessageBubble extends StatelessWidget {
body: 'Blabla',
),
),
isMine: isMine,
sender: ChatMember(
User(
id: UserId('@wilko:pattle.im'),
state: UserState(
roomId: RoomId('!343432:pattle.im'),
displayName: 'Wilko',
since: DateTime.now(),
),
),
isYou: isMine,
name: 'Wilko',
),
),
child: LoadingContent(),
);
......@@ -167,7 +179,7 @@ class MessageBubble extends StatelessWidget {
}
final previousHasSameSender = previousEvent != null &&
previousEvent.sender.displayName == event.sender.displayName &&
previousMessage.sender.name == previousMessage.sender.name &&
previousEvent.sender == event.sender;
if (!previousHasSameSender) {
......@@ -201,7 +213,7 @@ class MessageBubble extends StatelessWidget {
}
final nextHasSameSender = nextEvent != null &&
nextEvent.sender.displayName == event.sender.displayName &&
nextMessage.sender.name == nextMessage.sender.name &&
nextEvent.sender == event.sender;
if (!nextHasSameSender) {
......@@ -419,12 +431,10 @@ class Sender extends StatelessWidget {
final bubble = MessageBubble.of(context);
return Text(
bubble.message.event.sender.displayName,
bubble.message.sender.name,
style: TextStyle(
fontWeight: FontWeight.bold,
color: personalizedColor
? bubble.message.event.sender.getColor(context)
: null,
color: personalizedColor ? bubble.message.sender.color(context) : null,
),
);
}
......
......@@ -20,8 +20,6 @@ import 'package:flutter/material.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../../../../../util/user.dart';
import '../state.dart';
/// If [message] is `null`, will try to get the [message] from the
......@@ -40,7 +38,10 @@ class CreationContent extends StatelessWidget {
style: DefaultTextStyle.of(context).style,
children: l(context).createdThisGroup(
TextSpan(
text: message.room.creator.displayName,
text: message.sender.name,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
......
......@@ -17,10 +17,10 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../../util/member_span.dart';
import '../state.dart';
/// If [message] is `null`, will try to get the [message] from the
......@@ -30,6 +30,34 @@ class MemberChangeContent extends StatelessWidget {
const MemberChangeContent({Key key, this.message}) : super(key: key);
List<TextSpan> _span(BuildContext context, ChatMessage message) {
final event = message.event;
final style = TextStyle(fontWeight: FontWeight.bold);
final sender = TextSpan(
text: message.sender.name,
style: style,
);
final subject = TextSpan(
text: message.subject.name,
style: style,
);
var text;
if (event is JoinEvent) {
text = l(context).joined(subject);
} else if (event is LeaveEvent) {
text = l(context).left(subject);
} else if (event is InviteEvent) {
text = l(context).wasInvitedBy(subject, sender);
} else if (event is BanEvent) {
text = l(context).wasBannedBy(subject, sender);
}
return text;
}
@override
Widget build(BuildContext context) {
final message = this.message ?? StateBubble.of(context).message;
......@@ -37,10 +65,7 @@ class MemberChangeContent extends StatelessWidget {
return RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: spanFor(
context,
message.event,
),
children: _span(context, message),
),
);
}
......
......@@ -20,8 +20,6 @@ import 'package:flutter/material.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../../../../../util/user.dart';
import '../state.dart';
/// If [message] is `null`, will try to get the [message] from the
......@@ -40,7 +38,7 @@ class TopicChangeContent extends StatelessWidget {
style: DefaultTextStyle.of(context).style,
children: l(context).changedDescriptionTapToView(
TextSpan(
text: message.event.sender.displayName,
text: message.sender.name,
),
),
),
......
......@@ -20,8 +20,6 @@ import 'package:flutter/material.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../../../../../util/user.dart';
import '../state.dart';
/// If [message] is `null`, will try to get the [message] from the
......@@ -40,7 +38,7 @@ class UpgradeContent extends StatelessWidget {
style: DefaultTextStyle.of(context).style,
children: l(context).upgradedThisGroup(
TextSpan(
text: message.event.sender.displayName,
text: message.sender.name,
),
),
),
......
......@@ -17,6 +17,7 @@
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import 'package:pattle/src/section/main/models/chat_message.dart';
import '../../../matrix.dart';
......@@ -79,17 +80,21 @@ class ChatsBloc extends Bloc<ChatsEvent, ChatsState> {
name: await room.getDisplayName(),
isJustYou: room.members.count == 1,
latestMessage: latestEvent != null
? ChatMessage(
? await ChatMessage.create(
room,
latestEvent,
isMine: latestEvent.sender == _matrix.user,
isMe: (u) => u == _matrix.user,
)
: null,
latestMessageForSorting: latestEventForSorting != null
? ChatMessage(
room,
latestEventForSorting,
isMine: latestEventForSorting.sender == _matrix.user,
sender: await ChatMember.fromUser(
room,
latestEventForSorting.sender,
isYou: latestEventForSorting.sender == _matrix.user,
),
)
: null,
);
......
......@@ -16,9 +16,9 @@
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
import '../../../../../matrix.dart';
import '../../../../../util/user.dart';
import 'event.dart';
export 'event.dart';
......@@ -31,7 +31,7 @@ class CreateGroupBloc extends Bloc<CreateGroupEvent, CreateGroupState> {
bool _isCreatingGroup = false;
final _members = List<User>();
final _members = List<ChatMember>();
String _groupName;
......@@ -44,13 +44,13 @@ class CreateGroupBloc extends Bloc<CreateGroupEvent, CreateGroupState> {
CreateGroupState get initialState => InitialCreateGroupState();
Stream<CreateGroupState> _loadUsers() async* {
final users = Set<User>();
final users = Set<ChatMember>();
// Load members of some rooms, in the future
// this'll be based on activity and what not
for (final room in await matrix.user.rooms.get(upTo: 10)) {
for (final user in await room.members.get(upTo: 20)) {
if (user != matrix.user) {
users.add(user);
users.add(await ChatMember.fromUser(room, user, isYou: false));
}
}
}
......@@ -58,7 +58,7 @@ class CreateGroupBloc extends Bloc<CreateGroupEvent, CreateGroupState> {
yield UserListUpdated(
users.toList(growable: false)
..sort(
(User a, User b) => a.displayName.compareTo(b.displayName),
(a, b) => a.name.compareTo(b.name),
),
members: _members,
);
......@@ -72,7 +72,7 @@ class CreateGroupBloc extends Bloc<CreateGroupEvent, CreateGroupState> {
final id = await matrix.user.rooms.create(
name: _groupName,
invitees: _members,
invitees: _members.map((m) => m.user),
);
// Await the next sync so the room has been processed
......@@ -97,12 +97,12 @@ class CreateGroupBloc extends Bloc<CreateGroupEvent, CreateGroupState> {
}
if (event is AddMember) {
_members.add(event.user);
_members.add(event.member);
yield MemberListUpdated(_members);
}
if (event is RemoveMember) {
_members.remove(event.user);
_members.remove(event.member);
yield MemberListUpdated(_members);
}
}
......
......@@ -21,9 +21,8 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/app.dart';
import 'package:pattle/src/resources/localizations.dart';
import 'package:pattle/src/section/main/widgets/error.dart';
import 'package:pattle/src/section/main/widgets/user_avatar.dart';
import 'package:pattle/src/section/main/widgets/chat_member_avatar.dart';
import '../../../../../util/user.dart';
import 'bloc.dart';
class CreateGroupDetailsPage extends StatefulWidget {
......@@ -138,7 +137,7 @@ class _CreateGroupDetailsPageState extends State<CreateGroupDetailsPage> {
builder: (context, state) {
final children = List<Widget>();
for (final user in state?.members) {
for (final member in state?.members) {
children.add(
Column(
mainAxisSize: MainAxisSize.min,
......@@ -149,12 +148,12 @@ class _CreateGroupDetailsPageState extends State<CreateGroupDetailsPage> {
padding: EdgeInsets.all(8),
child: AspectRatio(
aspectRatio: 1 / 1,
child: UserAvatar(user: user, radius: 32),
child: ChatMemberAvatar(member: member, radius: 32),
),
),
),
Text(
user.getDisplayName(context),
member.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
......
import 'package:equatable/equatable.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:pattle/src/section/main/models/chat_member.dart';
abstract class CreateGroupEvent extends Equatable {
@override
......@@ -18,15 +18,15 @@ class UpdateGroupName extends CreateGroupEvent {
}
class AddMember extends CreateGroupEvent {