1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-25 14:29:22 +00:00
comunicmobile/lib/ui/widgets/tablet_mode/memberships_panel.dart

312 lines
9.3 KiB
Dart
Raw Normal View History

2020-05-05 17:33:04 +00:00
import 'package:comunic/helpers/conversations_helper.dart';
import 'package:comunic/helpers/friends_helper.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
2020-05-05 16:49:50 +00:00
import 'package:comunic/helpers/webapp_helper.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/lists/groups_list.dart';
2020-05-05 16:49:50 +00:00
import 'package:comunic/lists/memberships_list.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/lists/users_list.dart';
import 'package:comunic/models/friend.dart';
2021-04-07 14:28:59 +00:00
import 'package:comunic/models/group.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/models/membership.dart';
2020-05-09 06:17:52 +00:00
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/routes/main_route/page_info.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/ui/widgets/account_image_widget.dart';
2021-03-11 17:11:24 +00:00
import 'package:comunic/ui/widgets/conversation_image_widget.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/ui/widgets/group_icon_widget.dart';
import 'package:comunic/ui/widgets/group_membership_widget.dart';
2020-05-05 16:49:50 +00:00
import 'package:comunic/ui/widgets/safe_state.dart';
2020-05-05 17:33:04 +00:00
import 'package:comunic/utils/date_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
2020-05-05 16:49:50 +00:00
import 'package:flutter/material.dart';
/// Memberships panel
///
/// @author Pierre Hubert
class MembershipsPanel extends StatefulWidget {
final PageInfo currentPage;
const MembershipsPanel({
Key key,
@required this.currentPage,
}) : assert(currentPage != null),
super(key: key);
2020-05-05 16:49:50 +00:00
@override
_MembershipsPanelState createState() => _MembershipsPanelState();
}
2020-05-05 17:33:04 +00:00
const _MembershipIconsWidth = 30.0;
2020-05-05 16:49:50 +00:00
class _MembershipsPanelState extends SafeState<MembershipsPanel> {
2020-05-05 17:33:04 +00:00
final _refreshKey = GlobalKey<RefreshIndicatorState>();
2020-05-05 16:49:50 +00:00
MembershipList _membershipList;
2020-05-05 17:33:04 +00:00
UsersList _usersList;
GroupsList _groupsList;
2020-05-05 16:49:50 +00:00
Future<void> _refresh() async {
try {
final memberships = await WebAppHelper.getMemberships();
2020-05-05 17:33:04 +00:00
final users = await UsersHelper().getListWithThrow(memberships.usersId);
final groups = await GroupsHelper().getListOrThrow(memberships.groupsId);
2020-05-05 16:49:50 +00:00
setState(() {
_membershipList = memberships;
2020-05-05 17:33:04 +00:00
_usersList = users;
_groupsList = groups;
2020-05-05 16:49:50 +00:00
});
} catch (e, s) {
print("Could not load the list of memberships! $e\n$s");
}
}
@override
void initState() {
super.initState();
setInterval(20, (t) => _refresh());
2020-05-05 16:49:50 +00:00
_refresh();
}
@override
Widget build(BuildContext context) {
2020-05-05 17:33:04 +00:00
if (_membershipList == null) return buildCenteredProgressBar();
return Material(
color: Colors.transparent,
child: RefreshIndicator(
key: _refreshKey,
child: _buildMembershipsList(),
onRefresh: _refresh),
);
2020-05-05 17:33:04 +00:00
}
Widget _buildMembershipsList() {
return ListTileTheme(
iconColor: IconTheme.of(context).color,
child: ListView.builder(
itemBuilder: _buildMembershipTile,
itemCount: _membershipList.length,
),
);
}
Widget _buildMembershipTile(BuildContext context, int index) {
final membership = _membershipList[index];
switch (membership.type) {
case MembershipType.FRIEND:
return _buildFriendMembership(membership);
case MembershipType.GROUP:
return _buildGroupMembership(membership);
case MembershipType.CONVERSATION:
return _buildConversationMembership(membership);
}
2020-05-09 08:07:05 +00:00
throw Exception("Unreachable statement!");
2020-05-05 17:33:04 +00:00
}
// TODO : add private messages icon support
Widget _buildFriendMembership(Membership membership) {
final user = _usersList.getUser(membership.friend.id);
final connected = membership.friend.isConnected;
Widget subtitle;
if (!membership.friend.accepted) {
subtitle = RichText(
text: TextSpan(children: [
WidgetSpan(
child: _RespondFriendshipRequestButton(
friend: membership.friend,
accept: true,
text: tr("Accept"),
color: Colors.green,
onTap: _respondFriendshipRequest,
)),
TextSpan(text: " "),
WidgetSpan(
child: _RespondFriendshipRequestButton(
friend: membership.friend,
accept: false,
text: tr("Reject"),
color: Colors.red,
onTap: _respondFriendshipRequest,
)),
]));
} else
subtitle = Text(
connected ? tr("Online") : diffTimeFromNowToStr(membership.lastActive),
style: TextStyle(color: connected ? Colors.green : null),
);
return Container(
color: widget.currentPage.type == PageType.USER_PAGE &&
widget.currentPage.id == user.id
? Colors.grey.shade800
: null,
child: ListTile(
leading: AccountImageWidget(user: user, width: _MembershipIconsWidth),
title: Text(user.displayName),
subtitle: subtitle,
onTap: () => MainController.of(context).openUserPage(user.id),
),
2020-05-05 17:33:04 +00:00
);
}
Widget _buildGroupMembership(Membership membership) {
final group = _groupsList.getGroup(membership.groupID);
2021-04-07 14:28:59 +00:00
return Container(
color: widget.currentPage.type == PageType.GROUP_PAGE &&
widget.currentPage.id == group.id
? Colors.grey.shade800
: null,
child: Column(
children: [_buildMainGroupInformationTile(membership, group)]
..addAll(_membershipList
.getGroupConversations(group.id)
.map((e) => Padding(
padding: const EdgeInsets.only(left: 30.0),
child: _buildConversationMembership(e, true),
))
.toList()),
),
);
}
2021-04-07 14:28:59 +00:00
Widget _buildMainGroupInformationTile(Membership membership, Group group) {
Widget subtitle;
if (!group.isAtLeastMember) {
subtitle = GroupMembershipWidget(
group: group,
onUpdated: () => _refreshKey.currentState.show(),
onError: _onGroupMembershipUpdateError,
);
} else {
subtitle = Text(diffTimeFromNowToStr(membership.lastActive));
2021-04-07 14:28:59 +00:00
} // Main group information
2021-04-07 14:28:59 +00:00
return ListTile(
leading: GroupIcon(
group: group,
width: _MembershipIconsWidth,
2020-05-05 17:33:04 +00:00
),
2021-04-07 14:28:59 +00:00
title: Text(group.displayName),
subtitle: subtitle,
onTap: () => MainController.of(context).openGroup(group.id),
2020-05-05 17:33:04 +00:00
);
}
2021-04-07 14:28:59 +00:00
Widget _buildConversationMembership(Membership membership,
[bool allowGroup = false]) {
2020-05-06 16:05:02 +00:00
final conversation = membership.conversation;
2020-05-11 16:12:49 +00:00
2021-04-07 14:28:59 +00:00
if (conversation.isGroupConversation && !allowGroup) return Container();
2020-05-11 16:12:49 +00:00
Color color;
if (conversation.isHavingCall)
color = Color(0xFF815d1d);
else if (widget.currentPage.type == PageType.CONVERSATION_PAGE &&
widget.currentPage.id == conversation.id)
color = Colors.grey.shade800;
else if (!conversation.sawLastMessage) color = Color(0xFF1c443a);
2020-05-06 15:57:49 +00:00
return Container(
2020-05-11 16:12:49 +00:00
color: color,
2020-05-06 15:57:49 +00:00
child: ListTile(
dense: true,
2021-03-11 17:11:24 +00:00
leading: ConversationImageWidget(
conversation: conversation,
users: _usersList,
noUserImage: conversation.isGroupConversation,
2021-03-11 17:11:24 +00:00
),
title: Row(
children: [
Icon(
Icons.message,
size: 12,
),
SizedBox(width: 5),
2021-03-16 18:12:37 +00:00
Expanded(
child: Text(ConversationsHelper.getConversationName(
conversation, _usersList)),
),
],
),
2020-05-06 16:05:02 +00:00
subtitle: Text(diffTimeFromNowToStr(membership.lastActive) +
(conversation.isHavingCall ? "\n" + tr("Ongoing call") : "")),
2021-04-07 14:35:18 +00:00
onTap: () => MainController.of(context)
.openConversation(conversation, fullScreen: true),
2020-05-09 18:19:16 +00:00
trailing: conversation.isHavingCall
? FloatingActionButton(
2020-05-13 16:38:57 +00:00
heroTag: null,
2020-05-09 18:19:16 +00:00
child: Icon(Icons.call),
onPressed: () =>
MainController.of(context).startCall(conversation.id),
)
: null,
2020-05-06 15:57:49 +00:00
),
2020-05-05 17:33:04 +00:00
);
2020-05-05 16:49:50 +00:00
}
/// Respond to a friendship request
Future<void> _respondFriendshipRequest(Friend f, bool accept) async {
try {
if (!accept &&
!await showConfirmDialog(
2020-05-06 15:53:27 +00:00
context: context,
message:
tr("Do you really want to reject this friendship request?")))
return;
await FriendsHelper().respondRequest(f.id, accept);
setState(() {
if (accept)
f.accepted = true;
else
_membershipList.removeFriend(f.id);
});
_refreshKey.currentState.show();
} catch (e, s) {
print("Could not respond to friendship request! $e\n$s");
showSimpleSnack(context, tr("Could not respond to friendship request!"));
}
}
/// Handles the case of failure in group membership update
void _onGroupMembershipUpdateError() {
showSimpleSnack(context, tr("Could not update group membership!"));
_refreshKey.currentState.show();
}
}
class _RespondFriendshipRequestButton extends StatelessWidget {
final Friend friend;
final bool accept;
final String text;
final Color color;
final void Function(Friend, bool) onTap;
const _RespondFriendshipRequestButton({
Key key,
@required this.friend,
@required this.accept,
@required this.text,
@required this.color,
@required this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => onTap(friend, accept),
child: Text(text, style: TextStyle(color: color)),
);
}
2020-05-05 16:49:50 +00:00
}