Render room avatar change events

parent 972b194c
{
"@@last_modified": "2020-05-30T16:46:37.614297",
"@@last_modified": "2020-06-04T16:02:06.691997",
"appName": "Pattle",
"@appName": {
"type": "text",
......@@ -188,6 +188,23 @@
"name": {}
}
},
"_ChatMessage_iconChange": "{person,select, second{You changed this group''s icon}third{{name} changed this group''s icon}}",
"@_ChatMessage_iconChange": {
"type": "text",
"placeholders": {
"person": {},
"name": {}
}
},
"_ChatMessage_iconChangeTo": "{person,select, second{You changed this group''s icon to}third{{name} changed this group''s icon to}}",
"@_ChatMessage_iconChangeTo": {
"description": "After the end of the sentence a small version of the chat icon is placed.",
"type": "text",
"placeholders": {
"person": {},
"name": {}
}
},
"_ChatMessage_join": "{person,select, second{You joined}third{{name} joined}}",
"@_ChatMessage_join": {
"type": "text",
......
......@@ -188,6 +188,23 @@
"name": {}
}
},
"_ChatMessage_iconChange": "{person,select, second{Je hebt het icoon van de groep verandert}third{{name} heeft het icoon van de groep verandert}}",
"@_ChatMessage_iconChange": {
"type": "text",
"placeholders": {
"person": {},
"name": {}
}
},
"_ChatMessage_iconChangeTo": "{person,select, second{Je hebt het icoon van de groep verandert naar}third{{name} heeft het icoon van de groep verandert naar}}",
"@_ChatMessage_iconChangeTo": {
"description": "After the end of the sentence a small version of the chat icon is placed.",
"type": "text",
"placeholders": {
"person": {},
"name": {}
}
},
"_ChatMessage_join": "{person,select, second{Je bent aan het gesprek toegevoegd}third{{name} is aan het gesprek toegevoegd}}",
"@_ChatMessage_join": {
"type": "text",
......
......@@ -563,6 +563,34 @@ class _ChatMessage extends _Category {
);
}
String iconChange(Person person, String name) {
return Intl.select(
person,
{
Person.second: 'You changed this group\'s icon',
Person.third: '$name changed this group\'s icon',
},
args: [person, name],
name: '_ChatMessage_iconChange',
locale: _localeName,
);
}
String iconChangeTo(Person person, String name) {
return Intl.select(
person,
{
Person.second: 'You changed this group\'s icon to',
Person.third: '$name changed this group\'s icon to',
},
args: [person, name],
name: '_ChatMessage_iconChangeTo',
desc: 'After the end of the sentence a small version of the chat icon is'
' placed.',
locale: _localeName,
);
}
String join(Person person, String name) {
return Intl.select(
person,
......
......@@ -47,41 +47,51 @@ class MessageLookup extends MessageLookupByLibrary {
'third': '${name} changed the description of this group',
})}";
static m6(person, invitee, inviter) => "${Intl.select(person, {
static m6(person, name) => "${Intl.select(person, {
'second': 'You changed this group\'s icon',
'third': '${name} changed this group\'s icon',
})}";
static m7(person, name) => "${Intl.select(person, {
'second': 'You changed this group\'s icon to',
'third': '${name} changed this group\'s icon to',
})}";
static m8(person, invitee, inviter) => "${Intl.select(person, {
'secondOnSecond': 'You were invited by yourself',
'secondOnThird': 'You were invited by ${inviter}',
'thirdOnThird': '${invitee} was invited by ${inviter}',
'thirdOnSecond': '${invitee} was invited by you',
})}";
static m7(person, name) => "${Intl.select(person, {
static m9(person, name) => "${Intl.select(person, {
'second': 'You joined',
'third': '${name} joined',
})}";
static m8(person, name) => "${Intl.select(person, {
static m10(person, name) => "${Intl.select(person, {
'second': 'You left',
'third': '${name} left',
})}";
static m9(person, name) => "${Intl.select(person, {
static m11(person, name) => "${Intl.select(person, {
'second': 'You changed the name of this group',
'third': '${name} changed the name of this group',
})}";
static m10(person, name) => "${Intl.select(person, {
static m12(person, name) => "${Intl.select(person, {
'second': 'You upgraded this group',
'third': '${name} upgraded this group',
})}";
static m11(andMore, first, second) => "${Intl.select(andMore, {
static m13(andMore, first, second) => "${Intl.select(andMore, {
'false': '${first} and ${second} are typing...',
'true': '${first}, ${second} and more are typing...',
})}";
static m12(name) => "${name} is typing...";
static m14(name) => "${name} is typing...";
static m13(version) => "Version ${version}";
static m15(version) => "Version ${version}";
final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function>{
......@@ -97,15 +107,17 @@ class MessageLookup extends MessageLookupByLibrary {
"_ChatMessage_creation": m3,
"_ChatMessage_deletion": m4,
"_ChatMessage_descriptionChange": m5,
"_ChatMessage_invite": m6,
"_ChatMessage_join": m7,
"_ChatMessage_leave": m8,
"_ChatMessage_nameChange": m9,
"_ChatMessage_upgrade": m10,
"_Chat_areTyping": m11,
"_ChatMessage_iconChange": m6,
"_ChatMessage_iconChangeTo": m7,
"_ChatMessage_invite": m8,
"_ChatMessage_join": m9,
"_ChatMessage_leave": m10,
"_ChatMessage_nameChange": m11,
"_ChatMessage_upgrade": m12,
"_Chat_areTyping": m13,
"_Chat_cantSendMessages": MessageLookupByLibrary.simpleMessage(
"You can\'t send messages to this group because you\'re no longer a participant."),
"_Chat_isTyping": m12,
"_Chat_isTyping": m14,
"_Chat_typeAMessage":
MessageLookupByLibrary.simpleMessage("Type a message"),
"_Chat_typing": MessageLookupByLibrary.simpleMessage("typing..."),
......@@ -161,7 +173,7 @@ class MessageLookup extends MessageLookupByLibrary {
"_Settings_editNameDescription": MessageLookupByLibrary.simpleMessage(
"This is not your username. This is the name that will be visible to others."),
"_Settings_title": MessageLookupByLibrary.simpleMessage("Settings"),
"_Settings_version": m13,
"_Settings_version": m15,
"_StartUsername_hostnameInvalidError":
MessageLookupByLibrary.simpleMessage("Invalid hostname"),
"_StartUsername_title":
......
......@@ -47,36 +47,51 @@ class MessageLookup extends MessageLookupByLibrary {
'third': '${name} heeft de beschrijving van de groep aangepast',
})}";
static m6(person, invitee, inviter) => "${Intl.select(person, {
static m6(person, name) => "${Intl.select(person, {
'second': 'Je hebt het icoon van de groep verandert',
'third': '${name} heeft het icoon van de groep verandert',
})}";
static m7(person, name) => "${Intl.select(person, {
'second': 'Je hebt het icoon van de groep verandert naar',
'third': '${name} heeft het icoon van de groep verandert naar',
})}";
static m8(person, invitee, inviter) => "${Intl.select(person, {
'secondOnSecond': 'Je bent door jezelf uitgenodigd',
'secondOnThird': 'Je bent uitgenodigd door ${inviter}',
'thirdOnThird': '${invitee} is uitgenodigd door ${inviter}',
'thirdOnSecond': '${invitee} is uitgenodigd door jou',
})}";
static m7(person, name) => "${Intl.select(person, {
static m9(person, name) => "${Intl.select(person, {
'second': 'Je bent aan het gesprek toegevoegd',
'third': '${name} is aan het gesprek toegevoegd',
})}";
static m8(person, name) => "${Intl.select(person, {
static m10(person, name) => "${Intl.select(person, {
'second': 'Je hebt het gesprek verlaten',
'third': '${name} heeft het gesprek verlaten',
})}";
static m10(person, name) => "${Intl.select(person, {
static m11(person, name) => "${Intl.select(person, {
'second': 'Je hebt de naam van de groep aangepast',
'third': '${name} heeft de naam van de groep aangepast',
})}";
static m12(person, name) => "${Intl.select(person, {
'second': 'Je hebt deze groep geüpgrade',
'third': '${name} heeft deze groep geüpgrade',
})}";
static m11(andMore, first, second) => "${Intl.select(andMore, {
static m13(andMore, first, second) => "${Intl.select(andMore, {
'false': '${first} en ${second} typen...',
'true': '${first}, ${second} en anderen typen...',
})}";
static m12(name) => "${name} typt...";
static m14(name) => "${name} typt...";
static m13(version) => "Versie ${version}";
static m15(version) => "Versie ${version}";
final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function>{
......@@ -92,14 +107,17 @@ class MessageLookup extends MessageLookupByLibrary {
"_ChatMessage_creation": m3,
"_ChatMessage_deletion": m4,
"_ChatMessage_descriptionChange": m5,
"_ChatMessage_invite": m6,
"_ChatMessage_join": m7,
"_ChatMessage_leave": m8,
"_ChatMessage_upgrade": m10,
"_Chat_areTyping": m11,
"_ChatMessage_iconChange": m6,
"_ChatMessage_iconChangeTo": m7,
"_ChatMessage_invite": m8,
"_ChatMessage_join": m9,
"_ChatMessage_leave": m10,
"_ChatMessage_nameChange": m11,
"_ChatMessage_upgrade": m12,
"_Chat_areTyping": m13,
"_Chat_cantSendMessages": MessageLookupByLibrary.simpleMessage(
"Je kan geen berichten naar deze groep sturen omdat je geen deelnemer meer bent."),
"_Chat_isTyping": m12,
"_Chat_isTyping": m14,
"_Chat_typeAMessage":
MessageLookupByLibrary.simpleMessage("Typ een bericht"),
"_Chat_typing":
......@@ -158,7 +176,7 @@ class MessageLookup extends MessageLookupByLibrary {
"_Settings_editNameDescription": MessageLookupByLibrary.simpleMessage(
"Dit is niet je gebruikersnaam. Deze naam is zichtbaar voor anderen."),
"_Settings_title": MessageLookupByLibrary.simpleMessage("Instellingen"),
"_Settings_version": m13,
"_Settings_version": m15,
"_StartUsername_hostnameInvalidError":
MessageLookupByLibrary.simpleMessage("Ongeldige hostnaam"),
"_StartUsername_title":
......
......@@ -333,7 +333,10 @@ class _MessageListState extends State<_MessageList> {
Widget bubble;
if (event is StateEvent) {
bubble = StateBubble.withContent(message: message);
bubble = StateBubble.withContent(
chat: widget.chat,
message: message,
);
} else {
bubble = MessageBubble.withContent(
chat: widget.chat,
......@@ -454,6 +457,7 @@ class _InviteSplash extends StatelessWidget {
),
SizedBox(height: 16),
StateBubble.withContent(
chat: chat,
// Latest message should be the invite event
message: chat.latestMessage,
),
......
// Copyright (C) 2020 Wilko Manger
// Copyright (C) 2019 Mathieu Velten (FLA signed)
//
// This file is part of Pattle.
//
// Pattle is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pattle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Pattle. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import '../../../../../../../resources/intl/localizations.dart';
import '../../../../../chats/widgets/chat_avatar.dart';
import '../../../../../../../models/chat.dart';
import '../../../../../../../models/chat_message.dart';
import '../state.dart';
import 'state_content.dart';
/// If [message] is `null`, will try to get the [message] from the
/// ancestor [StateBubble].
class AvatarChangeContent extends StatelessWidget {
final Chat chat;
final ChatMessage message;
final bool withImage;
const AvatarChangeContent({
Key key,
this.chat,
this.message,
this.withImage = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final content = StateContent.singleName(
message: message,
content: (withImage
? context.intl.chat.message.iconChangeTo
: context.intl.chat.message.iconChange)
.toTextSpans,
person: (message) => message.sender.person,
name: (message) => message.sender.name,
);
return !withImage
? content
: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
content,
SizedBox(
width: DefaultTextStyle.of(context).style.fontSize * 0.3,
),
ChatAvatar(
chat: chat ?? StateBubble.of(context).chat,
radius: DefaultTextStyle.of(context).style.fontSize * 0.8,
),
],
);
}
}
......@@ -21,8 +21,11 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:provider/provider.dart';
import '../../../../../../resources/theme.dart';
import '../../../../../../models/chat.dart';
import '../../../../../../models/chat_message.dart';
import 'content/avatar_change.dart';
import 'content/creation.dart';
import 'content/member_change.dart';
import 'content/name_change.dart';
......@@ -32,15 +35,22 @@ import 'content/upgrade.dart';
import '../../../../../../util/date_format.dart';
class StateBubble extends StatelessWidget {
final Chat chat;
final ChatMessage message;
final Widget child;
StateBubble({Key key, this.message, this.child}) : super(key: key) {
StateBubble({
Key key,
@required this.chat,
@required this.message,
this.child,
}) : super(key: key) {
assert(message.event is StateEvent);
}
/// Create a [StateBubble] with the correct [child] for the given [message].
factory StateBubble.withContent({
@required Chat chat,
@required ChatMessage message,
}) {
final event = message.event;
......@@ -55,11 +65,14 @@ class StateBubble extends StatelessWidget {
content = NameChangeContent();
} else if (event is TopicChangeEvent) {
content = TopicChangeContent();
} else if (event is RoomAvatarChangeEvent) {
content = AvatarChangeContent(withImage: true);
} else if (event is UpgradeContent) {
content = UpgradeContent();
}
return StateBubble(
chat: chat,
message: message,
child: content,
);
......
......@@ -24,8 +24,9 @@ import '../../../../util/chat_member.dart';
class ChatAvatar extends StatelessWidget {
final Chat chat;
final double radius;
const ChatAvatar({Key key, this.chat}) : super(key: key);
const ChatAvatar({Key key, this.chat, this.radius}) : super(key: key);
@override
Widget build(BuildContext context) {
......@@ -37,16 +38,19 @@ class ChatAvatar extends StatelessWidget {
if (chat.isDirect) {
return Avatar.direct(
url: avatarUrl,
radius: radius,
placeholderColor: placeholderColor,
);
} else if (chat.isChannel) {
return Avatar.channel(
url: avatarUrl,
radius: radius,
placeholderColor: placeholderColor,
);
} else {
return Avatar.group(
url: avatarUrl,
radius: radius,
placeholderColor: placeholderColor,
);
}
......
......@@ -17,6 +17,7 @@
import 'package:flutter/material.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:provider/provider.dart';
import '../../../../../resources/theme.dart';
......@@ -28,6 +29,7 @@ import '../../../chat/widgets/bubble/state/content/creation.dart';
import '../../../chat/widgets/bubble/state/content/member_change.dart';
import '../../../chat/widgets/bubble/state/content/name_change.dart';
import '../../../chat/widgets/bubble/state/content/topic_change.dart';
import '../../../chat/widgets/bubble/state/content/avatar_change.dart';
import '../../../chat/widgets/bubble/state/content/upgrade.dart';
import '../typing_content.dart';
......@@ -63,6 +65,8 @@ class Subtitle extends StatelessWidget {
content = NameChangeContent(message: chat.latestMessage);
} else if (event is TopicChangeEvent) {
content = TopicChangeContent(message: chat.latestMessage);
} else if (event is RoomAvatarChangeEvent) {
content = AvatarChangeContent(chat: chat, message: chat.latestMessage);
} else if (event is RoomUpgradeEvent) {
content = UpgradeContent(message: chat.latestMessage);
} else if (event is RoomCreationEvent) {
......
......@@ -25,6 +25,7 @@ import '../../../util/url.dart';
class Avatar extends StatelessWidget {
final Uri url;
final double radius;
final Color placeholderColor;
final _AvatarType _type;
......@@ -32,18 +33,22 @@ class Avatar extends StatelessWidget {
const Avatar._({
Key key,
this.url,
double radius,
this.placeholderColor,
@required _AvatarType type,
}) : _type = type,
radius = radius ?? 24,
super(key: key);
Avatar.direct({
Key key,
Uri url,
double radius,
Color placeholderColor,
}) : this._(
key: key,
url: url,
radius: radius,
placeholderColor: placeholderColor,
type: _AvatarType.direct,
);
......@@ -51,10 +56,12 @@ class Avatar extends StatelessWidget {
Avatar.group({
Key key,
Uri url,
double radius,
Color placeholderColor,
}) : this._(
key: key,
url: url,
radius: radius,
placeholderColor: placeholderColor,
type: _AvatarType.group,
);
......@@ -62,10 +69,12 @@ class Avatar extends StatelessWidget {
Avatar.channel({
Key key,
Uri url,
double radius,
Color placeholderColor,
}) : this._(
key: key,
url: url,
radius: radius,
placeholderColor: placeholderColor,
type: _AvatarType.channel,
);
......@@ -79,8 +88,8 @@ class Avatar extends StatelessWidget {
if (url != null) {
return Container(
width: 48,
height: 48,
width: radius * 2,
height: radius * 2,
child: ClipOval(
child: FadeInImage(
fit: BoxFit.cover,
......@@ -102,11 +111,13 @@ class Avatar extends StatelessWidget {
class _PlaceholderAvatar extends StatelessWidget {
final _AvatarType type;
final double radius;
final Color color;
const _PlaceholderAvatar({
Key key,
@required this.type,
this.radius,
this.color,
}) : super(key: key);
......@@ -115,7 +126,7 @@ class _PlaceholderAvatar extends StatelessWidget {
return CircleAvatar(
foregroundColor: Colors.white,
backgroundColor: color ?? context.pattleTheme.data.primarySwatch[500],
radius: 24,
radius: radius,
child: _icon,
);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment