mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-26 06:49:22 +00:00
Display the list of friends of the user
This commit is contained in:
parent
3109f7c482
commit
5021ded039
38
lib/helpers/friends_helper.dart
Normal file
38
lib/helpers/friends_helper.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:comunic/lists/friends_list.dart';
|
||||||
|
import 'package:comunic/models/api_request.dart';
|
||||||
|
import 'package:comunic/models/friend.dart';
|
||||||
|
|
||||||
|
/// Friends helper
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class FriendsHelper {
|
||||||
|
/// Get the list of friends of the user
|
||||||
|
///
|
||||||
|
/// Returns the list of friends in case of success, or null if an error
|
||||||
|
/// occurred
|
||||||
|
Future<FriendsList> downloadList() async {
|
||||||
|
final response = await APIRequest(
|
||||||
|
uri: "friends/getList",
|
||||||
|
needLogin: true,
|
||||||
|
args: {
|
||||||
|
"complete": "true",
|
||||||
|
},
|
||||||
|
).exec();
|
||||||
|
|
||||||
|
if (response.code != 200) return null;
|
||||||
|
|
||||||
|
// Parse and return the list of friends
|
||||||
|
FriendsList list = FriendsList();
|
||||||
|
response.getArray().forEach((f) =>
|
||||||
|
list.add(Friend(
|
||||||
|
id: f["ID_friend"],
|
||||||
|
accepted: f["accepted"] == 1,
|
||||||
|
lastActive: f["time_last_activity"],
|
||||||
|
following: f["following"] == 1,
|
||||||
|
canPostTexts: f["canPostTexts"],),),
|
||||||
|
);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
24
lib/lists/friends_list.dart
Normal file
24
lib/lists/friends_list.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:comunic/models/friend.dart';
|
||||||
|
|
||||||
|
/// List of friends of the user
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class FriendsList extends ListBase<Friend> {
|
||||||
|
List<Friend> _list = List();
|
||||||
|
|
||||||
|
int get length => _list.length;
|
||||||
|
|
||||||
|
set length(int length) => _list.length = length;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Friend operator [](int index) => _list[index];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void operator []=(int index, Friend value) => _list[index] = value;
|
||||||
|
|
||||||
|
/// Get the ID of all the friends of the current user
|
||||||
|
List<int> get usersId => map((f) => f.id).toList();
|
||||||
|
}
|
29
lib/models/friend.dart
Normal file
29
lib/models/friend.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:comunic/utils/date_utils.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
/// Single user Friend information
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class Friend {
|
||||||
|
final int id;
|
||||||
|
final bool accepted;
|
||||||
|
final int lastActive;
|
||||||
|
final bool following;
|
||||||
|
final bool canPostTexts;
|
||||||
|
|
||||||
|
Friend({
|
||||||
|
@required this.id,
|
||||||
|
@required this.accepted,
|
||||||
|
@required this.lastActive,
|
||||||
|
@required this.following,
|
||||||
|
@required this.canPostTexts,
|
||||||
|
}) : assert(id != null),
|
||||||
|
assert(accepted != null),
|
||||||
|
assert(lastActive != null),
|
||||||
|
assert(following != null),
|
||||||
|
assert(canPostTexts != null);
|
||||||
|
|
||||||
|
/// Check out whether friend is connected or not
|
||||||
|
bool get isConnected => time() - 30 < lastActive;
|
||||||
|
}
|
@ -31,6 +31,9 @@ class User extends CacheModel {
|
|||||||
/// Get user full name
|
/// Get user full name
|
||||||
String get fullName => firstName + " " + lastName;
|
String get fullName => firstName + " " + lastName;
|
||||||
|
|
||||||
|
/// Get user display name
|
||||||
|
String get displayName => fullName; //TODO : support HTML characters (eg: É => é)
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return {
|
return {
|
||||||
UserTableContract.C_ID: id,
|
UserTableContract.C_ID: id,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
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/menus_screen.dart';
|
import 'package:comunic/ui/screens/menus_screen.dart';
|
||||||
import 'package:comunic/ui/tiles/custom_bottom_navigation_bar_item.dart';
|
import 'package:comunic/ui/tiles/custom_bottom_navigation_bar_item.dart';
|
||||||
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// Main route of the application
|
/// Main route of the application
|
||||||
@ -52,6 +54,9 @@ class _HomeRouteState extends State<HomeRoute> {
|
|||||||
return ConversationsListScreen();
|
return ConversationsListScreen();
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
return FriendsListScreen();
|
||||||
|
|
||||||
|
case 2:
|
||||||
return MenuScreen();
|
return MenuScreen();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -64,11 +69,15 @@ class _HomeRouteState extends State<HomeRoute> {
|
|||||||
return <BottomNavigationBarItem>[
|
return <BottomNavigationBarItem>[
|
||||||
CustomNavigationBarItem(
|
CustomNavigationBarItem(
|
||||||
icon: Icon(Icons.chat),
|
icon: Icon(Icons.chat),
|
||||||
title: Text("Conversations"),
|
title: Text(tr("Conversations")),
|
||||||
|
),
|
||||||
|
CustomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.group),
|
||||||
|
title: Text(tr("Friends")),
|
||||||
),
|
),
|
||||||
CustomNavigationBarItem(
|
CustomNavigationBarItem(
|
||||||
icon: Icon(Icons.menu),
|
icon: Icon(Icons.menu),
|
||||||
title: Text("Menu"),
|
title: Text(tr("Menu")),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
122
lib/ui/screens/friends_list_screen.dart
Normal file
122
lib/ui/screens/friends_list_screen.dart
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import 'package:comunic/helpers/friends_helper.dart';
|
||||||
|
import 'package:comunic/helpers/users_helper.dart';
|
||||||
|
import 'package:comunic/lists/friends_list.dart';
|
||||||
|
import 'package:comunic/lists/users_list.dart';
|
||||||
|
import 'package:comunic/ui/tiles/accepted_friend_tile.dart';
|
||||||
|
import 'package:comunic/ui/tiles/pending_friend_tile.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';
|
||||||
|
|
||||||
|
/// Friends list screen
|
||||||
|
///
|
||||||
|
/// Display the list of friends of the current user
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
enum _ErrorsLevel { NONE, MINOR, MAJOR }
|
||||||
|
|
||||||
|
class FriendsListScreen extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _FriendsListScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FriendsListScreenState extends SafeState<FriendsListScreen> {
|
||||||
|
/// Helpers
|
||||||
|
final _friendsHelper = FriendsHelper();
|
||||||
|
final _usersHelper = UsersHelper();
|
||||||
|
|
||||||
|
/// Widget members
|
||||||
|
_ErrorsLevel _error = _ErrorsLevel.NONE;
|
||||||
|
FriendsList _friendsList;
|
||||||
|
UsersList _usersInfo;
|
||||||
|
bool _loading = true;
|
||||||
|
|
||||||
|
/// Useful setters
|
||||||
|
set error(_ErrorsLevel err) => setState(() => _error = err);
|
||||||
|
|
||||||
|
set loading(bool loading) => setState(() => _loading = loading);
|
||||||
|
|
||||||
|
void _gotError() =>
|
||||||
|
error = _friendsList == null ? _ErrorsLevel.MAJOR : _ErrorsLevel.MINOR;
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
_loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load the list of friends
|
||||||
|
Future<void> _loadList() async {
|
||||||
|
error = _ErrorsLevel.NONE;
|
||||||
|
loading = true;
|
||||||
|
|
||||||
|
// Get the list of friends
|
||||||
|
final list = await _friendsHelper.downloadList();
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (list == null) return _gotError();
|
||||||
|
|
||||||
|
// Get information about related users
|
||||||
|
final users = await _usersHelper.getUsersInfo(list.usersId);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (users == null) return _gotError();
|
||||||
|
|
||||||
|
// Apply new information
|
||||||
|
setState(() {
|
||||||
|
_friendsList = list;
|
||||||
|
_usersInfo = users;
|
||||||
|
});
|
||||||
|
loading = false;
|
||||||
|
error = _ErrorsLevel.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build and return loading error
|
||||||
|
Widget _buildError() =>
|
||||||
|
buildErrorCard(
|
||||||
|
tr("Could not load your list of friends!"),
|
||||||
|
actions: [
|
||||||
|
FlatButton(
|
||||||
|
onPressed: _loadList,
|
||||||
|
child: Text(
|
||||||
|
tr("Retry").toUpperCase(),
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (_error == _ErrorsLevel.MAJOR) return _buildError();
|
||||||
|
if (_friendsList == null) return buildCenteredProgressBar();
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
Container(child: _error != _ErrorsLevel.NONE ? _buildError() : null),
|
||||||
|
|
||||||
|
// Check if loading
|
||||||
|
Container(child: _loading ? CircularProgressIndicator() : null),
|
||||||
|
|
||||||
|
// List of friends
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(itemCount: _friendsList.length, itemBuilder: (c, i) =>
|
||||||
|
_friendsList[i].accepted ? AcceptedFriendTile(
|
||||||
|
friend: _friendsList[i],
|
||||||
|
user: _usersInfo.getUser(_friendsList[i].id),
|
||||||
|
) : PendingFriendTile(
|
||||||
|
friend: _friendsList[i],
|
||||||
|
user: _usersInfo.getUser(_friendsList[i].id),
|
||||||
|
onRespond: (friend, accept){},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
39
lib/ui/tiles/accepted_friend_tile.dart
Normal file
39
lib/ui/tiles/accepted_friend_tile.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:comunic/models/friend.dart';
|
||||||
|
import 'package:comunic/models/user.dart';
|
||||||
|
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||||
|
import 'package:comunic/utils/date_utils.dart';
|
||||||
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Accepted friend tile
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
class AcceptedFriendTile extends StatelessWidget {
|
||||||
|
final Friend friend;
|
||||||
|
final User user;
|
||||||
|
|
||||||
|
const AcceptedFriendTile(
|
||||||
|
{Key key, @required this.friend, @required this.user})
|
||||||
|
: assert(friend != null),
|
||||||
|
assert(user != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
leading: AccountImageWidget(user: user),
|
||||||
|
title: Text(user.displayName),
|
||||||
|
subtitle: friend.isConnected
|
||||||
|
? Text(
|
||||||
|
tr(
|
||||||
|
"Online",
|
||||||
|
),
|
||||||
|
style: TextStyle(color: Colors.green),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
diffTimeFromNowToStr(friend.lastActive),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
64
lib/ui/tiles/pending_friend_tile.dart
Normal file
64
lib/ui/tiles/pending_friend_tile.dart
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import 'package:comunic/models/friend.dart';
|
||||||
|
import 'package:comunic/models/user.dart';
|
||||||
|
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||||
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Pending friend tile
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
typedef RespondFriendshipRequestCallback = void Function(Friend, bool);
|
||||||
|
|
||||||
|
class PendingFriendTile extends StatelessWidget {
|
||||||
|
final Friend friend;
|
||||||
|
final User user;
|
||||||
|
final RespondFriendshipRequestCallback onRespond;
|
||||||
|
|
||||||
|
const PendingFriendTile(
|
||||||
|
{Key key,
|
||||||
|
@required this.friend,
|
||||||
|
@required this.user,
|
||||||
|
@required this.onRespond})
|
||||||
|
: assert(friend != null),
|
||||||
|
assert(user != null),
|
||||||
|
assert(onRespond != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
leading: AccountImageWidget(
|
||||||
|
user: user,
|
||||||
|
),
|
||||||
|
isThreeLine: true,
|
||||||
|
title: Text(user.fullName),
|
||||||
|
subtitle: Container(
|
||||||
|
height: 30.0,
|
||||||
|
margin: EdgeInsets.only(top: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
FlatButton(
|
||||||
|
child: Text(
|
||||||
|
tr("Accept").toUpperCase(),
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
color: Colors.green,
|
||||||
|
onPressed: () => onRespond(friend, true),
|
||||||
|
),
|
||||||
|
Container(width: 8.0,),
|
||||||
|
FlatButton(
|
||||||
|
child: Text(
|
||||||
|
tr("Reject").toUpperCase(),
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
color: Colors.red,
|
||||||
|
onPressed: () => onRespond(friend, false),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
lib/ui/widgets/safe_state.dart
Normal file
13
lib/ui/widgets/safe_state.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Little State hack to avoid issues
|
||||||
|
///
|
||||||
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
|
abstract class SafeState<T extends StatefulWidget> extends State<T> {
|
||||||
|
@override
|
||||||
|
void setState(fn) {
|
||||||
|
if(mounted)
|
||||||
|
super.setState(fn);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user