mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 06:19:22 +00:00
312 lines
9.3 KiB
Dart
312 lines
9.3 KiB
Dart
import 'package:comunic/helpers/conversations_helper.dart';
|
|
import 'package:comunic/helpers/friends_helper.dart';
|
|
import 'package:comunic/helpers/groups_helper.dart';
|
|
import 'package:comunic/helpers/users_helper.dart';
|
|
import 'package:comunic/helpers/webapp_helper.dart';
|
|
import 'package:comunic/lists/groups_list.dart';
|
|
import 'package:comunic/lists/memberships_list.dart';
|
|
import 'package:comunic/lists/users_list.dart';
|
|
import 'package:comunic/models/friend.dart';
|
|
import 'package:comunic/models/group.dart';
|
|
import 'package:comunic/models/membership.dart';
|
|
import 'package:comunic/ui/routes/main_route/main_route.dart';
|
|
import 'package:comunic/ui/routes/main_route/page_info.dart';
|
|
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
|
import 'package:comunic/ui/widgets/conversation_image_widget.dart';
|
|
import 'package:comunic/ui/widgets/group_icon_widget.dart';
|
|
import 'package:comunic/ui/widgets/group_membership_widget.dart';
|
|
import 'package:comunic/ui/widgets/safe_state.dart';
|
|
import 'package:comunic/utils/date_utils.dart';
|
|
import 'package:comunic/utils/intl_utils.dart';
|
|
import 'package:comunic/utils/ui_utils.dart';
|
|
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);
|
|
|
|
@override
|
|
_MembershipsPanelState createState() => _MembershipsPanelState();
|
|
}
|
|
|
|
const _MembershipIconsWidth = 30.0;
|
|
|
|
class _MembershipsPanelState extends SafeState<MembershipsPanel> {
|
|
final _refreshKey = GlobalKey<RefreshIndicatorState>();
|
|
MembershipList _membershipList;
|
|
UsersList _usersList;
|
|
GroupsList _groupsList;
|
|
|
|
Future<void> _refresh() async {
|
|
try {
|
|
final memberships = await WebAppHelper.getMemberships();
|
|
final users = await UsersHelper().getListWithThrow(memberships.usersId);
|
|
final groups = await GroupsHelper().getListOrThrow(memberships.groupsId);
|
|
|
|
setState(() {
|
|
_membershipList = memberships;
|
|
_usersList = users;
|
|
_groupsList = groups;
|
|
});
|
|
} catch (e, s) {
|
|
print("Could not load the list of memberships! $e\n$s");
|
|
}
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
setInterval(20, (t) => _refresh());
|
|
_refresh();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_membershipList == null) return buildCenteredProgressBar();
|
|
|
|
return Material(
|
|
color: Colors.transparent,
|
|
child: RefreshIndicator(
|
|
key: _refreshKey,
|
|
child: _buildMembershipsList(),
|
|
onRefresh: _refresh),
|
|
);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
throw Exception("Unreachable statement!");
|
|
}
|
|
|
|
// 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),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGroupMembership(Membership membership) {
|
|
final group = _groupsList.getGroup(membership.groupID);
|
|
|
|
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()),
|
|
),
|
|
);
|
|
}
|
|
|
|
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));
|
|
} // Main group information
|
|
|
|
return ListTile(
|
|
leading: GroupIcon(
|
|
group: group,
|
|
width: _MembershipIconsWidth,
|
|
),
|
|
title: Text(group.displayName),
|
|
subtitle: subtitle,
|
|
onTap: () => MainController.of(context).openGroup(group.id),
|
|
);
|
|
}
|
|
|
|
Widget _buildConversationMembership(Membership membership,
|
|
[bool allowGroup = false]) {
|
|
final conversation = membership.conversation;
|
|
|
|
if (conversation.isGroupConversation && !allowGroup) return Container();
|
|
|
|
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);
|
|
|
|
return Container(
|
|
color: color,
|
|
child: ListTile(
|
|
dense: true,
|
|
leading: ConversationImageWidget(
|
|
conversation: conversation,
|
|
users: _usersList,
|
|
noUserImage: conversation.isGroupConversation,
|
|
),
|
|
title: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.message,
|
|
size: 12,
|
|
),
|
|
SizedBox(width: 5),
|
|
Expanded(
|
|
child: Text(ConversationsHelper.getConversationName(
|
|
conversation, _usersList)),
|
|
),
|
|
],
|
|
),
|
|
subtitle: Text(diffTimeFromNowToStr(membership.lastActive) +
|
|
(conversation.isHavingCall ? "\n" + tr("Ongoing call") : "")),
|
|
onTap: () => MainController.of(context)
|
|
.openConversation(conversation, fullScreen: true),
|
|
trailing: conversation.isHavingCall
|
|
? FloatingActionButton(
|
|
heroTag: null,
|
|
child: Icon(Icons.call),
|
|
onPressed: () =>
|
|
MainController.of(context).startCall(conversation.id),
|
|
)
|
|
: null,
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Respond to a friendship request
|
|
Future<void> _respondFriendshipRequest(Friend f, bool accept) async {
|
|
try {
|
|
if (!accept &&
|
|
!await showConfirmDialog(
|
|
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)),
|
|
);
|
|
}
|
|
}
|