...
 
Commits (3)
......@@ -32,7 +32,7 @@ import 'resources/theme.dart';
import 'section/main/chat/page.dart';
import 'section/main/chat/image/page.dart';
import 'section/main/chat/settings/page.dart';
import 'section/main/chats/models/chat.dart';
import 'section/main/models/chat.dart';
import 'section/main/chats/page.dart';
import 'section/main/chats/create/group/details_page.dart';
import 'section/main/chats/create/group/members_page.dart';
......@@ -85,9 +85,9 @@ final Map<String, MaterialPageRoute Function(Object)> routes = {
settings: RouteSettings(name: Routes.chatsNewDetails),
builder: (context) => CreateGroupDetailsPage.withGivenBloc(arguments),
),
Routes.image: (arguments) => MaterialPageRoute(
Routes.image: (dynamic arguments) => MaterialPageRoute(
settings: RouteSettings(name: Routes.image),
builder: (context) => ImagePage.withBloc(arguments)),
builder: (context) => ImagePage.withBloc(arguments[0], arguments[1])),
Routes.login: (params) => MaterialPageRoute(
settings: RouteSettings(name: Routes.login),
builder: (context) => StartPage(),
......
......@@ -25,7 +25,7 @@ import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import '../section/main/chats/models/chat.dart';
import '../section/main/models/chat.dart';
import '../section/main/models/chat_member.dart';
import '../auth/bloc.dart';
......@@ -193,8 +193,8 @@ class NotificationsBloc extends Bloc<NotificationsEvent, NotificationsState> {
style: AndroidNotificationStyle.Messaging,
styleInformation: MessagingStyleInformation(
senderPerson,
conversationTitle: !room.isDirect ? await chat.name : null,
groupConversation: room.isDirect,
conversationTitle: !chat.isDirect ? await chat.name : null,
groupConversation: chat.isDirect,
messages: [message],
),
),
......
{
"@@last_modified": "2020-03-23T21:58:49.230276",
"@@last_modified": "2020-03-25T20:06:47.053234",
"appName": "Pattle",
"@appName": {
"type": "text",
......@@ -238,13 +238,13 @@
"count": {}
}
},
"_Chats_personal": "Personal",
"@_Chats_personal": {
"_Chats_chats": "Chats",
"@_Chats_chats": {
"type": "text",
"placeholders": {}
},
"_Chats_public": "Public",
"@_Chats_public": {
"_Chats_channels": "Channels",
"@_Chats_channels": {
"type": "text",
"placeholders": {}
},
......
......@@ -639,18 +639,26 @@ class _Chats extends _Category {
: newGroup = _ChatsNewGroup(localeName),
super(localeName);
String get personal {
String get chats {
return Intl.message(
'Personal',
name: '_Chats_personal',
'Chats',
name: '_Chats_chats',
locale: _localeName,
);
}
String get public {
String get channels {
return Intl.message(
'Public',
name: '_Chats_public',
'Channels',
name: '_Chats_channels',
locale: _localeName,
);
}
String get newChannel {
return Intl.message(
'New channel',
name: '_Chats_newChannel',
locale: _localeName,
);
}
......
......@@ -105,8 +105,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Group name"),
"_ChatsNewGroup_title":
MessageLookupByLibrary.simpleMessage("New group"),
"_Chats_personal": MessageLookupByLibrary.simpleMessage("Personal"),
"_Chats_public": MessageLookupByLibrary.simpleMessage("Public"),
"_Chats_channels": MessageLookupByLibrary.simpleMessage("Channels"),
"_Chats_chats": MessageLookupByLibrary.simpleMessage("Chats"),
"_Common_confirm": MessageLookupByLibrary.simpleMessage("Confirm"),
"_Common_name": MessageLookupByLibrary.simpleMessage("Name"),
"_Common_next": MessageLookupByLibrary.simpleMessage("Next"),
......
......@@ -19,9 +19,11 @@ 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:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import '../../models/chat.dart';
import '../../models/chat_member.dart';
import '../../models/chat_message.dart';
......@@ -36,11 +38,11 @@ class ImagePage extends StatefulWidget {
ImagePage._(this.message);
static Widget withBloc(ChatMessage message) {
static Widget withBloc(Chat chat, ChatMessage message) {
assert(message.event is ImageMessageEvent);
return BlocProvider<ImageBloc>(
create: (c) => ImageBloc(Matrix.of(c), message.room),
create: (c) => ImageBloc(Matrix.of(c), chat.room),
child: ImagePage._(message),
);
}
......
......@@ -26,7 +26,7 @@ import '../../../app.dart';
import '../../../resources/intl/localizations.dart';
import '../../../resources/theme.dart';
import '../chats/models/chat.dart';
import '../models/chat.dart';
import '../chats/widgets/typing_content.dart';
import '../widgets/chat_name.dart';
import '../widgets/error.dart';
......@@ -136,7 +136,7 @@ class _ChatPageState extends State<ChatPage> {
child: Column(
children: <Widget>[
Expanded(
child: _MessageList(room: _room),
child: _MessageList(chat: widget.chat),
),
ConstrainedBox(
constraints: BoxConstraints.loose(
......@@ -156,9 +156,9 @@ class _ChatPageState extends State<ChatPage> {
}
class _MessageList extends StatefulWidget {
final Room room;
final Chat chat;
const _MessageList({Key key, @required this.room}) : super(key: key);
const _MessageList({Key key, @required this.chat}) : super(key: key);
@override
State<StatefulWidget> createState() => _MessageListState();
......@@ -228,6 +228,7 @@ class _MessageListState extends State<_MessageList> {
bubble = StateBubble.withContent(message: message);
} else {
bubble = MessageBubble.withContent(
chat: widget.chat,
message: message,
previousMessage: previousMessage,
nextMessage: nextMessage,
......@@ -254,7 +255,7 @@ class _MessageListState extends State<_MessageList> {
reverse: true,
children: List.generate(10, (i) {
return MessageBubble.loading(
room: widget.room,
chat: widget.chat,
isMine: i % 2 == 0,
);
}),
......
......@@ -27,7 +27,7 @@ import '../../../../resources/theme.dart';
import '../../widgets/chat_name.dart';
import '../../widgets/chat_member_tile.dart';
import '../../chats/models/chat.dart';
import '../../models/chat.dart';
import '../../models/chat_member.dart';
import '../../../../matrix.dart';
......
......@@ -32,10 +32,11 @@ class ImageContent extends StatelessWidget {
static const double _maxHeight = 292;
void _onTap(BuildContext context) {
final bubble = MessageBubble.of(context);
Navigator.pushNamed(
context,
Routes.image,
arguments: MessageBubble.of(context).message,
arguments: [bubble.chat, bubble.message],
);
}
......
......@@ -36,7 +36,7 @@ class TextContent extends StatelessWidget {
final bubble = MessageBubble.of(context);
final needsBorder =
!bubble.message.room.isDirect && bubble.reply?.isMine == false ||
!bubble.chat.isDirect && bubble.reply?.isMine == false ||
bubble.message.isMine && bubble.reply?.isMine == true;
return Clickable(
......@@ -67,6 +67,7 @@ class TextContent extends StatelessWidget {
if (bubble.message.inReplyTo != null) ...[
SizedBox(height: 4),
MessageBubble.withContent(
chat: bubble.chat,
message: bubble.message.inReplyTo,
reply: bubble.message,
),
......
......@@ -17,10 +17,13 @@
import 'package:flutter/material.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:provider/provider.dart';
import '../../../../models/chat.dart';
import '../../../../models/chat_member.dart';
import '../../../../models/chat_message.dart';
import '../../../../../../resources/theme.dart';
import '../../../../widgets/message_state.dart';
......@@ -35,6 +38,8 @@ import '../../../../../../util/date_format.dart';
import '../../../../../../util/chat_member.dart';
class MessageBubble extends StatelessWidget {
final Chat chat;
final ChatMessage message;
final ChatMessage previousMessage;
final ChatMessage nextMessage;
......@@ -62,6 +67,7 @@ class MessageBubble extends StatelessWidget {
static const _paddingBetweenSameGroup = 2.0;
MessageBubble._({
@required this.chat,
@required this.message,
this.previousMessage,
this.nextMessage,
......@@ -74,6 +80,7 @@ class MessageBubble extends StatelessWidget {
});
factory MessageBubble({
@required Chat chat,
@required ChatMessage message,
ChatMessage previousMessage,
ChatMessage nextMessage,
......@@ -85,6 +92,7 @@ class MessageBubble extends StatelessWidget {
final isEndOfGroup = _isEndofGroup(message, nextMessage, reply);
return MessageBubble._(
chat: chat,
message: message,
previousMessage: previousMessage,
nextMessage: nextMessage,
......@@ -99,6 +107,7 @@ class MessageBubble extends StatelessWidget {
/// Create a [MessageBubble] with the correct [child] for the given [message].
factory MessageBubble.withContent({
@required Chat chat,
@required ChatMessage message,
ChatMessage previousMessage,
ChatMessage nextMessage,
......@@ -117,6 +126,7 @@ class MessageBubble extends StatelessWidget {
}
return MessageBubble(
chat: chat,
message: message,
previousMessage: previousMessage,
nextMessage: nextMessage,
......@@ -125,11 +135,11 @@ class MessageBubble extends StatelessWidget {
);
}
factory MessageBubble.loading({@required Room room, bool isMine = false}) {
factory MessageBubble.loading({@required Chat chat, bool isMine = false}) {
return MessageBubble(
chat: chat,
color: Colors.grey[300],
message: ChatMessage(
room,
TextMessageEvent(
RoomEventArgs(
id: EventId('1234'),
......@@ -424,7 +434,7 @@ class Sender extends StatelessWidget {
final bubble = MessageBubble.of(context);
return !bubble.message.isMine &&
!bubble.message.room.isDirect &&
!bubble.chat.isDirect &&
(bubble.isStartOfGroup || bubble.reply != null);
}
......
......@@ -18,7 +18,7 @@
import 'package:bloc/bloc.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'models/chat.dart';
import '../models/chat.dart';
import '../models/chat_member.dart';
import '../models/chat_message.dart';
......@@ -88,7 +88,6 @@ class ChatsBloc extends Bloc<ChatsEvent, ChatsState> {
: null,
latestMessageForSorting: latestEventForSorting != null
? ChatMessage(
room,
latestEventForSorting,
sender: await ChatMember.fromUser(
room,
......@@ -144,21 +143,8 @@ class ChatsBloc extends Bloc<ChatsEvent, ChatsState> {
Future<ChatsState> _loadChats() async {
final chats = await _getChats();
final personalChats = chats
.where(
(chat) =>
chat.room.joinRule == JoinRule.invite ||
chat.room.joinRule == JoinRule.private,
)
.toList();
final publicChats = chats
.where(
(chat) =>
chat.room.joinRule == JoinRule.public ||
chat.room.joinRule == JoinRule.knock,
)
.toList();
final personalChats = chats.where((chat) => !chat.isChannel).toList();
final publicChats = chats.where((chat) => chat.isChannel).toList();
return ChatsLoaded(personal: personalChats, public: publicChats);
}
......
......@@ -17,7 +17,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:mdi/mdi.dart';
import '../../../app.dart';
import '../../../resources/intl/localizations.dart';
......@@ -41,10 +40,6 @@ class ChatsPage extends StatefulWidget {
}
class _ChatsPageState extends State<ChatsPage> {
void _goToCreateGroup() {
Navigator.of(context).pushNamed(Routes.chatsNew);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
......@@ -59,12 +54,6 @@ class _ChatsPageState extends State<ChatsPage> {
child: Scaffold(
appBar: AppBar(
title: Text(context.intl.appName),
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings),
onPressed: () => Navigator.pushNamed(context, Routes.settings),
)
],
bottom: TabBar(
tabs: <Widget>[
Tab(
......@@ -73,7 +62,7 @@ class _ChatsPageState extends State<ChatsPage> {
children: <Widget>[
Icon(Icons.group),
SizedBox(width: 8),
Text(context.intl.chats.personal.toUpperCase()),
Text(context.intl.chats.chats.toUpperCase()),
],
),
),
......@@ -82,15 +71,16 @@ class _ChatsPageState extends State<ChatsPage> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Mdi.bullhorn),
Icon(Icons.public),
SizedBox(width: 8),
Text(context.intl.chats.public.toUpperCase()),
Text(context.intl.chats.channels.toUpperCase()),
],
),
),
],
),
),
drawer: _Drawer(),
body: TabBarView(
children: <Widget>[
_ChatsTab(personal: true),
......@@ -98,7 +88,7 @@ class _ChatsPageState extends State<ChatsPage> {
],
),
floatingActionButton: FloatingActionButton(
onPressed: _goToCreateGroup,
onPressed: () => Navigator.of(context).pushNamed(Routes.chatsNew),
child: Icon(Icons.chat),
),
),
......@@ -124,3 +114,47 @@ class _ChatsTab extends StatelessWidget {
});
}
}
class _Drawer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
),
child: Container(),
),
ListTile(
leading: Icon(
Icons.group,
color: Theme.of(context).primaryColor,
),
title: Text(context.intl.chats.newGroup.title),
onTap: () => Navigator.of(context).pushNamed(Routes.chatsNew),
),
ListTile(
leading: Icon(
Icons.public,
color: Theme.of(context).primaryColor,
),
title: Text(context.intl.chats.newChannel),
onTap: () {},
),
Divider(),
ListTile(
leading: Icon(
Icons.settings,
color: Theme.of(context).primaryColor,
),
title: Text(context.intl.settings.title),
onTap: () => Navigator.pushNamed(context, Routes.settings),
),
],
),
);
}
}
import 'package:meta/meta.dart';
import 'package:equatable/equatable.dart';
import 'models/chat.dart';
import '../models/chat.dart';
abstract class ChatsState extends Equatable {
@override
......
......@@ -17,11 +17,10 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:mdi/mdi.dart';
import 'package:transparent_image/transparent_image.dart';
import '../../../../resources/theme.dart';
import '../models/chat.dart';
import '../../models/chat.dart';
import '../../../../util/chat_member.dart';
import '../../../../util/url.dart';
......@@ -55,16 +54,16 @@ class ChatAvatar extends StatelessWidget {
? chat.directMember.color(context)
: LightColors.red[500],
radius: 24,
child: _icon(),
child: _icon,
);
}
}
Icon _icon() {
if (chat.room.isDirect) {
Icon get _icon {
if (chat.isDirect) {
return Icon(Icons.person);
} else if (chat.room.aliases != null && chat.room.aliases.isNotEmpty) {
return Icon(Mdi.bullhorn);
} else if (chat.isChannel) {
return Icon(Icons.public);
} else {
return Icon(Icons.group);
}
......
......@@ -18,7 +18,7 @@
import 'package:flutter/material.dart';
import '../../../../app.dart';
import '../models/chat.dart';
import '../../models/chat.dart';
import '../../widgets/chat_name.dart';
import '../../../../util/date_format.dart';
......
......@@ -20,7 +20,7 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:provider/provider.dart';
import '../../../../../resources/theme.dart';
import '../../models/chat.dart';
import '../../../models/chat.dart';
import '../../../../../matrix.dart';
......@@ -117,10 +117,10 @@ class Sender extends StatelessWidget {
const Sender({Key key}) : super(key: key);
static bool necessary(BuildContext context) {
final message = Subtitle.of(context).chat.latestMessage;
final chat = Subtitle.of(context).chat;
final message = chat.latestMessage;
return message.event.sender != Matrix.of(context).user &&
!message.room.isDirect;
return message.event.sender != Matrix.of(context).user && !chat.isDirect;
}
@override
......
......@@ -20,7 +20,7 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import '../../../../resources/intl/localizations.dart';
import '../../../../resources/theme.dart';
import '../models/chat.dart';
import '../../models/chat.dart';
class TypingContent extends StatelessWidget {
final Chat chat;
......
......@@ -18,8 +18,8 @@
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:meta/meta.dart';
import '../../models/chat_member.dart';
import '../../models/chat_message.dart';
import 'chat_member.dart';
import 'chat_message.dart';
/// Chat overview used in the 'chats' page.
class Chat {
......@@ -38,6 +38,10 @@ class Chat {
final ChatMember directMember;
bool get isDirect => room.isDirect;
bool get isChannel =>
room.joinRule == JoinRule.public || room.joinRule == JoinRule.knock;
Chat({
@required this.room,
this.latestMessage,
......
......@@ -22,7 +22,6 @@ import 'chat_member.dart';
@immutable
class ChatMessage {
final Room room;
final RoomEvent event;
final ChatMember sender;
......@@ -36,7 +35,6 @@ class ChatMessage {
final ChatMember subject;
ChatMessage(
this.room,
this.event, {
@required this.sender,
this.inReplyTo,
......@@ -46,8 +44,7 @@ class ChatMessage {
@override
bool operator ==(dynamic other) {
if (other is ChatMessage) {
return room == other.room &&
event == other.event &&
return event == other.event &&
inReplyTo == other.inReplyTo &&
isMine == other.isMine;
} else {
......@@ -66,7 +63,6 @@ class ChatMessage {
if (event is RedactedEvent) {
redactionMessage = ChatMessage(
room,
event.redaction,
sender: await ChatMember.fromUser(
room,
......@@ -83,7 +79,6 @@ class ChatMessage {
}
return ChatMessage(
room,
event,
sender: await ChatMember.fromUser(
room,
......@@ -98,5 +93,5 @@ class ChatMessage {
@override
int get hashCode =>
room.hashCode + event.hashCode + inReplyTo.hashCode + isMine.hashCode;
hashCode + event.hashCode + inReplyTo.hashCode + isMine.hashCode;
}
......@@ -19,7 +19,7 @@ import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
import '../../../resources/intl/localizations.dart';
import '../chats/models/chat.dart';
import '../models/chat.dart';
class ChatName extends StatelessWidget {
final Chat chat;
......