1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2025-06-19 08:15:16 +00:00

Start to build groups page

This commit is contained in:
2020-04-15 18:06:20 +02:00
parent c7d8843f06
commit b10163575f
9 changed files with 347 additions and 12 deletions

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/screens/conversations_list_screen.dart';
import 'package:comunic/ui/screens/friends_list_screen.dart';
import 'package:comunic/ui/screens/group_screen.dart';
import 'package:comunic/ui/screens/groups_list_screen.dart';
import 'package:comunic/ui/screens/newest_posts.dart';
import 'package:comunic/ui/screens/notifications_screen.dart';
@ -21,6 +22,10 @@ import 'login_route.dart';
class HomeRoute extends StatefulWidget {
@override
State<StatefulWidget> createState() => _HomeRouteState();
/// Get current instance of Home controller
static HomeController of(BuildContext context) =>
context.findAncestorStateOfType<HomeController>();
}
class CurrPage {
@ -28,9 +33,24 @@ class CurrPage {
final Map<String, dynamic> args;
const CurrPage(this.action, {this.args}) : assert(action != null);
@override
String toString() =>
"CurrPage {\n\taction: " +
this.action.toString() +
"\n\targs: " +
this.args.toString() +
"\n}";
}
class _HomeRouteState extends State<HomeRoute> {
/// Public interface of home controller
abstract class HomeController extends State<HomeRoute> {
/// Open a specific group page specified by its [groupID]
void openGroup(int groupID);
}
/// Private implementation of HomeController
class _HomeRouteState extends HomeController {
CurrPage get _currTab => history.last;
List<CurrPage> history = List();
@ -106,6 +126,9 @@ class _HomeRouteState extends State<HomeRoute> {
case BarCallbackActions.OPEN_GROUPS:
return GroupsListScreen();
case BarCallbackActions.OPEN_GROUP_PAGE:
return GroupPageScreen(groupID: _currTab.args["groupID"]);
default:
throw "Invalid tab : " + _currTab.toString();
}
@ -156,4 +179,10 @@ class _HomeRouteState extends State<HomeRoute> {
return LoginRoute();
}));
}
@override
void openGroup(int groupID) {
_pushPage(CurrPage(BarCallbackActions.OPEN_GROUP_PAGE,
args: {"groupID": groupID}));
}
}

View File

@ -0,0 +1,106 @@
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/models/group.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/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
/// Group access denied screen
///
/// @author Pierre Hubert
class GroupAccessDeniedScreen extends StatefulWidget {
final int groupID;
final Function() onMembershipAcquired;
const GroupAccessDeniedScreen({
Key key,
@required this.groupID,
@required this.onMembershipAcquired,
}) : assert(groupID != null),
assert(onMembershipAcquired != null),
super(key: key);
@override
_GroupAccessDeniedScreenState createState() =>
_GroupAccessDeniedScreenState();
}
class _GroupAccessDeniedScreenState extends SafeState<GroupAccessDeniedScreen> {
Group _group;
bool error = false;
@override
void initState() {
_refresh();
super.initState();
}
@override
Widget build(BuildContext context) {
if (error)
return buildErrorCard(tr("Could not get basic group information!"),
actions: [
MaterialButton(
child: Text(tr("Try again").toUpperCase()),
onPressed: () => this._refresh(),
)
]);
if (_group == null) return buildCenteredProgressBar();
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Spacer(
flex: 5,
),
GroupIcon(group: _group),
Spacer(),
Text(
_group.displayName,
style: TextStyle(fontSize: 20),
),
Spacer(),
Text(tr("A registration is required to access this group page.")),
Spacer(),
GroupMembershipWidget(
group: _group,
onUpdated: () => this._refresh(),
onError: () => this._refresh(),
),
Spacer(
flex: 5,
)
],
),
),
);
}
/// Get basic information about the groups
Future<void> _refresh() async {
try {
setState(() {
error = false;
_group = null;
});
// Get information about a single group
final group = await GroupsHelper().getSingle(widget.groupID, force: true);
if (group.getIsAtLeastMember) widget.onMembershipAcquired();
setState(() => _group = group);
} catch (e) {
print(e);
setState(() => error = true);
}
}
}

View File

@ -0,0 +1,80 @@
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/ui/screens/group_access_denied_screen.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';
/// Group screen
///
/// @author Pierre Hubert
class GroupPageScreen extends StatefulWidget {
final int groupID;
const GroupPageScreen({Key key, @required this.groupID})
: assert(groupID != null),
super(key: key);
@override
_GroupPageScreenState createState() => _GroupPageScreenState();
}
class _GroupPageScreenState extends SafeState<GroupPageScreen> {
int get groupID => widget.groupID;
GetAdvancedInfoResult _getGroupResult;
var error = false;
@override
void initState() {
_refreshPage();
super.initState();
}
@override
Widget build(BuildContext context) {
if (error)
return buildErrorCard(tr("Could not load information about the group!"),
actions: [
MaterialButton(
onPressed: () => _refreshPage(),
child: Text(tr("Try again").toUpperCase()),
)
]);
// If we are still loading the page
if (_getGroupResult == null) return buildCenteredProgressBar();
// Check if access to the group was denied
if (_getGroupResult.status == GetAdvancedInfoStatus.ACCESS_DENIED)
return GroupAccessDeniedScreen(
groupID: groupID,
onMembershipAcquired: () => _refreshPage(),
);
// Create another screen for the group page
}
/// Refresh the page
Future<void> _refreshPage() async {
try {
setState(() {
error = false;
_getGroupResult = null;
});
// Get information about the group
final result = await GroupsHelper().getAdvancedInfo(groupID);
setState(() {
_getGroupResult = result;
});
} catch (e) {
print(e);
setState(() {
error = true;
});
}
}
}

View File

@ -1,6 +1,7 @@
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/lists/groups_list.dart';
import 'package:comunic/models/group.dart';
import 'package:comunic/ui/routes/home_route.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';
@ -40,7 +41,7 @@ class _GroupsListScreenState extends SafeState<GroupsListScreen> {
hide: !_error,
actions: [
MaterialButton(
child: Text(tr("Try again".toUpperCase())),
child: Text(tr("Try again").toUpperCase()),
onPressed: () => _refreshList(),
),
],
@ -66,6 +67,7 @@ class _GroupsListScreenState extends SafeState<GroupsListScreen> {
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteGroup(g)),
onTap: () => HomeRoute.of(context).openGroup(g.id),
))
.toList(),
),

View File

@ -13,11 +13,11 @@ import 'package:flutter/material.dart';
class GroupMembershipWidget extends StatefulWidget {
final Group group;
final Function() onUpdated;
final Function() onError;
const GroupMembershipWidget({
@required this.group,
this.onUpdated,
}) : assert(group != null);
const GroupMembershipWidget(
{@required this.group, this.onUpdated, this.onError})
: assert(group != null);
@override
_GroupMembershipWidgetState createState() => _GroupMembershipWidgetState();
@ -50,6 +50,9 @@ class _GroupMembershipWidgetState extends SafeState<GroupMembershipWidget> {
case GroupMembershipLevel.VISITOR:
return _buildVisitorState();
default:
throw Exception("Unkonwn grou pmembership level state: $_level");
}
}
@ -84,9 +87,10 @@ class _GroupMembershipWidgetState extends SafeState<GroupMembershipWidget> {
message: tr("Do you really want to reject this invitation?")))
return;
if (!await GroupsHelper().respondInvitation(_id, accept))
if (!await GroupsHelper().respondInvitation(_id, accept)) {
showSimpleSnack(context, tr("Could not respond to your invitation!"));
else {
if (this.widget.onError != null) this.widget.onError();
} else {
// Refresh state
group.membershipLevel =
accept ? GroupMembershipLevel.MEMBER : GroupMembershipLevel.VISITOR;
@ -114,9 +118,10 @@ class _GroupMembershipWidgetState extends SafeState<GroupMembershipWidget> {
/// Cancel group membership request
void _cancelRequest() async {
if (!await GroupsHelper().cancelRequest(_id))
if (!await GroupsHelper().cancelRequest(_id)) {
showSimpleSnack(context, tr("Could not cancel your membership request!"));
else {
if (this.widget.onError != null) this.widget.onError();
} else {
// Refresh state
group.membershipLevel = GroupMembershipLevel.VISITOR;
this.setState(() {});
@ -138,9 +143,10 @@ class _GroupMembershipWidgetState extends SafeState<GroupMembershipWidget> {
/// Create new membership request
void _requestMembership() async {
if (!await GroupsHelper().sendRequest(_id))
if (!await GroupsHelper().sendRequest(_id)) {
showSimpleSnack(context, tr("Could not send your membership request!"));
else {
if (this.widget.onError != null) this.widget.onError();
} else {
// Refresh state
group.membershipLevel = GroupMembershipLevel.PENDING;
this.setState(() {});

View File

@ -16,6 +16,7 @@ enum BarCallbackActions {
OPEN_FRIENDS,
OPEN_MY_PAGE,
OPEN_GROUPS,
OPEN_GROUP_PAGE,
OPEN_APP_SETTINGS,
NONE,
ACTION_LOGOUT