1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-26 06:49:22 +00:00

Start to display user groups

This commit is contained in:
Pierre HUBERT 2020-04-15 12:04:19 +02:00
parent 8300fc8ca9
commit 4bedbc4b25
9 changed files with 173 additions and 1 deletions

View File

@ -1,6 +1,7 @@
import 'package:comunic/lists/groups_list.dart'; import 'package:comunic/lists/groups_list.dart';
import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/api_request.dart';
import 'package:comunic/models/group.dart'; import 'package:comunic/models/group.dart';
import 'package:comunic/utils/api_utils.dart';
/// Groups helper /// Groups helper
/// ///
@ -91,11 +92,20 @@ class GroupsHelper {
return list; return list;
} }
/// Get the list of groups of a user
Future<Set<int>> getListUser() async =>
(await APIRequest(uri: "groups/get_my_list", needLogin: true).exec())
.assertOk()
.getArray()
.map((f) => cast<int>(f))
.toSet();
/// Turn an API entry into a group object /// Turn an API entry into a group object
Group _getGroupFromAPI(Map<String, dynamic> map) { Group _getGroupFromAPI(Map<String, dynamic> map) {
return Group( return Group(
id: map["id"], id: map["id"],
name: map["name"], name: map["name"],
iconURL: map["icon_url"],
numberMembers: map["number_members"], numberMembers: map["number_members"],
membershipLevel: _APIGroupsMembershipLevelsMap[map["membership"]], membershipLevel: _APIGroupsMembershipLevelsMap[map["membership"]],
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]], visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],

View File

@ -16,4 +16,13 @@ class APIResponse {
/// Check if the request is successful or not /// Check if the request is successful or not
bool get isOK => code == 200; bool get isOK => code == 200;
/// Make sure the request succeed, or throw an exception else
APIResponse assertOk() {
if(!this.isOK)
throw Exception("Request failed with status $code");
return this;
}
} }

View File

@ -22,6 +22,7 @@ enum GroupPostCreationLevel { MODERATORS, MEMBERS }
class Group { class Group {
final int id; final int id;
final String name; final String name;
final String iconURL;
final int numberMembers; final int numberMembers;
final GroupMembershipLevel membershipLevel; final GroupMembershipLevel membershipLevel;
final GroupVisibilityLevel visibilityLevel; final GroupVisibilityLevel visibilityLevel;
@ -33,6 +34,7 @@ class Group {
Group({ Group({
@required this.id, @required this.id,
@required this.name, @required this.name,
@required this.iconURL,
@required this.numberMembers, @required this.numberMembers,
@required this.membershipLevel, @required this.membershipLevel,
@required this.visibilityLevel, @required this.visibilityLevel,
@ -42,6 +44,7 @@ class Group {
@required this.following, @required this.following,
}) : assert(id != null), }) : assert(id != null),
assert(name != null), assert(name != null),
assert(iconURL != null),
assert(numberMembers != null), assert(numberMembers != null),
assert(membershipLevel != null), assert(membershipLevel != null),
assert(visibilityLevel != null), assert(visibilityLevel != null),

View File

@ -2,6 +2,7 @@ import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/ui/routes/app_settings_route.dart'; import 'package:comunic/ui/routes/app_settings_route.dart';
import 'package:comunic/ui/screens/conversations_list_screen.dart'; import 'package:comunic/ui/screens/conversations_list_screen.dart';
import 'package:comunic/ui/screens/friends_list_screen.dart'; import 'package:comunic/ui/screens/friends_list_screen.dart';
import 'package:comunic/ui/screens/groups_list_screen.dart';
import 'package:comunic/ui/screens/newest_posts.dart'; import 'package:comunic/ui/screens/newest_posts.dart';
import 'package:comunic/ui/screens/notifications_screen.dart'; import 'package:comunic/ui/screens/notifications_screen.dart';
import 'package:comunic/ui/widgets/navbar_widget.dart'; import 'package:comunic/ui/widgets/navbar_widget.dart';
@ -89,6 +90,9 @@ class _HomeRouteState extends State<HomeRoute> {
case BarCallbackActions.OPEN_FRIENDS: case BarCallbackActions.OPEN_FRIENDS:
return FriendsListScreen(); return FriendsListScreen();
case BarCallbackActions.OPEN_GROUPS:
return GroupsListScreen();
default: default:
throw "Invalid tab : " + _currTab.toString(); throw "Invalid tab : " + _currTab.toString();
} }

View File

@ -0,0 +1,84 @@
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/lists/groups_list.dart';
import 'package:comunic/ui/widgets/group_icon_widget.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
/// Groups list screen
///
/// @author Pierre Hubert
class GroupsListScreen extends StatefulWidget {
@override
_GroupsListScreenState createState() => _GroupsListScreenState();
}
class _GroupsListScreenState extends SafeState<GroupsListScreen> {
/// The list of groups
GroupsList _groups;
bool _error = false;
@override
void initState() {
super.initState();
this._refreshList();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
// Error
buildErrorCard(
tr("Could not load the list of groups!"),
hide: !_error,
actions: [
MaterialButton(
child: Text(tr("Try again".toUpperCase())),
onPressed: () => _refreshList(),
),
],
),
// List of groups
Expanded(
child: RefreshIndicator(
onRefresh: () => this._refreshList(),
child: _groups == null
? Container()
: ListView(
children: _groups.values
.map((g) => ListTile(
leading: GroupIcon(group: g),
title: Text(g.displayName),
))
.toList(),
),
))
],
);
}
/// Refresh the list of groups
Future<void> _refreshList() async {
try {
final list = await GroupsHelper().getListUser();
final groups = await GroupsHelper().getListOrThrow(list, force: true);
setState(() {
_groups = groups;
_error = false;
});
} catch (e) {
print(e);
setState(() {
_error = true;
});
}
}
}

View File

@ -0,0 +1,50 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:comunic/models/group.dart';
import 'package:flutter/material.dart';
/// Custom group icon
///
/// @author Pierre Hubert
class GroupIcon extends StatelessWidget {
final Group group;
final double width;
const GroupIcon({
Key key,
@required this.group,
this.width = 50,
}) : assert(group != null),
assert(width != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Material(
child: CachedNetworkImage(
imageUrl: group.iconURL,
width: width,
height: width,
placeholder: (c, s) => Container(
color: Colors.grey,
width: width,
height: width,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CircularProgressIndicator(
strokeWidth: 4.0,
),
),
),
errorWidget: (c, s, o) => Container(
color: Colors.red,
width: width,
height: width,
child: Icon(
Icons.error,
color: Colors.white,
),
),
),
);
}
}

View File

@ -15,6 +15,7 @@ enum BarCallbackActions {
OPEN_NEWEST_POSTS, OPEN_NEWEST_POSTS,
OPEN_FRIENDS, OPEN_FRIENDS,
OPEN_MY_PAGE, OPEN_MY_PAGE,
OPEN_GROUPS,
OPEN_APP_SETTINGS, OPEN_APP_SETTINGS,
NONE, NONE,
ACTION_LOGOUT ACTION_LOGOUT
@ -81,6 +82,7 @@ final _menuItems = <_MenuItem>[
final _menuActionsItem = <_ActionMenuItem>[ final _menuActionsItem = <_ActionMenuItem>[
_ActionMenuItem( _ActionMenuItem(
label: tr("My Page"), action: BarCallbackActions.OPEN_MY_PAGE), label: tr("My Page"), action: BarCallbackActions.OPEN_MY_PAGE),
_ActionMenuItem(label: tr("Groups"), action: BarCallbackActions.OPEN_GROUPS),
_ActionMenuItem( _ActionMenuItem(
label: tr("App settings"), action: BarCallbackActions.OPEN_APP_SETTINGS), label: tr("App settings"), action: BarCallbackActions.OPEN_APP_SETTINGS),
_ActionMenuItem( _ActionMenuItem(

6
lib/utils/api_utils.dart Normal file
View File

@ -0,0 +1,6 @@
/// API utilities
///
/// @author Pierre Hubert
/// Casting helper
T cast<T>(dynamic val) => val is T ? val : null;

View File

@ -31,7 +31,11 @@ Widget buildLoadingPage({
} }
/// Build and return an error card /// Build and return an error card
Widget buildErrorCard(String message, {List<Widget> actions}) { Widget buildErrorCard(String message, {List<Widget> actions, bool hide = false}) {
if(hide)
return Container();
return Card( return Card(
elevation: 2.0, elevation: 2.0,
color: Colors.red, color: Colors.red,