mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Add user profile route
This commit is contained in:
		
							
								
								
									
										175
									
								
								lib/forez/ui/routes/forez_member_profile_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								lib/forez/ui/routes/forez_member_profile_route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					import 'package:cached_network_image/cached_network_image.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/forez/helpers/forez_group_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/forez_groups_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/forez_presence_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/lists/forez_presences_set.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/advanced_user_info.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/displayed_content.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/widgets/copy_icon.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/widgets/forez_presence_calendar_widget.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/widgets/text_widget.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:url_launcher/url_launcher.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Show information about a Forez member
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForezMemberProfileRoute extends StatefulWidget {
 | 
				
			||||||
 | 
					  final int userID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ForezMemberProfileRoute({
 | 
				
			||||||
 | 
					    Key key,
 | 
				
			||||||
 | 
					    @required this.userID,
 | 
				
			||||||
 | 
					  })  : assert(userID != null),
 | 
				
			||||||
 | 
					        super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  _ForezMemberProfileRouteState createState() =>
 | 
				
			||||||
 | 
					      _ForezMemberProfileRouteState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _ForezMemberProfileRouteState extends State<ForezMemberProfileRoute> {
 | 
				
			||||||
 | 
					  final double _appBarHeight = 256.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final _key = GlobalKey<AsyncScreenWidgetState>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  AdvancedUserInfo _user;
 | 
				
			||||||
 | 
					  PresenceSet _presence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> _load() async {
 | 
				
			||||||
 | 
					    _user = await ForezGroupsHelper.getMemberInfo(forezGroup.id, widget.userID);
 | 
				
			||||||
 | 
					    _presence =
 | 
				
			||||||
 | 
					        await ForezPresenceHelper.getForUser(forezGroup.id, widget.userID);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) => AsyncScreenWidget(
 | 
				
			||||||
 | 
					      onReload: _load,
 | 
				
			||||||
 | 
					      onBuild: _buildProfile,
 | 
				
			||||||
 | 
					      loadingWidget: _buildLoading(),
 | 
				
			||||||
 | 
					      errorWidget: _buildError(),
 | 
				
			||||||
 | 
					      errorMessage: tr(
 | 
				
			||||||
 | 
					          "Failed to load user information, maybe it is not a Forez member yet?"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildLoading() => Scaffold(
 | 
				
			||||||
 | 
					        appBar: AppBar(
 | 
				
			||||||
 | 
					          title: Text(tr("Loading...")),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        body: buildCenteredProgressBar(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildError() => Scaffold(
 | 
				
			||||||
 | 
					        appBar: AppBar(
 | 
				
			||||||
 | 
					          title: Text(tr("Error")),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        body: buildErrorCard(
 | 
				
			||||||
 | 
					            tr("Failed to load user information, maybe it is not a Forez member yet?"),
 | 
				
			||||||
 | 
					            actions: [
 | 
				
			||||||
 | 
					              MaterialButton(
 | 
				
			||||||
 | 
					                onPressed: () => _key.currentState.refresh(),
 | 
				
			||||||
 | 
					                child: Text(tr("Try again")),
 | 
				
			||||||
 | 
					                textColor: Colors.white,
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					            ]),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildProfile() => Scaffold(
 | 
				
			||||||
 | 
					        body: CustomScrollView(
 | 
				
			||||||
 | 
					          slivers: <Widget>[
 | 
				
			||||||
 | 
					            _buildAppBar(),
 | 
				
			||||||
 | 
					            _buildList(),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildAppBar() => SliverAppBar(
 | 
				
			||||||
 | 
					        expandedHeight: _appBarHeight,
 | 
				
			||||||
 | 
					        pinned: true,
 | 
				
			||||||
 | 
					        flexibleSpace: FlexibleSpaceBar(
 | 
				
			||||||
 | 
					          title: Text(_user.fullName),
 | 
				
			||||||
 | 
					          background: Stack(
 | 
				
			||||||
 | 
					            fit: StackFit.expand,
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              _user.accountImageURL == null
 | 
				
			||||||
 | 
					                  ? Container()
 | 
				
			||||||
 | 
					                  : CachedNetworkImage(
 | 
				
			||||||
 | 
					                      fit: BoxFit.cover,
 | 
				
			||||||
 | 
					                      imageUrl: _user.accountImageURL,
 | 
				
			||||||
 | 
					                      height: _appBarHeight,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					              // This gradient ensures that the toolbar icons are distinct
 | 
				
			||||||
 | 
					              // against the background image.
 | 
				
			||||||
 | 
					              const DecoratedBox(
 | 
				
			||||||
 | 
					                decoration: BoxDecoration(
 | 
				
			||||||
 | 
					                  gradient: LinearGradient(
 | 
				
			||||||
 | 
					                    begin: Alignment(0.0, -1.0),
 | 
				
			||||||
 | 
					                    end: Alignment(0.0, -0.4),
 | 
				
			||||||
 | 
					                    colors: <Color>[Color(0x60000000), Color(0x00000000)],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildList() => SliverList(
 | 
				
			||||||
 | 
					          delegate: SliverChildListDelegate(<Widget>[
 | 
				
			||||||
 | 
					        // Public note
 | 
				
			||||||
 | 
					        !_user.hasPublicNote
 | 
				
			||||||
 | 
					            ? Container()
 | 
				
			||||||
 | 
					            : ListTile(
 | 
				
			||||||
 | 
					                leading: Icon(Icons.note),
 | 
				
			||||||
 | 
					                title: TextWidget(content: DisplayedString(_user.publicNote)),
 | 
				
			||||||
 | 
					                subtitle: Text(tr("Note")),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Email address
 | 
				
			||||||
 | 
					        !_user.hasEmailAddress
 | 
				
			||||||
 | 
					            ? Container()
 | 
				
			||||||
 | 
					            : ListTile(
 | 
				
			||||||
 | 
					                leading: Icon(Icons.email),
 | 
				
			||||||
 | 
					                title: Text(_user.emailAddress),
 | 
				
			||||||
 | 
					                subtitle: Text(tr("Email address")),
 | 
				
			||||||
 | 
					                trailing: CopyIcon(_user.emailAddress),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Location
 | 
				
			||||||
 | 
					        !_user.hasLocation
 | 
				
			||||||
 | 
					            ? Container()
 | 
				
			||||||
 | 
					            : ListTile(
 | 
				
			||||||
 | 
					                leading: Icon(Icons.location_on),
 | 
				
			||||||
 | 
					                title: Text(_user.location),
 | 
				
			||||||
 | 
					                subtitle: Text(tr("Location")),
 | 
				
			||||||
 | 
					                trailing: CopyIcon(_user.location),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Website
 | 
				
			||||||
 | 
					        !_user.hasPersonalWebsite
 | 
				
			||||||
 | 
					            ? Container()
 | 
				
			||||||
 | 
					            : ListTile(
 | 
				
			||||||
 | 
					                leading: Icon(Icons.link),
 | 
				
			||||||
 | 
					                title: Text(_user.personalWebsite),
 | 
				
			||||||
 | 
					                subtitle: Text(tr("Website")),
 | 
				
			||||||
 | 
					                trailing: IconButton(
 | 
				
			||||||
 | 
					                  icon: Icon(Icons.open_in_new),
 | 
				
			||||||
 | 
					                  onPressed: () => launch(_user.personalWebsite),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Divider(),
 | 
				
			||||||
 | 
					        ListTile(
 | 
				
			||||||
 | 
					          leading: Icon(Icons.calendar_today),
 | 
				
			||||||
 | 
					          title: Text(tr("Presence in Forez")),
 | 
				
			||||||
 | 
					          subtitle: Text(_presence.containsDate(DateTime.now())
 | 
				
			||||||
 | 
					              ? tr("Present today")
 | 
				
			||||||
 | 
					              : tr("Absent")),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        PresenceCalendarWidget(presenceSet: _presence),
 | 
				
			||||||
 | 
					        Divider(),
 | 
				
			||||||
 | 
					      ]));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import 'package:comunic/forez/helpers/forez_group_helper.dart';
 | 
					import 'package:comunic/forez/helpers/forez_group_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/forez/ui/routes/forez_member_profile_route.dart';
 | 
				
			||||||
import 'package:comunic/forez/ui/screens/forez_directory_screen.dart';
 | 
					import 'package:comunic/forez/ui/screens/forez_directory_screen.dart';
 | 
				
			||||||
import 'package:comunic/helpers/events_helper.dart';
 | 
					import 'package:comunic/helpers/events_helper.dart';
 | 
				
			||||||
import 'package:comunic/models/conversation.dart';
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
@@ -72,7 +73,13 @@ class _MainRouteState extends MainController {
 | 
				
			|||||||
  void openGroup(int groupID, {int conversationID}) => _unsupportedFeature();
 | 
					  void openGroup(int groupID, {int conversationID}) => _unsupportedFeature();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void openUserPage(int userID) => _unsupportedFeature();
 | 
					  void openUserPage(int userID) => pushPage(PageInfo(
 | 
				
			||||||
 | 
					        child: ForezMemberProfileRoute(userID: userID),
 | 
				
			||||||
 | 
					        hideNavBar: true,
 | 
				
			||||||
 | 
					        canShowAsDialog: true,
 | 
				
			||||||
 | 
					        type: PageType.USER_PAGE,
 | 
				
			||||||
 | 
					        id: userID,
 | 
				
			||||||
 | 
					      ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void openFriendsList() => _unsupportedFeature();
 | 
					  void openFriendsList() => _unsupportedFeature();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ import 'package:comunic/lists/group_members_list.dart';
 | 
				
			|||||||
import 'package:comunic/lists/users_list.dart';
 | 
					import 'package:comunic/lists/users_list.dart';
 | 
				
			||||||
import 'package:comunic/models/group_membership.dart';
 | 
					import 'package:comunic/models/group_membership.dart';
 | 
				
			||||||
import 'package:comunic/models/user.dart';
 | 
					import 'package:comunic/models/user.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/main_route/main_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
 | 
					import 'package:comunic/ui/widgets/account_image_widget.dart';
 | 
				
			||||||
import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
					import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
				
			||||||
import 'package:comunic/utils/account_utils.dart';
 | 
					import 'package:comunic/utils/account_utils.dart';
 | 
				
			||||||
@@ -123,9 +124,8 @@ class _ForezDirectoryScreenState extends State<ForezDirectoryScreen> {
 | 
				
			|||||||
    if (user != null) _openUserProfile(user);
 | 
					    if (user != null) _openUserProfile(user);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _openUserProfile(User user) {
 | 
					  void _openUserProfile(User user) =>
 | 
				
			||||||
    print("Open user profile ${user.fullName}");
 | 
					      MainController.of(context).openUserPage(user.id);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _ForezMemberTile extends StatelessWidget {
 | 
					class _ForezMemberTile extends StatelessWidget {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
import 'package:comunic/helpers/groups_helper.dart';
 | 
					import 'package:comunic/helpers/groups_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/users_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/advanced_user_info.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';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,4 +16,16 @@ class ForezGroupsHelper {
 | 
				
			|||||||
        .map(GroupsHelper.getGroupFromAPI)
 | 
					        .map(GroupsHelper.getGroupFromAPI)
 | 
				
			||||||
        .toList();
 | 
					        .toList();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Get advanced information about a Forez member
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// This methods throws an exception in case of failure
 | 
				
			||||||
 | 
					  static Future<AdvancedUserInfo> getMemberInfo(int groupID, int userID) async {
 | 
				
			||||||
 | 
					    final response = await APIRequest.withLogin("forez/get_member_info")
 | 
				
			||||||
 | 
					        .addInt("group", groupID)
 | 
				
			||||||
 | 
					        .addInt("user", userID)
 | 
				
			||||||
 | 
					        .execWithThrowGetObject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return UsersHelper.apiToAdvancedUserInfo(response);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -151,36 +151,11 @@ class UsersHelper {
 | 
				
			|||||||
      throw new GetUserAdvancedUserError(cause);
 | 
					      throw new GetUserAdvancedUserError(cause);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    final data = response.getObject();
 | 
					    return apiToAdvancedUserInfo(response.getObject());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return AdvancedUserInfo(
 | 
					 | 
				
			||||||
      id: data["userID"],
 | 
					 | 
				
			||||||
      firstName: data["firstName"],
 | 
					 | 
				
			||||||
      lastName: data["lastName"],
 | 
					 | 
				
			||||||
      pageVisibility: data["publicPage"] == "false"
 | 
					 | 
				
			||||||
          ? UserPageVisibility.PRIVATE
 | 
					 | 
				
			||||||
          : (data["openPage"] == "false"
 | 
					 | 
				
			||||||
              ? UserPageVisibility.PRIVATE
 | 
					 | 
				
			||||||
              : UserPageVisibility.OPEN),
 | 
					 | 
				
			||||||
      virtualDirectory:
 | 
					 | 
				
			||||||
          data["virtualDirectory"] == "" ? null : data["virtualDirectory"],
 | 
					 | 
				
			||||||
      accountImageURL: data["accountImage"],
 | 
					 | 
				
			||||||
      emailAddress: data["email_address"],
 | 
					 | 
				
			||||||
      customEmojies: _parseCustomEmojies(data["customEmojis"]),
 | 
					 | 
				
			||||||
      publicNote: data["publicNote"],
 | 
					 | 
				
			||||||
      canPostTexts: data["can_post_texts"],
 | 
					 | 
				
			||||||
      isFriendsListPublic: data["friend_list_public"],
 | 
					 | 
				
			||||||
      numberFriends: data["number_friends"],
 | 
					 | 
				
			||||||
      accountCreationTime: data["account_creation_time"],
 | 
					 | 
				
			||||||
      personalWebsite: data["personnalWebsite"],
 | 
					 | 
				
			||||||
      location: data["location"],
 | 
					 | 
				
			||||||
      likes: data["pageLikes"],
 | 
					 | 
				
			||||||
      userLike: data["user_like_page"],
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Parse the list of custom emojies
 | 
					  /// Parse the list of custom emojies
 | 
				
			||||||
  CustomEmojiesList _parseCustomEmojies(List<dynamic> list) {
 | 
					  static CustomEmojiesList _parseCustomEmojies(List<dynamic> list) {
 | 
				
			||||||
    final l = list.cast<Map<String, dynamic>>();
 | 
					    final l = list.cast<Map<String, dynamic>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return CustomEmojiesList()
 | 
					    return CustomEmojiesList()
 | 
				
			||||||
@@ -193,4 +168,30 @@ class UsersHelper {
 | 
				
			|||||||
              ))
 | 
					              ))
 | 
				
			||||||
          .toList());
 | 
					          .toList());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static AdvancedUserInfo apiToAdvancedUserInfo(Map<String, dynamic> data) =>
 | 
				
			||||||
 | 
					      AdvancedUserInfo(
 | 
				
			||||||
 | 
					        id: data["userID"],
 | 
				
			||||||
 | 
					        firstName: data["firstName"],
 | 
				
			||||||
 | 
					        lastName: data["lastName"],
 | 
				
			||||||
 | 
					        pageVisibility: data["publicPage"] == "false"
 | 
				
			||||||
 | 
					            ? UserPageVisibility.PRIVATE
 | 
				
			||||||
 | 
					            : (data["openPage"] == "false"
 | 
				
			||||||
 | 
					                ? UserPageVisibility.PRIVATE
 | 
				
			||||||
 | 
					                : UserPageVisibility.OPEN),
 | 
				
			||||||
 | 
					        virtualDirectory:
 | 
				
			||||||
 | 
					            data["virtualDirectory"] == "" ? null : data["virtualDirectory"],
 | 
				
			||||||
 | 
					        accountImageURL: data["accountImage"],
 | 
				
			||||||
 | 
					        emailAddress: data["email_address"],
 | 
				
			||||||
 | 
					        customEmojies: _parseCustomEmojies(data["customEmojis"]),
 | 
				
			||||||
 | 
					        publicNote: data["publicNote"],
 | 
				
			||||||
 | 
					        canPostTexts: data["can_post_texts"],
 | 
				
			||||||
 | 
					        isFriendsListPublic: data["friend_list_public"],
 | 
				
			||||||
 | 
					        numberFriends: data["number_friends"],
 | 
				
			||||||
 | 
					        accountCreationTime: data["account_creation_time"],
 | 
				
			||||||
 | 
					        personalWebsite: data["personnalWebsite"],
 | 
				
			||||||
 | 
					        location: data["location"],
 | 
				
			||||||
 | 
					        likes: data["pageLikes"],
 | 
				
			||||||
 | 
					        userLike: data["user_like_page"],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,6 +60,10 @@ class AdvancedUserInfo extends User implements LikeElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  bool get hasPersonalWebsite => personalWebsite.isNotEmpty;
 | 
					  bool get hasPersonalWebsite => personalWebsite.isNotEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get hasEmailAddress => emailAddress != null && emailAddress.isNotEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get hasLocation => location != null && location.isNotEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  LikesType get likeType => LikesType.USER;
 | 
					  LikesType get likeType => LikesType.USER;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,12 +28,24 @@ class AsyncScreenWidget extends StatefulWidget {
 | 
				
			|||||||
  /// Specify whether old data can be kept or not while updating this widget
 | 
					  /// Specify whether old data can be kept or not while updating this widget
 | 
				
			||||||
  final bool showOldDataWhileUpdating;
 | 
					  final bool showOldDataWhileUpdating;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Widget to use while we are refreshing
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// This widget is optional
 | 
				
			||||||
 | 
					  final Widget loadingWidget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Widget to use in case of error
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// This widget is optional
 | 
				
			||||||
 | 
					  final Widget errorWidget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const AsyncScreenWidget({
 | 
					  const AsyncScreenWidget({
 | 
				
			||||||
    Key key,
 | 
					    Key key,
 | 
				
			||||||
    @required this.onReload,
 | 
					    @required this.onReload,
 | 
				
			||||||
    @required this.onBuild,
 | 
					    @required this.onBuild,
 | 
				
			||||||
    @required this.errorMessage,
 | 
					    @required this.errorMessage,
 | 
				
			||||||
    this.showOldDataWhileUpdating = false,
 | 
					    this.showOldDataWhileUpdating = false,
 | 
				
			||||||
 | 
					    this.loadingWidget,
 | 
				
			||||||
 | 
					    this.errorWidget,
 | 
				
			||||||
  })  : assert(onReload != null),
 | 
					  })  : assert(onReload != null),
 | 
				
			||||||
        assert(onBuild != null),
 | 
					        assert(onBuild != null),
 | 
				
			||||||
        assert(errorMessage != null),
 | 
					        assert(errorMessage != null),
 | 
				
			||||||
@@ -59,16 +71,17 @@ class AsyncScreenWidgetState extends SafeState<AsyncScreenWidget> {
 | 
				
			|||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    // In case of error
 | 
					    // In case of error
 | 
				
			||||||
    if (error)
 | 
					    if (error)
 | 
				
			||||||
      return buildErrorCard(widget.errorMessage, actions: [
 | 
					      return widget.errorWidget ??
 | 
				
			||||||
        MaterialButton(
 | 
					          buildErrorCard(widget.errorMessage, actions: [
 | 
				
			||||||
          textColor: Colors.white,
 | 
					            MaterialButton(
 | 
				
			||||||
          onPressed: () => refresh(),
 | 
					              textColor: Colors.white,
 | 
				
			||||||
          child: Text(tr("Try again").toUpperCase()),
 | 
					              onPressed: () => refresh(),
 | 
				
			||||||
        )
 | 
					              child: Text(tr("Try again").toUpperCase()),
 | 
				
			||||||
      ]);
 | 
					            )
 | 
				
			||||||
 | 
					          ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Show loading states
 | 
					    // Show loading states
 | 
				
			||||||
    if (!ready) return buildCenteredProgressBar();
 | 
					    if (!ready) return widget.loadingWidget ?? buildCenteredProgressBar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The widget is ready, show it
 | 
					    // The widget is ready, show it
 | 
				
			||||||
    return RefreshIndicator(
 | 
					    return RefreshIndicator(
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								lib/ui/widgets/copy_icon.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/ui/widgets/copy_icon.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import 'package:clipboard/clipboard.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Icon used to copy content in clipboard
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CopyIcon extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const CopyIcon(this.value) : assert(value != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return IconButton(
 | 
				
			||||||
 | 
					      icon: Icon(Icons.content_copy),
 | 
				
			||||||
 | 
					      onPressed: () {
 | 
				
			||||||
 | 
					        FlutterClipboard.copy(value);
 | 
				
			||||||
 | 
					        snack(context, tr("'%c%' was copied to clipboard", args: {"c": value}));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user